Re: [PATCH 1/2] t3404: fix another typo

2016-06-29 Thread Pranit Bauva
Hey Johannes,

Very minor nits.

On Wed, Jun 29, 2016 at 8:01 PM, Johannes Schindelin
 wrote:
> The past tense of "to run" is "run", not "ran".

Past tense of "to run" is "ran" while past participle is "to run".

Past tense: He ran.
Past Participle: He has to run.

> Signed-off-by: Johannes Schindelin 
> ---
>  t/t3404-rebase-interactive.sh | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
> index 66348f1..c7ea8ba 100755
> --- a/t/t3404-rebase-interactive.sh
> +++ b/t/t3404-rebase-interactive.sh
> @@ -60,7 +60,7 @@ test_expect_success 'setup' '
> test_commit P fileP
>  '
>
> -# "exec" commands are ran with the user shell by default, but this may

This sentence seems to be in present tense if I am not wrong (though I
am not a native English speaker).

> +# "exec" commands are run with the user shell by default, but this may
>  # be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work
>  # to create a file. Unsetting SHELL avoids such non-portable behavior
>  # in tests. It must be exported for it to take effect where needed.

The change introduces fixed the grammo properly but the commit message
probably reports it incorrectly.

Would it be better if the commit message is without changing anything else:
 The present tense of "to run" is "run", not "ran".

Regards,
Pranit Bauva
--
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


git pull --rebase should use fast forward merge if possible

2016-06-29 Thread neuling
Hi, 

since I have added "pull.rebase=preserve" to my global configuration I 
wonder why "git pull" also trys to rebase if a fast forward merge is 
possible. 

A fast forward merge would speed up every pull if your local branch 
contains no new commits and the remote branch is ahead. The result would 
be the same. 

Is it possible to change the behavior of "git pull 
--rebase=true|preserve|interactive" to use a fast forward merge if the 
remote branch is ahead and the local branch contains no new commits? 


Regards, 
Mattias 
--
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: git pull --rebase should use fast forward merge if possible

2016-06-29 Thread Junio C Hamano
neul...@dakosy.de writes:

> since I have added "pull.rebase=preserve" to my global configuration I 
> wonder why "git pull" also trys to rebase if a fast forward merge is 
> possible. 
>
> A fast forward merge would speed up every pull if your local branch 
> contains no new commits and the remote branch is ahead. The result would 
> be the same. 
>
> Is it possible to change the behavior of "git pull 
> --rebase=true|preserve|interactive" to use a fast forward merge if the 
> remote branch is ahead and the local branch contains no new commits? 

Interesting.  I do not think of a reason why we shouldn't.

If we were still working in scripted Porcelain, it would have been a
five minute hack, perhaps like this.

 contrib/examples/git-pull.sh | 8 
 1 file changed, 8 insertions(+)

diff --git a/contrib/examples/git-pull.sh b/contrib/examples/git-pull.sh
index 6b3a03f..3648040 100755
--- a/contrib/examples/git-pull.sh
+++ b/contrib/examples/git-pull.sh
@@ -358,6 +358,14 @@ fi
 
 if test true = "$rebase"
 then
+   if git merge-base --is-ancestor "$orig_head" "$merge_head"
+   then
+   # We can just fast-forward, as "git rebase --no-ff"
+   # is nonsense.
+   git merge --ff-only "$merge_head"
+   exit
+   fi
+
o=$(git show-branch --merge-base $curr_branch $merge_head $oldremoteref)
if test "$oldremoteref" = "$o"
then
--
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] Refactor recv_sideband()

2016-06-29 Thread Junio C Hamano
Nicolas Pitre  writes:

> To make it clearer, here's a patch on top of pu that fixes all the 
> issues I think are remaining. All tests pass now.
>
> diff --git a/sideband.c b/sideband.c
> index 36a032f..0e6c6df 100644
> --- a/sideband.c
> +++ b/sideband.c
> @@ -23,10 +23,8 @@ int recv_sideband(const char *me, int in_stream, int out)
>   const char *term, *suffix;
>   char buf[LARGE_PACKET_MAX + 1];
>   struct strbuf outbuf = STRBUF_INIT;
> - const char *b, *brk;
>   int retval = 0;
>  
> - strbuf_addf(&outbuf, "%s", PREFIX);
>   term = getenv("TERM");
>   if (isatty(2) && term && strcmp(term, "dumb"))
>   suffix = ANSI_SUFFIX;
> @@ -34,14 +32,15 @@ int recv_sideband(const char *me, int in_stream, int out)
>   suffix = DUMB_SUFFIX;
>  
>   while (!retval) {
> + const char *b, *brk;
>   int band, len;
>   len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX, 
> 0);
>   if (len == 0)
>   break;
>   if (len < 1) {
>   strbuf_addf(&outbuf,
> - "\n%s: protocol error: no band 
> designator\n",
> - me);
> + "%s%s: protocol error: no band designator",
> + outbuf.len ? "\n" : "", me);

OK, because you no longer put PREFIX in outbuf, outbuf.len becomes
an easy way to tell if we have anything accumulated, and if there
already is something, we separate our message from it with a LF.

I like the simplicity and clarity of the logic.

> @@ -50,7 +49,8 @@ int recv_sideband(const char *me, int in_stream, int out)
>   len--;
>   switch (band) {
>   case 3:
> - strbuf_addf(&outbuf, "\n%s%s\n", PREFIX, buf + 1);
> + strbuf_addf(&outbuf, "%s%s%s", outbuf.len ? "\n" : "",
> + PREFIX, buf + 1);

Likewise for all other changes.

> - if (outbuf.len)
> + if (outbuf.len) {
> + strbuf_addf(&outbuf, "\n");
>   fwrite(outbuf.buf, 1, outbuf.len, stderr);
> + }

... and this does make sense.

Lukas, can you see what is in 'pu' after I push out today's
integration result in several hours and tell us if you like the
result of the SQUASH??? change?

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: preview: What's cooking in git.git (Jun 2016, #10; Tue, 28)

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> On Tue, 28 Jun 2016, Junio C Hamano wrote:
>
>> * jk/ansi-color (2016-06-23) 7 commits
>>   (merged to 'next' on 2016-06-28 at 354989c)
>>  + color: support strike-through attribute
>>  + color: support "italic" attribute
>>  + color: allow "no-" for negating attributes
>>  + color: refactor parse_attr
>>  + add skip_prefix_mem helper
>>  + doc: refactor description of color format
>>  + color: fix max-size comment
>> 
>>  The output coloring scheme learned two new attributes, italic and
>>  strike, in addition to existing bold, reverse, etc.
>> 
>>  Will merge to 'master'.
>
> Please note that those "colors" do not work on Windows, at least as far as
> I know, I only skimmed the code in set_attr():
>
>   https://github.com/git/git/blob/v2.9.0/compat/winansi.c#L175-L314
>
> ... and it looks as if italic is plainly unsupported, and strike-through
> is not handled.

This hopefully is a low-hanging-fruit for aspiring new developers in
the Windows land, perhaps?

We do not use italic/strike as a built-in default style for
anything, so we do not have to wait for Windows support of these two
attributes to appear to include this topic in the next release.

After all, users on "screen", or anything that translates these ANSI
colors via termcap/terminfo, do not get them, either.  A user may
try using these once, notices that her terminal lacks support, and
would move on.

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] t/Makefile: add a rule to re-run previously-failed tests

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> While developing patch series, it is a good practice to run the test
> suite from time to time, just to make sure that obvious bugs are caught
> early. With complex patch series, it is common to run `make -j15 -k
> test`, i.e. run the tests in parallel and not stop at the first failing
> test but continue.

Hmmm, my tests run in parallel and do not stop at the first one
without '-k'.  What are we doing differently?

> It is the most convenient way to determine which tests failed after
> running the entire test suite, in parallel, to look for left-over "trash
> directory.t*" subdirectories in the t/ subdirectory.

Good idea, but I'd drop "in the t/ subdirectory" from the
description.

> +failed: $(patsubst trash,,$(patsubst directory.%,%.sh,$(wildcard trash\ 
> directory.t[0-9]*)))
> +

This would not work if you use --root= in GIT_TEST_OPTS, I am
afraid.
--
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: git pull --rebase should use fast forward merge if possible

2016-06-29 Thread Junio C Hamano
Junio C Hamano  writes:

>> Is it possible to change the behavior of "git pull 
>> --rebase=true|preserve|interactive" to use a fast forward merge if the 
>> remote branch is ahead and the local branch contains no new commits? 
>
> Interesting.  I do not think of a reason why we shouldn't.
>
> If we were still working in scripted Porcelain, it would have been a
> five minute hack, perhaps like this.
>
>  contrib/examples/git-pull.sh | 8 
>  1 file changed, 8 insertions(+)

... and if we have to work with built-ins, it becomes a lot larger
than a five-minute hack, unfortunately.

Something like this may have a chance of working ;-)

 builtin/pull.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/builtin/pull.c b/builtin/pull.c
index bf3fd3f..777ae56 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -878,10 +878,24 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
if (merge_heads.nr > 1)
die(_("Cannot merge multiple branches into empty 
head."));
return pull_into_void(*merge_heads.sha1, curr_head);
-   } else if (opt_rebase) {
-   if (merge_heads.nr > 1)
-   die(_("Cannot rebase onto multiple branches."));
+   }
+   if (opt_rebase && merge_heads.nr > 1)
+   die(_("Cannot rebase onto multiple branches."));
+
+   if (opt_rebase) {
+   struct commit_list *list = NULL;
+   struct commit *merge_head, *head;
+
+   head = lookup_commit_reference(orig_head);
+   commit_list_insert(head, &list);
+   merge_head = lookup_commit_reference(merge_heads.sha1[0]);
+   if (is_descendant_of(merge_head, list)) {
+   /* we can fast-forward this without invoking rebase */
+   opt_ff = "--ff-only";
+   return run_merge();
+   }
return run_rebase(curr_head, *merge_heads.sha1, 
rebase_fork_point);
-   } else
+   }
+   else
return run_merge();
 }
--
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 9/9] am: make a direct call to merge_recursive

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> From: Junio C Hamano 

Did I write this thing?

Having two sets of numbers that illustrated that this is not really
a useful optimization in the bigger picture looks vaguely familiar
(e.g. $gmane/279417), but the numbers are different.

>   It feels *slightly* wrong to submit your own patch to review,
>   however, please keep in mind that
>
>   1) I changed the patch (o.gently does not exist anymore, so I do
>  not set it), and
>
>   2) I added my own timings performed on Windows.

It probably is much less confusing if you take the authorship,
possibly with a passing reference to whatever I wrote as the source
of inspiration in the log message, or something.  I do not think I
deserve a credit in this 9-patch series.

I haven't read the other 8 patches, so I cannot comment on it yet.

>  builtin/am.c | 27 ++-
>  1 file changed, 14 insertions(+), 13 deletions(-)
>
> diff --git a/builtin/am.c b/builtin/am.c
> index 3dfe70b..dd41154 100644
> --- a/builtin/am.c
> +++ b/builtin/am.c
> @@ -1587,25 +1587,26 @@ static int run_fallback_merge_recursive(const struct 
> am_state *state,
>   unsigned char *our_tree,
>   unsigned char *his_tree)
>  {
> - struct child_process cp = CHILD_PROCESS_INIT;
> + const unsigned char *bases[1] = {orig_tree};
> + struct merge_options o;
> + struct commit *result;
> + char *his_tree_name;
>   int status;
>  
> - cp.git_cmd = 1;
> + init_merge_options(&o);
> +
> + o.branch1 = "HEAD";
> + his_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
> + o.branch2 = his_tree_name;
>  
> - argv_array_pushf(&cp.env_array, "GITHEAD_%s=%.*s",
> -  sha1_to_hex(his_tree), linelen(state->msg), 
> state->msg);
>   if (state->quiet)
> - argv_array_push(&cp.env_array, "GIT_MERGE_VERBOSITY=0");
> + o.verbosity = 0;
>  
> - argv_array_push(&cp.args, "merge-recursive");
> - argv_array_push(&cp.args, sha1_to_hex(orig_tree));
> - argv_array_push(&cp.args, "--");
> - argv_array_push(&cp.args, sha1_to_hex(our_tree));
> - argv_array_push(&cp.args, sha1_to_hex(his_tree));
> + status = merge_recursive_generic(&o, our_tree, his_tree, 1, bases, 
> &result);
> + if (status < 0)
> + exit(128);
> + free(his_tree_name);
>  
> - status = run_command(&cp) ? (-1) : 0;
> - discard_cache();
> - read_cache();
>   return status;
>  }
--
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] Use skip_blank_lines() for more commit messages

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> It occurred to me that there might be more code locations where finding
> the commit object's body is hand-rolled, and could benefit from using
> the skip_blank_lines() function to handle not-quite-standard but
> still-allowed objects from being processed correctly.

Thanks for following up on this one.  We could have left them as
low-hanging-fruit for new people, but doing these ourselves while
we still remember is a good idea.
--
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 1/2] t3404: fix another typo

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> On Wed, 29 Jun 2016, Junio C Hamano wrote:
>
>> Johannes Schindelin  writes:
>> 
>> > The past tense of "to run" is "run", not "ran".
>> 
>> Actually, past tense of the verb "to run" is "ran" ;-) The reason
>> why this patch is still correct is because this is writing in
>> passive voice, where you want "be + past participle", and the past
>> participle of the verb "to run" is "run".
>
> Embarrassing! ;-)
>
> Well, I shall fix up the commit message thusly:
>
> t3404: fix another typo
>
> The passive form of "to run" is "run", not "ran".

If your convention of referring to a verb is to show its infinitive
form, i.e. "to run", then you would probably want to say

The passive from of "to run" is "to be run", not "to be
ran".

But I think we do not need any of this if we just retitled it to

Subject: t3404: fix a grammo (commands are ran -> commands are run)

without any body.



--
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 1/9] Report bugs consistently

2016-06-29 Thread Eric Sunshine
On Wed, Jun 29, 2016 at 7:36 AM, Johannes Schindelin
 wrote:
> The vast majority of error messages in Git's source code which report a
> bug use the convention to prefix the message with "BUG:".
> [...]
> Signed-off-by: Johannes Schindelin 
> ---
> diff --git a/merge-recursive.c b/merge-recursive.c
> @@ -1853,7 +1852,7 @@ int merge_trees(struct merge_options *o,
> -   die(_("Unprocessed path??? %s"),
> +   die(_("BUG: unprocessed path??? %s"),

This and others downcase the first word (which is consistent with
modern practice)...

> diff --git a/sha1_file.c b/sha1_file.c
> @@ -795,7 +795,7 @@ void close_all_packs(void)
> -   die("BUG! Want to close pack marked 'do-not-close'");
> +   die("BUG: Want to close pack marked 'do-not-close'");

...but this one neglects to.
--
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] t3404: add a test for the --gpg-sign option

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> To keep the time t3404 requires short (in this developer's Windows
> setup, this single test already takes a painful 8 minutes to pass),
> we avoid a full-blown GPG test and cop out by verifying the message
> displayed to the user upon an 'edit' command.

This is a tangent, but I wonder if we should be solving it by
parallelizing the tests even more.  If the script for example
can be split into part1 and part2 that share the same set-up
that is prepared by the very first test, we could split this
into three files (common one that is dot-sourced by two actual
test scripts that have part1 and part2).

>
> Signed-off-by: Johannes Schindelin 
> ---
>  t/t3404-rebase-interactive.sh | 7 +++
>  1 file changed, 7 insertions(+)
>
> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
> index c7ea8ba..4c96075 100755
> --- a/t/t3404-rebase-interactive.sh
> +++ b/t/t3404-rebase-interactive.sh
> @@ -1281,4 +1281,11 @@ test_expect_success 'editor saves as CR/LF' '
>   )
>  '
>  
> +EPIPHANY="'"

Why?  If you really need a variable, SQ is probably the way this
codebase typically spell it.

> +test_expect_success 'rebase -i --gpg-sign=' '
> + set_fake_editor &&
> + FAKE_LINES="edit 1" git rebase -i --gpg-sign=\" HEAD^ >out 2>err &&
> + grep "$EPIPHANY-S\"$EPIPHANY" err

I am not sure what is going on here.  You are asking to sign using
the keyid of a single double-quote, and expecting the message that
says

You can amend the commit now, with

git commit --amend '-S"'

...

that has a substring '-S"' in it to ensure that the codepath to
parse --gpg-sign= on the command line of "rebase", and to the
message we see here are working correctly, without actually checking
if GPG is invoked at all, or if it is invoked the key given by the
option is correctly passed to the invocation?

If so, can't you do that without confusing users by using keyid "?
IOW, wouldn't using --gpg-sign=me work equally well?  For example:

diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 4c96075..2dd3644 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1281,11 +1281,10 @@ test_expect_success 'editor saves as CR/LF' '
)
 '
 
-EPIPHANY="'"
 test_expect_success 'rebase -i --gpg-sign=' '
set_fake_editor &&
-   FAKE_LINES="edit 1" git rebase -i --gpg-sign=\" HEAD^ >out 2>err &&
-   grep "$EPIPHANY-S\"$EPIPHANY" err
+   FAKE_LINES="edit 1" git rebase -i --gpg-sign=me HEAD^ >out 2>err &&
+   grep -e "commit --amend  '\''-Sme'\''" err
 '
 
 test_done
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/9] merge-recursive: clarify code in was_tracked()

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> It can be puzzling to see that was_tracked() tries to match an index
> entry by name even if cache_name_pos() returned a negative value. Let's
> clarify that cache_name_pos() implicitly looks for stage 0, while we are
> also okay with finding other stages.
>
> Signed-off-by: Johannes Schindelin 
> ---
>  merge-recursive.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/merge-recursive.c b/merge-recursive.c
> index 98f4632..bcb53f0 100644
> --- a/merge-recursive.c
> +++ b/merge-recursive.c
> @@ -658,6 +658,7 @@ static int was_tracked(const char *path)
>  {
>   int pos = cache_name_pos(path, strlen(path));
>  
> + /* cache_name_pos() looks for stage == 0, so pos may be < 0 */

It returns >= if found at stage #0, or a negative (counting from -1)
to indicate where the path would be inserted if it were to be added
at stage #0.

The new comment does not explain how "pos may be < 0" leads to
"hence pos = -1 - pos is the right thing to do here".  It is
misleading and we probably are better off without.

>   if (pos < 0)
>   pos = -1 - pos;
>   while (pos < active_nr &&
--
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


topological index field for commit objects

2016-06-29 Thread Marc Strapetz
This is no RFE but rather recurring thoughts whenever I'm working with 
commit graphs: a topological index attribute for commit objects would be 
incredible useful. By "topological index" I mean a simple integer for 
which following condition holds true:


if commit C is part of the history of commit D,
  then C's topological index is smaller than D's index

This would allow topological sorting of commits (e.g. in queues) on the 
fly and quickly give a "no" answer on the question whether D is part of 
C's history.


-Marc

--
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: topological index field for commit objects

2016-06-29 Thread Junio C Hamano
On Wed, Jun 29, 2016 at 11:31 AM, Marc Strapetz
 wrote:
> This is no RFE but rather recurring thoughts whenever I'm working with
> commit graphs: a topological index attribute for commit objects would be
> incredible useful. By "topological index" I mean a simple integer for which
> following condition holds true:

Look for "generation numbers" in the list archive, perhaps?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/9] Prepare the builtins for a libified merge_recursive()

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> A truly libified function does not die() just for fun.

The sentence is wasting bits.  After all, a helper function in
run-once-and-exit program does not die() just for fun, either.

So what's more interesting to know for the readers?

> As such, the
> recursive merge will convert all die() calls to return -1 instead in the
> next commits, giving the caller a chance at least to print some helpful
> message.
>
> Let's prepare the builtins for this fatal error condition, even if we do
> not really do more than imitating the previous die()'s exit(128): this is
> what callers of e.g. `git merge` have come to expect.

One thing missing is your design decision and justification.

For example, the above explanation hints that the original code in
this hunk expected merge_trees() to die() with some useful message
when there is an error condition, but merge_trees() is going to be
improved not to die() itself and return -1 instead to signal an
error, so that the caller can react more flexibly, and this is a
step to prepare for the version of merge_trees() that no longer
dies.

> - merge_trees(&o, new->commit->tree, work,
> + ret = merge_trees(&o, new->commit->tree, work,
>   old->commit->tree, &result);
> + if (ret < 0)
> + exit(128);

The postimage of the patch tells us that the caller is now
responsible for exiting with status 128, but neither the proposed
log message nor the above hunk tells us where the message the
original code must have given to the end user from die() inside
merge_trees().  The updated caller just exits, so a natural guess is
that the calls to die() have been changed to fprintf(stderr) with
the patch.

But that does not mesh very well with the stated objective of the
patch.  The callers want flexibility to do their own error handling,
including giving their own message, so letting merge_trees() to
still write the same message to the standard error stream would not
work well for them.  A caller may want to do merge_trees() just to
see if it succeeds, without wanting to give _any_ indication of that
is happening to the user, because it has an alternate/fallback code
if merge_trees() fails, for example (analogy: "am -3" first tries a
straight patch application before fallking back to 3-way merge; it
may not want to show the error from the first attempt).

The reader _can_ guess that this step ignores the error-message
issue, and improving it later (or keep ignoring that issue) might be
OK in the context of this patch series, but it is necessary to be
upfront to the readers what the design choices were and which one of
those choices the proposed patch adopted as its design for them to
be able to evaluate the patch series correctly.

One design alternative we've seen used in our code to help callers
who want no default messages is to pass struct strbuf &err down the
callchain and collect the default messages without emitting them
directly to the standard error stream when an error is diagnosed.  I
do not know if that pattern is applicable or should be applied to
this codepath.

> Note that the callers of the sequencer (revert and cherry-pick) already
> fail fast even for the return value -1; The only difference is that they
> now get a chance to say " failed".
>
> Signed-off-by: Johannes Schindelin 
> ---
>  builtin/checkout.c | 4 +++-
>  builtin/merge.c| 4 
>  sequencer.c| 4 
>  3 files changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/checkout.c b/builtin/checkout.c
> index c3486bd..14312f7 100644
> --- a/builtin/checkout.c
> +++ b/builtin/checkout.c
> @@ -567,8 +567,10 @@ static int merge_working_tree(const struct checkout_opts 
> *opts,
>   o.ancestor = old->name;
>   o.branch1 = new->name;
>   o.branch2 = "local";
> - merge_trees(&o, new->commit->tree, work,
> + ret = merge_trees(&o, new->commit->tree, work,
>   old->commit->tree, &result);
> + if (ret < 0)
> + exit(128);
>   ret = reset_tree(new->commit->tree, opts, 0,
>writeout_error);
>   if (ret)
> diff --git a/builtin/merge.c b/builtin/merge.c
> index b555a1b..133b853 100644
> --- a/builtin/merge.c
> +++ b/builtin/merge.c
> @@ -682,6 +682,8 @@ static int try_merge_strategy(const char *strategy, 
> struct commit_list *common,
>   hold_locked_index(&lock, 1);
>   clean = merge_recursive(&o, head,
>   remoteheads->item, reversed, &result);
> + if (clean < 0)
> + exit(128);
>   if (active_cache_changed &&
>   write_locked_index(&the_index, &lock, COMMIT_LOCK))
>   die (_("unable t

Re: Fwd: what is a snapshot?

2016-06-29 Thread Jakub Narębski
W dniu 2016-06-19 o 16:15, Ovatta Bianca pisze:

> I read in every comparison of git vs other version control systems,
> that git does not record differences but takes "snapshots"
> I was wondering what a "snapshot" is ? Does git store at every commit
> the entire files which have been modified even if only a few bytes
> were changed out of a large file?

There are two things: the conceptual level, and actual storage. On the
conceptual level, object representing revisions (commit) refer to
object representing top directory (tree) of a project, that is a snapshot
of a project state at given revision.

On the storage level, Git has two types of object storage. In "loose"
format (used for new objects), each object is stored as a separate
file. This is not as wasteful as you think: first, there is deduplication,
that is each version of a file is stored only once. Second, contents
(usually text) is stored compressed.

In "packed" format (nowadays Git automatically repacks from "loose"
to "packed" when it looks like it is needed) there is additional
libxdiff-like deltafication. In this format Git stores differences
(well, it also ensures that delta chain doesn't gets too long).

HTH
-- 
Jakub Narębski

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


[RFD] Place to document magic pathspecs like ":/" and pathspec handling

2016-06-29 Thread Jakub Narębski
Hello,

123456789012345678901234567890123456789012345678901234567890123456789012345|

I have noticed that the magic pathspec ":/" is described only in RelNotes
for revision 1.7.6:

|* A magic pathspec ":/" tells a command that limits its operation to the 
current directory when ran from a subdirectory to work on the entire working 
tree. In general, ":/path/to/file" would be relative to the root of the working 
tree hierarchy. After "git reset --hard; edit Makefile; cd t/", "git add -u" 
would be a no-op, but "git add -u :/" would add the updated contents of the 
Makefile at the top level. If you want to name a path in the current 
subdirectory whose unusual name begins with ":/", you can name it by 
"./:/that/path" or by "\:/that/path".|

||
|I think the reason might be that there was no good place to put that
information in.  Nowadays we have gitcli(7) manual page, but perhaps
it would be better to create a separate manpage for issues related
to pathspec handling (of which ":/" is only one part)... but then
what should it be named?

What do you think?
-- 
Jakub Narębski
|||

--
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: [RFD] Place to document magic pathspecs like ":/" and pathspec handling

2016-06-29 Thread Junio C Hamano
On Wed, Jun 29, 2016 at 12:47 PM, Jakub Narębski  wrote:
>
> I have noticed that the magic pathspec ":/" is described only in RelNotes
> for revision 1.7.6:
> |I think the reason might be that there was no good place to put that
> information in.  Nowadays we have gitcli(7) manual page, but perhaps

$ git help glossary

look for pathspec.
--
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: [RFC/PATCH v2 00/10] Add initial experimental external ODB support

2016-06-29 Thread Eric Wong
Christian Couder  wrote:
> Design discussion about performance
> ~~~
> 
> Yeah, it is not efficient to fork/exec a command to just read or write
> one object to or from the external ODB. Batch calls and/or using a
> daemon and/or RPC should be used instead to be able to store regular
> objects in an external ODB. But for now the external ODB would be all
> about really big files, where the cost of a fork+exec should not
> matter much. If we later want to extend usage of external ODBs, yeah
> we will probably need to design other mechanisms.

I would also investigate switching run_command to use vfork+exec
or posix_spawn for performance (keeping in mind vfork
caveats documented at https://ewontfix.com/7/ )

posix_spawn in future glibc (probably 2.24) will use CLONE_VFORK
in all cases under Linux, and posix_spawn may help with
portability, too.  I think the only thing we can't support
with posix_spawn which run_command supports is chdir;
all the redirections/closing FDs should be fine.

With only 10MB malloc-ed, the following shows vfork performance
being noticeably faster than plain fork:

/* gcc -o vfork-test -Wall -O2 vfork-test.c */
#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[], char *envp[])
{
int i;
int do_vfork = argc > 1 && !strcmp(argv[1], "vfork");
char * const cmd[] = { "/bin/true", 0 };
size_t n = 1024 * 1024 * 10;
char *mem = malloc(n);

memset(mem, 'a', n); /* make sure it's really allocated */

for (i = 0; i < 1; i++) {
pid_t pid = do_vfork ? vfork() : fork();

if (pid == 0) {
execve(cmd[0], cmd, envp);
write(2, "exec error\n", 11);
_exit(1);
}
waitpid(pid, 0, 0);
}
return 0;
}
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/9] merge_recursive: abort properly upon errors

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> There are a couple of places where return values indicating errors
> are ignored. Let's teach them manners.
>
> Signed-off-by: Johannes Schindelin 
> ---
>  merge-recursive.c | 10 --
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/merge-recursive.c b/merge-recursive.c
> index bcb53f0..c4ece96 100644
> --- a/merge-recursive.c
> +++ b/merge-recursive.c
> @@ -1944,8 +1944,9 @@ int merge_recursive(struct merge_options *o,
>   saved_b2 = o->branch2;
>   o->branch1 = "Temporary merge branch 1";
>   o->branch2 = "Temporary merge branch 2";
> - merge_recursive(o, merged_common_ancestors, iter->item,
> - NULL, &merged_common_ancestors);
> + if (merge_recursive(o, merged_common_ancestors, iter->item,
> + NULL, &merged_common_ancestors) < 0)
> + return -1;
>   o->branch1 = saved_b1;
>   o->branch2 = saved_b2;
>   o->call_depth--;

OK, this early return (and others in this patch) are only for
negative (i.e. error) cases, and "attempted a merge, resulted in
conflicts" cases are handled as before.

Which is good.

I wonder if o->branch[12] need to be restored, though.  The only
sensible thing the caller can do is to punt, but would it expect to
be able to do some error reporting based on these fields, e.g.
printf("merge of %s and %s failed", o->branch1, o->branch2) or
something?  In addition to that kind of "state restoration", we may
need to watch out for resource leaks, but I think there is none at
least these three early returns.

Thanks.

> @@ -1961,6 +1962,8 @@ int merge_recursive(struct merge_options *o,
>   o->ancestor = "merged common ancestors";
>   clean = merge_trees(o, h1->tree, h2->tree, 
> merged_common_ancestors->tree,
>   &mrtree);
> + if (clean < 0)
> + return clean;
>  
>   if (o->call_depth) {
>   *result = make_virtual_commit(mrtree, "merged tree");
> @@ -2017,6 +2020,9 @@ int merge_recursive_generic(struct merge_options *o,
>   hold_locked_index(lock, 1);
>   clean = merge_recursive(o, head_commit, next_commit, ca,
>   result);
> + if (clean < 0)
> + return clean;
> +
>   if (active_cache_changed &&
>   write_locked_index(&the_index, lock, COMMIT_LOCK))
>   return error(_("Unable to write index."));
--
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: topological index field for commit objects

2016-06-29 Thread Stefan Beller
On Wed, Jun 29, 2016 at 11:59 AM, Junio C Hamano  wrote:
> On Wed, Jun 29, 2016 at 11:31 AM, Marc Strapetz
>  wrote:
>> This is no RFE but rather recurring thoughts whenever I'm working with
>> commit graphs: a topological index attribute for commit objects would be
>> incredible useful. By "topological index" I mean a simple integer for which
>> following condition holds true:
>
> Look for "generation numbers" in the list archive, perhaps?

Thanks for the pointer to the interesting discussions.

In http://www.spinics.net/lists/git/msg161363.html
Linus wrote in a discussion with Jeff:

> Right now, we do *have* a "generation number". It's just that it's
> very easy to corrupt even by mistake. It's called "committer date". We
> could improve on it.

Would it make sense to refuse creating commits that have a commit date
prior to its parents commit date (except when the user gives a
`--dammit-I-know-I-break-a-wildy-used-heuristic`)?

With the proposal to refuse an earlier committer date we would avoid
the corruption by mistake and only allow for corruption by actual
users intention. And then going forward we could rely more on the
committer date than we do today (i.e. some algorithms can go faster)?
For that we'd
 * need to document, what stuff actually breaks if the user overwrites
the committer date to be earlier
 * and add a switch `--go-slow-because-dates-are-broken`

This seems to be the easiest fix in 2016 to me as that would require
to make just a very small change in commit creation, and we can postpone
the second part (relying even more on dates) until someone wants to fix it?

Thanks,
Stefan

> --
> 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
--
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 5/9] merge-recursive: avoid returning a wholesale struct

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> It is technically allowed, as per C89, for functions' return type to
> be complete structs (i.e. *not* just pointers to structs), but it is
> bad practice.

Not necessarily.

> This is a very late attempt to contain the damage done by this developer
> in 6d297f8 (Status update on merge-recursive in C, 2006-07-08) which
> introduced such a return type.
>
> It will also help the current effort to libify merge-recursive.c, as
> it will allow us to return proper error codes later.

But this part of the motivation does make sense.  Having to pass an
extra int &error_code field, only because the return value is
already used for something else, is a lot more weird.

> Signed-off-by: Johannes Schindelin 
> ---
>  merge-recursive.c | 93 
> ++-
>  1 file changed, 50 insertions(+), 43 deletions(-)
>
> diff --git a/merge-recursive.c b/merge-recursive.c
> index c4ece96..d56651c9 100644
> --- a/merge-recursive.c
> +++ b/merge-recursive.c
> @@ -888,47 +888,47 @@ static int merge_3way(struct merge_options *o,
>   return merge_status;
>  }
>  
> -static struct merge_file_info merge_file_1(struct merge_options *o,
> +static int merge_file_1(struct merge_options *o,
>  const struct diff_filespec *one,
>  const struct diff_filespec *a,
>  const struct diff_filespec *b,
>  const char *branch1,
> -const char *branch2)
> +const char *branch2,
> +struct merge_file_info *result)
>  {
> - struct merge_file_info result;
> - result.merge = 0;
> - result.clean = 1;
> + result->merge = 0;
> + result->clean = 1;
>  
>   if ((S_IFMT & a->mode) != (S_IFMT & b->mode)) {
> - result.clean = 0;
> + result->clean = 0;
>   if (S_ISREG(a->mode)) {
> - result.mode = a->mode;
> - hashcpy(result.sha, a->sha1);
> + result->mode = a->mode;
> + hashcpy(result->sha, a->sha1);
>   } else {
> - result.mode = b->mode;
> - hashcpy(result.sha, b->sha1);
> + result->mode = b->mode;
> + hashcpy(result->sha, b->sha1);
>   }
>   } else {
>   if (!sha_eq(a->sha1, one->sha1) && !sha_eq(b->sha1, one->sha1))
> - result.merge = 1;
> + result->merge = 1;
>  
>   /*
>* Merge modes
>*/
>   if (a->mode == b->mode || a->mode == one->mode)
> - result.mode = b->mode;
> + result->mode = b->mode;
>   else {
> - result.mode = a->mode;
> + result->mode = a->mode;
>   if (b->mode != one->mode) {
> - result.clean = 0;
> - result.merge = 1;
> + result->clean = 0;
> + result->merge = 1;
>   }
>   }
>  
>   if (sha_eq(a->sha1, b->sha1) || sha_eq(a->sha1, one->sha1))
> - hashcpy(result.sha, b->sha1);
> + hashcpy(result->sha, b->sha1);
>   else if (sha_eq(b->sha1, one->sha1))
> - hashcpy(result.sha, a->sha1);
> + hashcpy(result->sha, a->sha1);
>   else if (S_ISREG(a->mode)) {
>   mmbuffer_t result_buf;
>   int merge_status;
> @@ -940,62 +940,63 @@ static struct merge_file_info merge_file_1(struct 
> merge_options *o,
>   die(_("Failed to execute internal merge"));
>  
>   if (write_sha1_file(result_buf.ptr, result_buf.size,
> - blob_type, result.sha))
> + blob_type, result->sha))
>   die(_("Unable to add %s to database"),
>   a->path);
>  
>   free(result_buf.ptr);
> - result.clean = (merge_status == 0);
> + result->clean = (merge_status == 0);
>   } else if (S_ISGITLINK(a->mode)) {
> - result.clean = merge_submodule(result.sha,
> + result->clean = merge_submodule(result->sha,
>  one->path, one->sha1,
>  a->sha1, b->sha1,
>  !o->call_depth);
>   } else if (S_ISLNK(a->mode)) {
> - hashcpy(res

Re: git pull --rebase should use fast forward merge if possible

2016-06-29 Thread Stefan Beller
On Wed, Jun 29, 2016 at 10:23 AM, Junio C Hamano  wrote:
> Junio C Hamano  writes:
>
>>> Is it possible to change the behavior of "git pull
>>> --rebase=true|preserve|interactive" to use a fast forward merge if the
>>> remote branch is ahead and the local branch contains no new commits?
>>
>> Interesting.  I do not think of a reason why we shouldn't.

Me neither.

>>
>> If we were still working in scripted Porcelain, it would have been a
>> five minute hack, perhaps like this.
>>
>>  contrib/examples/git-pull.sh | 8 
>>  1 file changed, 8 insertions(+)
>
> ... and if we have to work with built-ins, it becomes a lot larger
> than a five-minute hack, unfortunately.
>
> Something like this may have a chance of working ;-)
>
>  builtin/pull.c | 22 ++
>  1 file changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/builtin/pull.c b/builtin/pull.c
> index bf3fd3f..777ae56 100644
> --- a/builtin/pull.c
> +++ b/builtin/pull.c
> @@ -878,10 +878,24 @@ int cmd_pull(int argc, const char **argv, const char 
> *prefix)
> if (merge_heads.nr > 1)
> die(_("Cannot merge multiple branches into empty 
> head."));
> return pull_into_void(*merge_heads.sha1, curr_head);
> -   } else if (opt_rebase) {
> -   if (merge_heads.nr > 1)
> -   die(_("Cannot rebase onto multiple branches."));
> +   }
> +   if (opt_rebase && merge_heads.nr > 1)
> +   die(_("Cannot rebase onto multiple branches."));
> +
> +   if (opt_rebase) {
> +   struct commit_list *list = NULL;
> +   struct commit *merge_head, *head;
> +
> +   head = lookup_commit_reference(orig_head);
> +   commit_list_insert(head, &list);
> +   merge_head = lookup_commit_reference(merge_heads.sha1[0]);

The crashes for merge_heads.nr == 0.
(I did not inspect code further up if this is caught before, I think
it would trigger if
you and the remote are on an initial commit with no parents?)

> +   if (is_descendant_of(merge_head, list)) {
> +   /* we can fast-forward this without invoking rebase */
> +   opt_ff = "--ff-only";
> +   return run_merge();
> +   }
> return run_rebase(curr_head, *merge_heads.sha1, 
> rebase_fork_point);
> -   } else
> +   }
> +   else

Keep the style ?

> return run_merge();
>  }
> --
> 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
--
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: git pull --rebase should use fast forward merge if possible

2016-06-29 Thread Junio C Hamano
On Wed, Jun 29, 2016 at 1:40 PM, Stefan Beller  wrote:
>> +   merge_head = lookup_commit_reference(merge_heads.sha1[0]);
>
> The crashes for merge_heads.nr == 0.
> (I did not inspect code further up if this is caught before, I think
> it would trigger if
> you and the remote are on an initial commit with no parents?)

Perhaps you can inspect code before you start typing?

die_no_merge_candidates() would have triggered, I would imagine.

Note that I won't be applying this without test updates and proper log message,
so no need to worry about the style yet ;-)
--
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: topological index field for commit objects

2016-06-29 Thread Junio C Hamano
Stefan Beller  writes:

> On Wed, Jun 29, 2016 at 11:59 AM, Junio C Hamano  wrote:
>> On Wed, Jun 29, 2016 at 11:31 AM, Marc Strapetz
>>  wrote:
>>> This is no RFE but rather recurring thoughts whenever I'm working with
>>> commit graphs: a topological index attribute for commit objects would be
>>> incredible useful. By "topological index" I mean a simple integer for which
>>> following condition holds true:
>>
>> Look for "generation numbers" in the list archive, perhaps?
>
> Thanks for the pointer to the interesting discussions.
>
> In http://www.spinics.net/lists/git/msg161363.html
> Linus wrote in a discussion with Jeff:
>
>> Right now, we do *have* a "generation number". It's just that it's
>> very easy to corrupt even by mistake. It's called "committer date". We
>> could improve on it.
>
> Would it make sense to refuse creating commits that have a commit date
> prior to its parents commit date (except when the user gives a
> `--dammit-I-know-I-break-a-wildy-used-heuristic`)?

I think that has also been discussed in the past.  I do not think it
would help very much in practice, as projects already have up to 10
years (and the ones migrated from CVS, even more) worth of commits
they cannot rewrite that may record incorrect committer dates.
You'd need something like "you can trust committer dates that are
newer that this date" per project to switch between slow path and
fast path, with an updated fsck that knows how to compute that
number after you pulled from somebody who used that overriding
option.

If the use of generation number can somehow be limited narrowly, we
may be able to incrementally introduce it only for new commits, but
I haven't thought things through, so let me do so aloud here ;-)

Suppose we use it only for this purpose:

 * When we have two commits, C1 and C2, with generation numbers G1
   and G2, we can say "C1 cannot possibly be an ancestor of C2" if
   G1 > G2.  We cannot say anything else based on generation
   numbers (or lack thereof).

then I think we could just say "A newly created commit must record
generation number G that is larger than generation numbers of its
parent commits; ignore parents that lack generation number for the
purpose of this sentence".

I am not sure if that limited use is all that useful, though.
--
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 1/9] Report bugs consistently

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> The vast majority of error messages in Git's source code which report a
> bug use the convention to prefix the message with "BUG:".

Good thing to do.

But if we were to review and apply a 200+ line patch, I wonder if we
want to go one step further to allow us to write

BUG("killed-file %s not found", name);

instead.

--
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: topological index field for commit objects

2016-06-29 Thread Jeff King
On Wed, Jun 29, 2016 at 01:39:17PM -0700, Junio C Hamano wrote:

> > Would it make sense to refuse creating commits that have a commit date
> > prior to its parents commit date (except when the user gives a
> > `--dammit-I-know-I-break-a-wildy-used-heuristic`)?
> 
> I think that has also been discussed in the past.  I do not think it
> would help very much in practice, as projects already have up to 10
> years (and the ones migrated from CVS, even more) worth of commits
> they cannot rewrite that may record incorrect committer dates.

Yep, it has been discussed and I agree it runs into a lot of corner
cases.

> If the use of generation number can somehow be limited narrowly, we
> may be able to incrementally introduce it only for new commits, but
> I haven't thought things through, so let me do so aloud here ;-)

I think the problem is that you really _do_ want generation numbers for
old commits. One of the most obvious cases is something like "tag
--contains HEAD", because it has to examine older tags.

So your history looks something like:

  A -- B -- ... Z
\\
 v1.0 HEAD

Without generation numbers (or some proxy), you have to walk the history
between B..Z to find the answer. With generation numbers, it is
immediately obvious.

So this is the ideal case for generation numbers (the worst cases are
when the things you are looking for are in branchy, close history where
the generation numbers don't tell you much; but in such cases the
walking is usually not too bad).

So I think you really do want to be able to generate and store
generation numbers after the fact. That has an added bonus that you do
not have to worry about baking incorrect values into your objects; you
do the topological walk once, and you _know_ it is correct (at least as
correct as the parent links, but that is our source of truth).

I have patches that generate and store the numbers at pack time, similar
to the way we do the reachability bitmaps. They're not production ready,
but they could probably be made so without too much effort. You wouldn't
have ready-made generation numbers for commits since the last full
repack, but you can compute them incrementally based on what you do have
at a cost linear to the unpacked commits (this is the same for bitmaps).

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


Re: topological index field for commit objects

2016-06-29 Thread Jakub Narębski
W dniu 2016-06-29 o 20:59, Junio C Hamano pisze:
> On Wed, Jun 29, 2016 at 11:31 AM, Marc Strapetz
>  wrote:
>
>> This is no RFE but rather recurring thoughts whenever I'm working with
>> commit graphs: a topological index attribute for commit objects would be
>> incredible useful. By "topological index" I mean a simple integer for which
>> following condition holds true:
>> 
>>  if commit C is part of the history of commit D,
>>then C's topological index is smaller than D's index
>> 
>> This would allow topological sorting of commits (e.g. in queues) on the fly
>> and quickly give a "no" answer on the question whether D is part of
>> C's history. 
> 
> Look for "generation numbers" in the list archive, perhaps?

If I remember correctly the discussion, the problem by adding generation number
to the commit object format was twofold (at least).

First there was a problem of backward compatibility, namely what to do with
existing repositories, where commit objects do not have generation number.
Objects in Git are immutable (and I think replacements mechanism wasn't
invented yet - anyway too many replacements would slow down operations
I guess).

Second objection was of philosophical nature: generation numbers duplicate
(cache) information that is stored in the graph of revisions. Also, what
if they get out of sync?

That is, if I remember the summary of that discussion correctly.


Also, generation numbers (graph level) only help with topological sorting;
for finding of two commits are connected (two nodes are connected) people
play with different ideas, for example FELINE index:
  http://openproceedings.org/EDBT/2014/paper_166.pdf

Nowadays there is also [compressed] bitmap index (if enabled), though I am
not sure if it is yet used to speed-up reachability queries
  http://githubengineering.com/counting-objects/
  
https://www.eclipsecon.org/2013/sites/eclipsecon.org.2013/files/Scaling%20Up%20JGit%20-%20EclipseCon%202013.pdf

-- 
Jakub Narębski
--
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: topological index field for commit objects

2016-06-29 Thread Stefan Beller
On Wed, Jun 29, 2016 at 1:39 PM, Junio C Hamano  wrote:
> Stefan Beller  writes:
>
>> On Wed, Jun 29, 2016 at 11:59 AM, Junio C Hamano  wrote:
>>> On Wed, Jun 29, 2016 at 11:31 AM, Marc Strapetz
>>>  wrote:
 This is no RFE but rather recurring thoughts whenever I'm working with
 commit graphs: a topological index attribute for commit objects would be
 incredible useful. By "topological index" I mean a simple integer for which
 following condition holds true:
>>>
>>> Look for "generation numbers" in the list archive, perhaps?
>>
>> Thanks for the pointer to the interesting discussions.
>>
>> In http://www.spinics.net/lists/git/msg161363.html
>> Linus wrote in a discussion with Jeff:
>>
>>> Right now, we do *have* a "generation number". It's just that it's
>>> very easy to corrupt even by mistake. It's called "committer date". We
>>> could improve on it.
>>
>> Would it make sense to refuse creating commits that have a commit date
>> prior to its parents commit date (except when the user gives a
>> `--dammit-I-know-I-break-a-wildy-used-heuristic`)?
>
> I think that has also been discussed in the past.

I should have guessed that and tried to find it.

> I do not think it
> would help very much in practice, as projects already have up to 10
> years (and the ones migrated from CVS, even more) worth of commits
> they cannot rewrite that may record incorrect committer dates.

Chances are that the 10 years of history may be correct time wise as long
as people don't introduce a bad date malevolently.

> You'd need something like "you can trust committer dates that are
> newer that this date" per project

and git version as old versions of git can still be used later.

> to switch between slow path and
> fast path, with an updated fsck that knows how to compute that
> number after you pulled from somebody who used that overriding
> option.

Well you could have a project setting (`config.sortedDates`)
that is automatically computed once when cloning a project and
depending on that setting you can go the fast path.

Additionally when that setting is set, you'd enforce the correct
dates in committing and merging (read pulling) to carry it on to
be true.

>
> If the use of generation number can somehow be limited narrowly, we
> may be able to incrementally introduce it only for new commits, but
> I haven't thought things through, so let me do so aloud here ;-)

I think of it as "committer date == generation number", i.e. just a
special form of noting the generation number with gaps in between.
This loses the ability to know how many commits there are at maximum
between 2 given "numbers" though, which I think is minor.

>
> Suppose we use it only for this purpose:
>
>  * When we have two commits, C1 and C2, with generation numbers G1
>and G2, we can say "C1 cannot possibly be an ancestor of C2" if
>G1 > G2.  We cannot say anything else based on generation
>numbers (or lack thereof).
>
> then I think we could just say "A newly created commit must record
> generation number G that is larger than generation numbers of its
> parent commits; ignore parents that lack generation number for the
> purpose of this sentence".
>
> I am not sure if that limited use is all that useful, though.

I did *not* propose to introduce the generation number, but
rather meant:
* we already have committer date
* it works pretty well
* only a tiny patch is required to tighten the heuristic to work even better
  (going forward) by avoiding accidents in the history that have
  a committer date earlier than their parents.
* we postpone drastic changes (i.e. introduction of generation
  numbers or change of algorithms) for now.
--
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 7/9] merge-recursive: handle return values indicating errors

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> diff --git a/merge-recursive.c b/merge-recursive.c
> index 6ab7dfc..bb075e3 100644
> --- a/merge-recursive.c
> +++ b/merge-recursive.c
> @@ -266,8 +266,10 @@ struct tree *write_tree_from_memory(struct merge_options 
> *o)
>   active_cache_tree = cache_tree();
>  
>   if (!cache_tree_fully_valid(active_cache_tree) &&
> - cache_tree_update(&the_index, 0) < 0)
> - die(_("error building trees"));
> + cache_tree_update(&the_index, 0) < 0) {
> + error(_("error building trees"));
> + return NULL;
> + }

This actually is a BUG(), isn't it?  We have already verified that
the cache is merged, so cache_tree_update() ought to be able to come
up with the whole-tree hash.

> @@ -548,19 +550,17 @@ static int update_stages(const char *path, const struct 
> diff_filespec *o,
>*/
>   int clear = 1;
>   int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_SKIP_DFCHECK;
> + int ret = 0;
> +
>   if (clear)
> - if (remove_file_from_cache(path))
> - return -1;
> - if (o)
> - if (add_cacheinfo(o->mode, o->sha1, path, 1, 0, options))
> - return -1;
> - if (a)
> - if (add_cacheinfo(a->mode, a->sha1, path, 2, 0, options))
> - return -1;
> - if (b)
> - if (add_cacheinfo(b->mode, b->sha1, path, 3, 0, options))
> - return -1;
> - return 0;
> + ret = remove_file_from_cache(path);
> + if (!ret && o)
> + ret = add_cacheinfo(o->mode, o->sha1, path, 1, 0, options);
> + if (!ret && a)
> + ret = add_cacheinfo(a->mode, a->sha1, path, 2, 0, options);
> + if (!ret && b)
> + ret = add_cacheinfo(b->mode, b->sha1, path, 3, 0, options);
> + return ret;
>  }

Aren't the preimage and the postimage doing the same thing?  The
only two differences I spot are (1) it is clear in the original that
the returned value is -1 in the error case, even if the error
convention of remove_file_from_cache() and add_cacheinfo() were "0
is good, others are bad"; and (2) the control flow is easier to
follow in the original.

> @@ -736,7 +736,7 @@ static int make_room_for_path(struct merge_options *o, 
> const char *path)
>   return error(msg, path, _(": perhaps a D/F conflict?"));
>  }
>  
> -static void update_file_flags(struct merge_options *o,
> +static int update_file_flags(struct merge_options *o,
> const unsigned char *sha,
> unsigned mode,
> const char *path,
> @@ -777,8 +777,7 @@ static void update_file_flags(struct merge_options *o,
>  
>   if (make_room_for_path(o, path) < 0) {
>   update_wd = 0;
> - free(buf);
> - goto update_index;
> + goto free_buf;
>   }
>   if (S_ISREG(mode) || (!has_symlinks && S_ISLNK(mode))) {
>   int fd;
> @@ -801,20 +800,22 @@ static void update_file_flags(struct merge_options *o,
>   } else
>   die(_("do not know what to do with %06o %s '%s'"),
>   mode, sha1_to_hex(sha), path);
> +free_buf:
>   free(buf);

I somehow find the above change harder to follow than the original.

>   }
>   update_index:
>   if (update_cache)
>   add_cacheinfo(mode, sha, path, 0, update_wd, 
> ADD_CACHE_OK_TO_ADD);
> + return 0;
>  }
>  

This one is in line with the stated goal of the patch.

> @@ -1028,21 +1030,23 @@ static void handle_change_delete(struct merge_options 
> *o,
>* correct; since there is no true "middle point" between
>* them, simply reuse the base version for virtual merge base.
>*/
> - remove_file_from_cache(path);
> - update_file(o, 0, o_sha, o_mode, renamed ? renamed : path);
> + ret = remove_file_from_cache(path);
> + if (!ret)
> + ret = update_file(o, 0, o_sha, o_mode,
> +   renamed ? renamed : path);

As you noted in the log message, this does change the behaviour.  If
remove returns non-zero for whatever reason, we still did update()
in the original, but we no longer do.  Does this have negative
effect to the overall codeflow?

Or, assuming that everybody returns -1 for errors, perhaps

ret = remove();
ret |= update();

may be a more faithful and safe conversion?

> @@ -1087,21 +1094,22 @@ static void conflict_rename_delete(struct 
> merge_options *o,
>   b_mode = dest->mode;
>   }
>  
> - handle_change_delete(o,
> + ret = handle_change_delete(o,
>o->call_depth ? orig->path : dest->path,
>orig->sha1, orig->mode,
>a_sha, a_mode,

Re: [PATCH 8/9] merge-recursive: switch to returning errors instead of dying

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> @@ -743,6 +741,8 @@ static int update_file_flags(struct merge_options *o,
> int update_cache,
> int update_wd)
> ...
> + ret = error_errno(_("do not know what to do with %06o 
> %s '%s'"),
> + mode, sha1_to_hex(sha), path);
>  free_buf:

OK, with a few more users of this label, it no longer looks so
strange to me to have this label here.

At least, match the indentation level to the existing one we see
below, though?

>   free(buf);
>   }
>   update_index:
> - if (update_cache)
> + if (!ret && update_cache)
>   add_cacheinfo(mode, sha, path, 0, update_wd, 
> ADD_CACHE_OK_TO_ADD);

Unlike my reaction to "if (!ret) do this" in an earlier patch, I do
think this change is sensible.  We wouldn't have reached here in the
original code if we saw errors, and some of the variable used to
call add_cacheinfo() at this point may be garbage when ret is
non-zero, i.e. we know we earlier saw an error.

> - return 0;
> + return ret;
>  }
> ...
>   if ((merge_status < 0) || !result_buf.ptr)
> - die(_("Failed to execute internal merge"));
> + ret = error(_("Failed to execute internal 
> merge"));
>  
> - if (write_sha1_file(result_buf.ptr, result_buf.size,
> + if (!ret && write_sha1_file(result_buf.ptr, 
> result_buf.size,
>   blob_type, result->sha))

Likewise.

> @@ -1861,7 +1867,7 @@ static int process_entry(struct merge_options *o,
>*/
>   remove_file(o, 1, path, !a_mode);
>   } else
> - die(_("Fatal merge failure, shouldn't happen."));
> + return error(_("Fatal merge failure, shouldn't happen."));

Isn't this BUG()?

--
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: [RFD] Place to document magic pathspecs like ":/" and pathspec handling

2016-06-29 Thread Jakub Narębski
W dniu 2016-06-29 o 21:51, Junio C Hamano pisze:
> On Wed, Jun 29, 2016 at 12:47 PM, Jakub Narębski  wrote:
>> I have noticed that the magic pathspec ":/" is described only in RelNotes
>> for revision 1.7.6:
>> |I think the reason might be that there was no good place to put that
>> information in.  Nowadays we have gitcli(7) manual page, but perhaps
> $ git help glossary
>
> look for pathspec.
Thanks. I haven't noticed that.

But I think it is not the best place to keep this documentation.
There are the following issues with it:

* it is hard to find; I did not search _glossary_ for information
  about how Git handles pathspecs, I would search it if I didn't know
  what pathspec means.

* it is longest entry in glossary, and the only one with nested
  list, but

* it is also too short to describe how Git handles pathspecs in detail,
  and a bit cryptic; there are no examples (so grepping docs for '":/"'
  didn't found it).

-- 
Jakub Narębski

--
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 9/9] am: make a direct call to merge_recursive

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> - cp.git_cmd = 1;
> + init_merge_options(&o);
> +
> + o.branch1 = "HEAD";
> + his_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
> + o.branch2 = his_tree_name;
>  
> - argv_array_pushf(&cp.env_array, "GITHEAD_%s=%.*s",
> -  sha1_to_hex(his_tree), linelen(state->msg), 
> state->msg);
>   if (state->quiet)
> - argv_array_push(&cp.env_array, "GIT_MERGE_VERBOSITY=0");
> + o.verbosity = 0;
>  
> - argv_array_push(&cp.args, "merge-recursive");
> - argv_array_push(&cp.args, sha1_to_hex(orig_tree));
> - argv_array_push(&cp.args, "--");
> - argv_array_push(&cp.args, sha1_to_hex(our_tree));
> - argv_array_push(&cp.args, sha1_to_hex(his_tree));
> + status = merge_recursive_generic(&o, our_tree, his_tree, 1, bases, 
> &result);
> + if (status < 0)
> + exit(128);
> + free(his_tree_name);
>  
> - status = run_command(&cp) ? (-1) : 0;
> - discard_cache();
> - read_cache();
>   return status;
>  }

Is this a correct conversion?

We used to prepare the command line and called run_command() and
without dying returned status with the error status from the
merge-recursive that was spawned by run_command().

The new code does not report failure to the caller and instead dies.

--
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: [RFD] Place to document magic pathspecs like ":/" and pathspec handling

2016-06-29 Thread Junio C Hamano
Jakub Narębski  writes:

> But I think it is not the best place to keep this documentation.

All true.  In case it was not obvious, I didn't mean to say "Here
you find the information, shut up."  It was "here is a pointer if
you didn't find it, so that you can use it as a starting point to
make a better documentation."

An analogous entity in the world model of Git that appears
everywhere and is not limited to a single command is the revision
set calculus.  Where do we describe it and how do we make it
discoverable?  Can the new way to describe pathspec and pathspec
magic mimic the way it is done for the revisions?
--
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: topological index field for commit objects

2016-06-29 Thread Stefan Beller
On Wed, Jun 29, 2016 at 1:54 PM, Stefan Beller  wrote:
> Chances are that the 10 years of history may be correct time wise as long
> as people don't introduce a bad date malevolently.
>

To answer my own speculation:
Even git.git violates the timing property, so there is no hope to find
many projects
to have "parents committer date < committer date"

$ git log --format="%H %ct %P" HEAD | {
> while read sha sha_date parents ; do
> for p in $parents ; do
> # echo "$id, $parents, $p"
> pd=$(git show -s --format="%ct" $p)
> if test $pd -gt $sha_date ; then
> echo $sha
> fi
> done
> done
> }
619a644d6daef56d70aeca85514e2d281eb483a5
776398709dee4050fc194fec45c5818ba9b01afe
ed19f367220a50e4e2a5c1a00b03c14eafcaba89

(out of curiosity these are:)
(2009-10-18 12:34:56, "checkout A...B" switches to the merge base
between A and B)
(2007-09-01 23:53:47, Keep last used delta base in the delta window)
(2006-03-03 23:29:56, Add a Documentation/git-tools.txt)
--
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: topological index field for commit objects

2016-06-29 Thread Jeff King
On Wed, Jun 29, 2016 at 02:37:17PM -0700, Stefan Beller wrote:

> On Wed, Jun 29, 2016 at 1:54 PM, Stefan Beller  wrote:
> > Chances are that the 10 years of history may be correct time wise as long
> > as people don't introduce a bad date malevolently.
> >
> 
> To answer my own speculation:
> Even git.git violates the timing property, so there is no hope to find
> many projects
> to have "parents committer date < committer date"

It's expected and reasonable for there to be some skew. People's clocks
aren't all perfectly synced. The question is one of how _much_ skew
you're willing to tolerate (and any algorithms obviously need to allow
that much, too).

In some places we allow 24 hours of skew between any two commits. In
others we allow up to 5 skewed commits in a row.

That may not be enough in general, though. E.g.:

> 619a644d6daef56d70aeca85514e2d281eb483a5

This one is a 3-day skew.

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


Re: topological index field for commit objects

2016-06-29 Thread Jakub Narębski
W dniu 2016-06-29 o 22:56, Jeff King pisze:
> On Wed, Jun 29, 2016 at 01:39:17PM -0700, Junio C Hamano wrote:
> 
>>> Would it make sense to refuse creating commits that have a commit date
>>> prior to its parents commit date (except when the user gives a
>>> `--dammit-I-know-I-break-a-wildy-used-heuristic`)?
>>
>> I think that has also been discussed in the past.  I do not think it
>> would help very much in practice, as projects already have up to 10
>> years (and the ones migrated from CVS, even more) worth of commits
>> they cannot rewrite that may record incorrect committer dates.
> 
> Yep, it has been discussed and I agree it runs into a lot of corner
> cases.
> 
>> If the use of generation number can somehow be limited narrowly, we
>> may be able to incrementally introduce it only for new commits, but
>> I haven't thought things through, so let me do so aloud here ;-)
> 
> I think the problem is that you really _do_ want generation numbers for
> old commits. One of the most obvious cases is something like "tag
> --contains HEAD", because it has to examine older tags.
> 
> So your history looks something like:
> 
>   A -- B -- ... Z
> \\
>v1.0 HEAD
> 
> Without generation numbers (or some proxy), you have to walk the history
> between B..Z to find the answer. With generation numbers, it is
> immediately obvious.
> 
> So this is the ideal case for generation numbers (the worst cases are
> when the things you are looking for are in branchy, close history where
> the generation numbers don't tell you much; but in such cases the
> walking is usually not too bad).

There are other approaches (special indices) that help reachability
queries beside "generation number".

> 
> So I think you really do want to be able to generate and store
> generation numbers after the fact. That has an added bonus that you do
> not have to worry about baking incorrect values into your objects; you
> do the topological walk once, and you _know_ it is correct (at least as
> correct as the parent links, but that is our source of truth).

By the way, what should happen if you add a replacement (in the git-replace
meaning) that creates a shortcut, therefore invalidating generation numbers,
at least in strict sense - committerdate as generation number would be still
good, I think?
 
> I have patches that generate and store the numbers at pack time, similar
> to the way we do the reachability bitmaps. They're not production ready,
> but they could probably be made so without too much effort. You wouldn't
> have ready-made generation numbers for commits since the last full
> repack, but you can compute them incrementally based on what you do have
> at a cost linear to the unpacked commits (this is the same for bitmaps).

Do Git use EWAH / EWOK bitmaps for reachability analysis, or is it still
limited to object counting?

-- 
Jakub Narębski


--
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: topological index field for commit objects

2016-06-29 Thread Jeff King
On Wed, Jun 29, 2016 at 11:49:35PM +0200, Jakub Narębski wrote:

> > So this is the ideal case for generation numbers (the worst cases are
> > when the things you are looking for are in branchy, close history where
> > the generation numbers don't tell you much; but in such cases the
> > walking is usually not too bad).
> 
> There are other approaches (special indices) that help reachability
> queries beside "generation number".

Yes, though generation numbers can help with more questions (e.g., "what
is the merge base").

> By the way, what should happen if you add a replacement (in the git-replace
> meaning) that creates a shortcut, therefore invalidating generation numbers,
> at least in strict sense - committerdate as generation number would be still
> good, I think?

This is one of the open questions. My older patches turned them off when
replacements and grafts are in effect.

> > I have patches that generate and store the numbers at pack time, similar
> > to the way we do the reachability bitmaps. They're not production ready,
> > but they could probably be made so without too much effort. You wouldn't
> > have ready-made generation numbers for commits since the last full
> > repack, but you can compute them incrementally based on what you do have
> > at a cost linear to the unpacked commits (this is the same for bitmaps).
> 
> Do Git use EWAH / EWOK bitmaps for reachability analysis, or is it still
> limited to object counting?

At GitHub we are using them for --contains analysis, along with mass
ahead/behind (e.g., as in https://github.com/gitster/git/branches). My
plan is to send patches upstream, but they need some cleanup first.

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


Re: [PATCH 2/5] sequencer: use skip_blank_lines() to find the commit subject

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> Just like we already taught the find_commit_subject() function (to make
> it consistent with the code in pretty.c), we now simply skip leading
> blank lines of the commit message.
>
> Signed-off-by: Johannes Schindelin 
> ---
>  sequencer.c | 6 ++
>  1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/sequencer.c b/sequencer.c
> index 7d7add6..cdfac82 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -544,10 +544,8 @@ static int do_pick_commit(struct commit *commit, struct 
> replay_opts *opts)
>* information followed by "\n\n".
>*/
>   p = strstr(msg.message, "\n\n");
> - if (p) {
> - p += 2;
> - strbuf_addstr(&msgbuf, p);
> - }
> + if (p)
> + strbuf_addstr(&msgbuf, skip_blank_lines(p + 2));
>  
>   if (opts->record_origin) {
>   if (!has_conforming_footer(&msgbuf, NULL, 0))

Here, msg.message was read in get_message() by calling
logmsg_reencode() that reads from get_commit_buffer().  The code
structure is exactly the same as the previous one.

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


Re: [PATCH 1/5] commit -C: skip blank lines at the beginning of the message

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> Consistent with the pretty-printing machinery, we skip leading blank
> lines (if any) of existing commit messages.
>
> While Git itself only produces commit objects with a single empty line
> between commit header and commit message, it is legal to have more than
> one blank line (i.e. lines containing only white space, or no
> characters) at the beginning of the commit message, and the
> pretty-printing code already handles that.
>
> Signed-off-by: Johannes Schindelin 
> ---
>  builtin/commit.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/builtin/commit.c b/builtin/commit.c
> index 3f18942..1f6dbcd 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -715,7 +715,7 @@ static int prepare_to_commit(const char *index_file, 
> const char *prefix,
>   char *buffer;
>   buffer = strstr(use_message_buffer, "\n\n");
>   if (buffer)
> - strbuf_addstr(&sb, buffer + 2);
> + strbuf_addstr(&sb, skip_blank_lines(buffer + 2));
>   hook_arg1 = "commit";
>   hook_arg2 = use_message;
>   } else if (fixup_message) {

use_message_buffer is the contents of the commit object read
elsewhere, and strstr() skips the header part, so this follows
exactly the same pattern as the one you fixed earlier.  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


Re: topological index field for commit objects

2016-06-29 Thread Junio C Hamano
Jeff King  writes:

> Yes, though generation numbers can help with more questions (e.g., "what
> is the merge base").

Hmm, how?  I have two commits, with generation number 38 and 47,
respectively.  What generation number does the commit that is the
merge base of these two commits?

I know we can say that 38 cannot possibly be a descendant of 47, but
can we say anything else that is useful?

--
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: topological index field for commit objects

2016-06-29 Thread Marc Strapetz

On 29.06.2016 22:39, Junio C Hamano wrote:

Stefan Beller  writes:


On Wed, Jun 29, 2016 at 11:59 AM, Junio C Hamano  wrote:

On Wed, Jun 29, 2016 at 11:31 AM, Marc Strapetz
 wrote:

This is no RFE but rather recurring thoughts whenever I'm working with
commit graphs: a topological index attribute for commit objects would be
incredible useful. By "topological index" I mean a simple integer for which
following condition holds true:


Look for "generation numbers" in the list archive, perhaps?


Thanks for the pointer to the interesting discussions.

In http://www.spinics.net/lists/git/msg161363.html
Linus wrote in a discussion with Jeff:


Right now, we do *have* a "generation number". It's just that it's
very easy to corrupt even by mistake. It's called "committer date". We
could improve on it.


Would it make sense to refuse creating commits that have a commit date
prior to its parents commit date (except when the user gives a
`--dammit-I-know-I-break-a-wildy-used-heuristic`)?


I think that has also been discussed in the past.  I do not think it
would help very much in practice, as projects already have up to 10
years (and the ones migrated from CVS, even more) worth of commits
they cannot rewrite that may record incorrect committer dates.
You'd need something like "you can trust committer dates that are
newer that this date" per project to switch between slow path and
fast path, with an updated fsck that knows how to compute that
number after you pulled from somebody who used that overriding
option.

If the use of generation number can somehow be limited narrowly, we
may be able to incrementally introduce it only for new commits, but
I haven't thought things through, so let me do so aloud here ;-)

Suppose we use it only for this purpose:

 * When we have two commits, C1 and C2, with generation numbers G1
   and G2, we can say "C1 cannot possibly be an ancestor of C2" if
   G1 > G2.  We cannot say anything else based on generation
   numbers (or lack thereof).

then I think we could just say "A newly created commit must record
generation number G that is larger than generation numbers of its
parent commits; ignore parents that lack generation number for the
purpose of this sentence".


From algorithm perspective, for already existing repositories you would 
still have to switch from an optimized generation number code to the 
current commit-time based code. That could things make even more complex 
and it's possibly expensive to determine whether a repository has full 
generation number support or not.


On the other hand, for new repositories, you could immediately use 
generation number based algorithms. So it could be "A newly created 
commit must record generation number G that is larger than generation 
numbers of its parent commits if all parents commits have a generation 
number recorded; otherwise do not record a generation number". Something 
like "git filter-branch" might already be sufficient to convert 
repositories.


Git versions released in 2019 may start issuing warnings if HEAD has no 
generation number assigned and Git versions released in 2025 may 
completely refuse to work with such repositories.


In the interim period, a local cache as Jeff is proposing could serve as 
secondary source for generation numbers. This would allow to phase out 
current algorithms immediately.


-Marc



--
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: topological index field for commit objects

2016-06-29 Thread Jeff King
On Wed, Jun 29, 2016 at 03:11:39PM -0700, Junio C Hamano wrote:

> Jeff King  writes:
> 
> > Yes, though generation numbers can help with more questions (e.g., "what
> > is the merge base").
> 
> Hmm, how?  I have two commits, with generation number 38 and 47,
> respectively.  What generation number does the commit that is the
> merge base of these two commits?
> 
> I know we can say that 38 cannot possibly be a descendant of 47, but
> can we say anything else that is useful?

I don't think it can give you the answer immediately from those values,
but in general generation numbers help you bound actual traversals and
avoid walking down unproductive paths. So comparing 38 and 47 is not
nearly as useful as walking from 47 down to 37 and saying "I know that I
cannot possibly reach 38 by walking further".

I haven't thought hard specifically about merge bases computation, so
perhaps that is a case that isn't helped at all. It has been a while
since I've looked into this, but I recall there were some computations
that are hard to improve with bitmaps. I may also simply be
mis-remembering; in my patches generations were tightly tied to having a
packv4-style cache of commit properties that can be used rather than
inflating the commit object itself. That cache helps any time you walk
by speeding up the parse_commit() process. But it's a per-commit
speedup. It doesn't change the algorithmic complexity of what you're
doing.

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


Re: [PATCH 5/5] Skip blank lines when matching ^{/foo}

2016-06-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> When trying to match a pattern in the commit subject, simply skip leading
> blank lines in the commit message. This is consistent with the
> pretty-printing machinery: it silently ignores leading blank lines in the
> commit object's body.
>
> Signed-off-by: Johannes Schindelin 
> ---

Hmm.

I just tried

$ git commit -s -m '  pull: fast-forward "pull --rebase=true"'

expecting that ":/^  pull:" would find it ;-)

The point of this patch is to make it not work, of course, which 
may or may not be a good thing.  I'd rather keep this separate from
the other fixes.

Also 4/5 is another different class of true bugfix, I would suspect,
so let's take it on a separate topic that can be merged down to
older maintainance tracks.

Thanks.

>  sha1_name.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/sha1_name.c b/sha1_name.c
> index ca7ddd6..da354a5 100644
> --- a/sha1_name.c
> +++ b/sha1_name.c
> @@ -912,7 +912,8 @@ static int get_sha1_oneline(const char *prefix, unsigned 
> char *sha1,
>   continue;
>   buf = get_commit_buffer(commit, NULL);
>   p = strstr(buf, "\n\n");
> - matches = negative ^ (p && !regexec(®ex, p + 2, 0, NULL, 0));
> + matches = negative ^ (p && !regexec(®ex,
> + skip_blank_lines(p + 2), 0, NULL, 0));
>   unuse_commit_buffer(commit, buf);
>  
>   if (matches) {
--
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


What's cooking in git.git (Jun 2016, #10; Wed, 29)

2016-06-29 Thread Junio C Hamano
Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.  The ones marked with '.' do not appear in any of
the integration branches, but I am still holding onto them.

The first few batches for this cycle has been merged to 'master',
and new topics are trickling into 'next'.

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

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

--
[New Topics]

* cc/apply-am (2016-06-28) 41 commits
 - apply: use error_errno() where possible
 - builtin/am: use apply api in run_apply()
 - apply: change error_routine when be_silent is set
 - usage: add get_error_routine() and get_warn_routine()
 - usage: add set_warn_routine()
 - apply: don't print on stdout when be_silent is set
 - apply: make 'be_silent' incompatible with 'apply_verbosely'
 - apply: add 'be_silent' variable to 'struct apply_state'
 - write_or_die: use warning() instead of fprintf(stderr, ...)
 - environment: add set_index_file()
 - apply: make some parsing functions static again
 - apply: move libified code from builtin/apply.c to apply.{c,h}
 - apply: rename and move opt constants to apply.h
 - builtin/apply: rename option parsing functions
 - builtin/apply: make create_one_file() return -1 on error
 - builtin/apply: make try_create_file() return -1 on error
 - builtin/apply: make write_out_results() return -1 on error
 - builtin/apply: make write_out_one_result() return -1 on error
 - builtin/apply: make create_file() return -1 on error
 - builtin/apply: make add_index_file() return -1 on error
 - builtin/apply: make add_conflicted_stages_file() return -1 on error
 - builtin/apply: make remove_file() return -1 on error
 - builtin/apply: make build_fake_ancestor() return -1 on error
 - builtin/apply: change die_on_unsafe_path() to check_unsafe_path()
 - builtin/apply: make gitdiff_*() return -1 on error
 - builtin/apply: make gitdiff_*() return 1 at end of header
 - builtin/apply: make parse_traditional_patch() return -1 on error
 - builtin/apply: make apply_all_patches() return 128 or 1 on error
 - builtin/apply: move check_apply_state() to apply.c
 - builtin/apply: make check_apply_state() return -1 instead of die()ing
 - apply: make init_apply_state() return -1 instead of exit()ing
 - builtin/apply: move init_apply_state() to apply.c
 - builtin/apply: make parse_ignorewhitespace_option() return -1 instead of 
die()ing
 - builtin/apply: make parse_whitespace_option() return -1 instead of die()ing
 - builtin/apply: make parse_single_patch() return -1 on error
 - builtin/apply: make parse_chunk() return a negative integer on error
 - builtin/apply: make find_header() return -128 instead of die()ing
 - builtin/apply: read_patch_file() return -1 instead of die()ing
 - builtin/apply: make apply_patch() return -1 or -128 instead of die()ing
 - apply: move 'struct apply_state' to apply.h
 - apply: make some names more specific

 "git am" has been taught to make an internal call to "git apply"'s
 innards without spawning the latter as a separate process.

 Needs review.


* dp/autoconf-curl-ssl (2016-06-28) 1 commit
 - ./configure.ac: detect SSL in libcurl using curl-config

 The ./configure script generated from configure.ac was taught how
 to detect support of SSL by libcurl better.

 Needs review.


* js/color-on-windows-comment (2016-06-28) 1 commit
  (merged to 'next' on 2016-06-28 at 38a2ea1)
 + color.h: remove obsolete comment about limitations on Windows

 For a long time, we carried an in-code comment that said our
 colored output would work only when we use fprintf/fputs on
 Windows, which no longer is the case for the past few years.

 Will merge to 'master'.


* js/sign-empty-commit-fix (2016-06-29) 1 commit
 - commit -S: avoid invalid pointer with empty message

 "git commit --amend --allow-empty-message -S" for a commit without
 any message body could have misidentified where the header of the
 commit object ends.

 Will merge to 'next'.


* js/t3404-grammo-fix (2016-06-29) 1 commit
 - t3404: fix a grammo (commands are ran -> commands are run)

 Will merge to 'next'.


* ls/p4-tmp-refs (2016-06-29) 1 commit
 - git-p4: place temporary refs used for branch import under refs/git-p4-tmp

 "git p4" used a location outside $GIT_DIR/refs/ to place its
 temporary branches, which has been moved to refs/git-p4-tmp/.

 Needs an ack from "git p4" experts.


* jc/pull-rebase-ff (2016-06-29) 1 commit
 -   pull: fast-forward "pull --rebase=true"

 "git pull --rebase", when there is no new commits on our side since
 we forked from the upstream, should be able to fast-forward without
 invoking "git rebase", but it didn't.

 Needs a real log message and a few tests.


* ps/rebase-i-auto-unstash-upon-abort (2016-06-29) 1 commit
 - rebase -i: restore autostash on abort

 "git rebase -i --autostash" did not restore t

Re: What's cooking in git.git (Jun 2016, #10; Wed, 29)

2016-06-29 Thread Ramsay Jones


On 30/06/16 00:22, Junio C Hamano wrote:
[snip]
> 
> * mh/ref-store (2016-06-20) 38 commits
>  - refs: implement iteration over only per-worktree refs
>  - refs: make lock generic
>  - refs: add method to rename refs
>  - refs: add methods to init refs db
>  - refs: make delete_refs() virtual
>  - refs: add method for initial ref transaction commit
>  - refs: add methods for reflog
>  - refs: add method iterator_begin
>  - files_ref_iterator_begin(): take a ref_store argument
>  - split_symref_update(): add a files_ref_store argument
>  - lock_ref_sha1_basic(): add a files_ref_store argument
>  - lock_ref_for_update(): add a files_ref_store argument
>  - commit_ref_update(): add a files_ref_store argument
>  - lock_raw_ref(): add a files_ref_store argument
>  - repack_without_refs(): add a files_ref_store argument
>  - refs: make peel_ref() virtual
>  - refs: make create_symref() virtual
>  - refs: make pack_refs() virtual
>  - refs: make verify_refname_available() virtual
>  - refs: make read_raw_ref() virtual
>  - resolve_gitlink_ref(): rename path parameter to submodule
>  - resolve_gitlink_ref(): avoid memory allocation in many cases
>  - resolve_gitlink_ref(): implement using resolve_ref_recursively()
>  - resolve_ref_recursively(): new function
>  - read_raw_ref(): take a (struct ref_store *) argument
>  - resolve_gitlink_packed_ref(): remove function
>  - resolve_packed_ref(): rename function from resolve_missing_loose_ref()
>  - refs: reorder definitions
>  - refs: add a transaction_commit() method
>  - {lock,commit,rollback}_packed_refs(): add files_ref_store arguments
>  - resolve_missing_loose_ref(): add a files_ref_store argument
>  - get_packed_ref(): add a files_ref_store argument
>  - add_packed_ref(): add a files_ref_store argument
>  - refs: create a base class "ref_store" for files_ref_store
>  - refs: add a backend method structure
>  - refs: rename struct ref_cache to files_ref_store
>  - rename_ref_available(): add docstring
>  - resolve_gitlink_ref(): eliminate temporary variable
>  (this branch uses mh/ref-iterators and mh/split-under-lock; is tangled with 
> mh/update-ref-errors.)
> 
>  The ref-store abstraction was introduced to the refs API so that we
>  can plug in different backends to store references.
> 
>  Is everybody happy with this version?
>  If so, will merge to 'next'.

A small fixup required for this one.

see http://thread.gmane.org/gmane.comp.version-control.git/298137

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


[PATCH 2/4] receive-pack: implement advertising and receiving push options

2016-06-29 Thread Stefan Beller
The pre/post receive hook may be interested in more information from the
user. This information can be transmitted when both client and server
support the "push-options" capability, which when used is a phase directly
after update commands ended by a flush pkt.

Similar to the atomic option, the server capability can be disabled via
the `receive.advertisePushOptions` config variable. While documenting
this, fix a nit in the `receive.advertiseAtomic` wording.

For now we only accept C strings with no new lines.

Signed-off-by: Stefan Beller 
---
 Documentation/config.txt  |  7 +++-
 Documentation/technical/pack-protocol.txt | 10 +++---
 Documentation/technical/protocol-capabilities.txt |  8 +
 builtin/receive-pack.c| 44 +++
 4 files changed, 64 insertions(+), 5 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 626243f..3b199f9 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2410,7 +2410,12 @@ rebase.instructionFormat
 
 receive.advertiseAtomic::
By default, git-receive-pack will advertise the atomic push
-   capability to its clients. If you don't want to this capability
+   capability to its clients. If you don't want this capability
+   to be advertised, set this variable to false.
+
+receive.advertisePushOptions::
+   By default, git-receive-pack will advertise the push options capability
+   to its clients. If you don't want this capability
to be advertised, set this variable to false.
 
 receive.autogc::
diff --git a/Documentation/technical/pack-protocol.txt 
b/Documentation/technical/pack-protocol.txt
index 8b36343..7a2ed30 100644
--- a/Documentation/technical/pack-protocol.txt
+++ b/Documentation/technical/pack-protocol.txt
@@ -454,7 +454,8 @@ The reference discovery phase is done nearly the same way 
as it is in the
 fetching protocol. Each reference obj-id and name on the server is sent
 in packet-line format to the client, followed by a flush-pkt.  The only
 real difference is that the capability listing is different - the only
-possible values are 'report-status', 'delete-refs' and 'ofs-delta'.
+possible values are 'report-status', 'delete-refs', 'ofs-delta' and
+'push-options'.
 
 Reference Update Request and Packfile Transfer
 --
@@ -465,9 +466,10 @@ that it wants to update, it sends a line listing the 
obj-id currently on
 the server, the obj-id the client would like to update it to and the name
 of the reference.
 
-This list is followed by a flush-pkt and then the packfile that should
-contain all the objects that the server will need to complete the new
-references.
+This list is followed by a flush-pkt. Then the push options are transmitted
+one per packet followed by another flush-pkt. After that the packfile that
+should contain all the objects that the server will need to complete the new
+references will be sent.
 
 
   update-request=  *shallow ( command-list | push-cert ) [packfile]
diff --git a/Documentation/technical/protocol-capabilities.txt 
b/Documentation/technical/protocol-capabilities.txt
index eaab6b4..b71eda9 100644
--- a/Documentation/technical/protocol-capabilities.txt
+++ b/Documentation/technical/protocol-capabilities.txt
@@ -253,6 +253,14 @@ atomic pushes. If the pushing client requests this 
capability, the server
 will update the refs in one atomic transaction. Either all refs are
 updated or none.
 
+push-options
+
+
+If the server sends the 'push-options' capability it is capable to accept
+push options after the update commands have been sent. If the pushing client
+requests this capability, the server will pass the options to the pre and post
+receive hooks that process this push request.
+
 allow-tip-sha1-in-want
 --
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 0da6852..68627ed 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -44,10 +44,12 @@ static struct strbuf fsck_msg_types = STRBUF_INIT;
 static int receive_unpack_limit = -1;
 static int transfer_unpack_limit = -1;
 static int advertise_atomic_push = 1;
+static int advertise_push_options = 1;
 static int unpack_limit = 100;
 static int report_status;
 static int use_sideband;
 static int use_atomic;
+static int use_push_options;
 static int quiet;
 static int prefer_ofs_delta = 1;
 static int auto_update_server_info;
@@ -193,6 +195,11 @@ static int receive_pack_config(const char *var, const char 
*value, void *cb)
return 0;
}
 
+   if (strcmp(var, "receive.advertisepushoptions") == 0) {
+   advertise_push_options = git_config_bool(var, value);
+   return 0;
+   }
+
return git_default_config(var, value, cb);
 }
 
@@ -207,6 +214,8 @@ static void show_ref(const char *path, const unsigned char 
*sha1)
  "report-status d

[PATCH 4/4] add a test for push options

2016-06-29 Thread Stefan Beller
The functions `mk_repo_pair` as well as `test_refs` are borrowed from
t5543-atomic-push, with additional hooks installed.

Signed-off-by: Stefan Beller 
---
 t/t5544-push-options.sh | 85 +
 1 file changed, 85 insertions(+)
 create mode 100755 t/t5544-push-options.sh

diff --git a/t/t5544-push-options.sh b/t/t5544-push-options.sh
new file mode 100755
index 000..49d5f80
--- /dev/null
+++ b/t/t5544-push-options.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+
+test_description='pushing to a repository using push options'
+
+. ./test-lib.sh
+
+mk_repo_pair () {
+   rm -rf workbench upstream &&
+   test_create_repo upstream &&
+   test_create_repo workbench &&
+   (
+   cd upstream &&
+   git config receive.denyCurrentBranch warn &&
+   mkdir -p .git/hooks &&
+   cat >.git/hooks/pre-receive <<-'EOF' &&
+   #!/bin/sh
+   cat $GIT_PUSH_OPTION_FILE >hooks/pre-receive.push_options
+   EOF
+   chmod u+x .git/hooks/pre-receive
+
+   cat >.git/hooks/post-receive <<-'EOF' &&
+   #!/bin/sh
+   cat $GIT_PUSH_OPTION_FILE >hooks/post-receive.push_options
+   EOF
+   chmod u+x .git/hooks/post-receive
+   ) &&
+   (
+   cd workbench &&
+   git remote add up ../upstream
+   )
+}
+
+# Compare the ref ($1) in upstream with a ref value from workbench ($2)
+# i.e. test_refs second HEAD@{2}
+test_refs () {
+   test $# = 2 &&
+   git -C upstream rev-parse --verify "$1" >expect &&
+   git -C workbench rev-parse --verify "$2" >actual &&
+   test_cmp expect actual
+}
+
+test_expect_success 'one push option works for a single branch' '
+   mk_repo_pair &&
+   (
+   cd workbench &&
+   test_commit one &&
+   git push --mirror up &&
+   test_commit two &&
+   git push --push-option=asdf up master
+   ) &&
+   test_refs master master &&
+   echo "asdf" >expect &&
+   test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
+   test_cmp expect upstream/.git/hooks/post-receive.push_options
+'
+
+test_expect_success 'push option denied by remote' '
+   mk_repo_pair &&
+   git -C upstream config receive.advertisePushOptions false &&
+   (
+   cd workbench &&
+   test_commit one &&
+   git push --mirror up &&
+   test_commit two &&
+   test_must_fail git push --push-option=asdf up master
+   ) &&
+   test_refs master HEAD@{1}
+'
+
+test_expect_success 'two push options work' '
+   mk_repo_pair &&
+   (
+   cd workbench &&
+   test_commit one &&
+   git push --mirror up &&
+   test_commit two &&
+   git push --push-option=asdf --push-option="more structured 
text" up master
+   ) &&
+   test_refs master master &&
+   printf "asdf\nmore structured text\n" >expect &&
+   test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
+   test_cmp expect upstream/.git/hooks/post-receive.push_options
+'
+
+test_done
-- 
2.9.0.141.gdd65b60

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


[RFC PATCHv1 0/4] Push options in C Git

2016-06-29 Thread Stefan Beller
Allow a user to pass information along a push to the pre/post-receive hook
on the remote.

When using a remote that is more than just a plain Git host (e.g. Gerrit,
Git{hub/lab}, etc) this may become more obvious: The (server backend specific)
push options can instruct the server to:
* open a pull request
* send out emails asking for review
* (un)trigger continuous integration
* set priority for continuous integration (i.e. bots pushing may ask to be
  treated with lower priority compared to humans)
* ... 

Most of these actions can be done on the client side as well,
but in these remote-centric workflows it is easier to do that on the remote,
which is why we need to transport the information there.

More concrete examples:
* When you want a change in Gerrit to be submitted to refs/heads/master, you
  push instead to a magic branch refs/for/master and Gerrit will create a change
  for you (similar to a pull request). Instead we could imagine that you push
  to a magical refs/heads/master with a push option "create-change".
  
* When pushing to Gerrit you can already attach some of this information by
  adding a '%' followed by the parameter to the ref, i.e. when interacting with
  Gerrit it is possible to do things like[1]:

git push origin 
HEAD:refs/for/master%draft%topic=example%cc=jon@example.org
  
  This is not appealing to our users as it looks like hacks upon hacks to make
  it work. It would read better if it was spelled as:
  
  git push origin HEAD:refs/for/master \
  --push-option draft \
  --push-option topic=example \
  --push-option cc=jon@example.org
  
  (with a short form that is even easier to type,
   but this is is more intuitive already)

This is a patch series to Git core, which is developed at the same time
as a change is proposed to JGit by Dan Wang, see [2].

This code is also available at [3].

Thanks,
Stefan

[1] Not all Gerrit '%' options are documented, so here is a link to source code 
instead :(
https://gerrit.googlesource.com/gerrit/+/refs/heads/master/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java#1141

[2] https://git.eclipse.org/r/#/c/74570/ 
 
[3] https://github.com/stefanbeller/git/tree/pushoptions

Stefan Beller (4):
  push options: {pre,post}-receive hook learns about push options
  receive-pack: implement advertising and receiving push options
  push: accept push options
  add a test for push options

 Documentation/config.txt  |  7 +-
 Documentation/git-push.txt|  8 ++-
 Documentation/githooks.txt|  4 ++
 Documentation/technical/pack-protocol.txt | 10 +--
 Documentation/technical/protocol-capabilities.txt |  8 +++
 builtin/push.c| 16 -
 builtin/receive-pack.c| 85 +++
 send-pack.c   | 29 
 send-pack.h   |  3 +
 t/t5544-push-options.sh   | 85 +++
 transport.c   |  2 +
 transport.h   |  7 ++
 12 files changed, 242 insertions(+), 22 deletions(-)
 create mode 100755 t/t5544-push-options.sh

-- 
2.9.0.141.gdd65b60

--
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/4] push options: {pre,post}-receive hook learns about push options

2016-06-29 Thread Stefan Beller
The environment variable GIT_PUSH_OPTION_FILE is set to the push options
separated by new line.

The code is not executed as the push options are set to NULL, nor is the
new capability advertised.

The rationale for keeping the actual options inside a file instead of
putting them directly into an environment variable has multiple reasons:

1) After a discussion about environment variables and shells, we may not
want to put user data into an environment variable (see [1] for example).

2) If a user passes multiple push options, we need to pass them to the
hooks in a way, the hook can separate them. This could be done via
multiple environment variables (e.g. have GIT_PUSH_OPTIONS_COUNT and
GIT_PUSH_OPTIONS_{0,1,2,...} set), or put it all in one environment
variable and choose an appropriate separator. That is hard to parse
in both ways. For now we'll just put it in a file separated by new line,
such that the hook scripts can pickup the variables as

while read option ; do
process_push_option() $option
done < $GIT_PUSH_OPTION_FILE

3) environment variables are messed with in the run-command API depending
on the occurrence of a '=' to set or unset the variable. Having multiple
'=' is ok, such that we could have it set to a "key=value" pair.

4) When putting the options in a file, we need to take care of the race
condition of multiple clients pushing. That is actually rather easy.

5) We only inject new lines as separator into the file, so it is possible
to transmit binaries ("attach an image to a code review").

[1] 'Shellshock' https://lwn.net/Articles/614218/

Signed-off-by: Stefan Beller 
---
 Documentation/githooks.txt |  4 
 builtin/receive-pack.c | 41 -
 2 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index d82e912..dc80574 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -247,6 +247,8 @@ Both standard output and standard error output are 
forwarded to
 'git send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
+The push options are available in the variable GIT_PUSH_OPTION_FILE.
+
 [[update]]
 update
 ~~
@@ -322,6 +324,8 @@ a sample script `post-receive-email` provided in the 
`contrib/hooks`
 directory in Git distribution, which implements sending commit
 emails.
 
+The push options are available in the variable GIT_PUSH_OPTION_FILE.
+
 [[post-update]]
 post-update
 ~~~
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 15c323a..0da6852 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -550,8 +550,16 @@ static void prepare_push_cert_sha1(struct child_process 
*proc)
}
 }
 
+struct receive_hook_feed_state {
+   struct command *cmd;
+   int skip_broken;
+   struct strbuf buf;
+   const char *push_options_file;
+};
+
 typedef int (*feed_fn)(void *, const char **, size_t *);
-static int run_and_feed_hook(const char *hook_name, feed_fn feed, void 
*feed_state)
+static int run_and_feed_hook(const char *hook_name, feed_fn feed,
+struct receive_hook_feed_state *feed_state)
 {
struct child_process proc = CHILD_PROCESS_INIT;
struct async muxer;
@@ -567,6 +575,9 @@ static int run_and_feed_hook(const char *hook_name, feed_fn 
feed, void *feed_sta
proc.argv = argv;
proc.in = -1;
proc.stdout_to_stderr = 1;
+   if (feed_state && feed_state->push_options_file)
+   argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_FILE=%s",
+feed_state->push_options_file);
 
if (use_sideband) {
memset(&muxer, 0, sizeof(muxer));
@@ -606,12 +617,6 @@ static int run_and_feed_hook(const char *hook_name, 
feed_fn feed, void *feed_sta
return finish_command(&proc);
 }
 
-struct receive_hook_feed_state {
-   struct command *cmd;
-   int skip_broken;
-   struct strbuf buf;
-};
-
 static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
 {
struct receive_hook_feed_state *state = state_;
@@ -634,8 +639,10 @@ static int feed_receive_hook(void *state_, const char 
**bufp, size_t *sizep)
return 0;
 }
 
-static int run_receive_hook(struct command *commands, const char *hook_name,
-   int skip_broken)
+static int run_receive_hook(struct command *commands,
+   const char *hook_name,
+   int skip_broken,
+   const char *push_options_file)
 {
struct receive_hook_feed_state state;
int status;
@@ -646,6 +653,7 @@ static int run_receive_hook(struct command *commands, const 
char *hook_name,
if (feed_receive_hook(&state, NULL, NULL))
return 0;
state.cmd = commands;
+   state.push_options_file = push_options_file;
status = run_and_feed_hook(hook_name, feed_r

[PATCH 3/4] push: accept push options

2016-06-29 Thread Stefan Beller
This implements everything that is required on the client side to make use
of push options from the porcelain push command.

Signed-off-by: Stefan Beller 
---
 Documentation/git-push.txt |  8 +++-
 builtin/push.c | 16 +---
 send-pack.c| 29 +
 send-pack.h|  3 +++
 transport.c|  2 ++
 transport.h|  7 +++
 6 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 19f46b6..b0b1273 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -11,7 +11,7 @@ SYNOPSIS
 [verse]
 'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | 
--dry-run] [--receive-pack=]
   [--repo=] [-f | --force] [-d | --delete] [--prune] [-v | 
--verbose]
-  [-u | --set-upstream]
+  [-u | --set-upstream] [--push-option=]
   [--[no-]signed|--sign=(true|false|if-asked)]
   [--force-with-lease[=[:]]]
   [--no-verify] [ [...]]
@@ -156,6 +156,12 @@ already exists on the remote side.
Either all refs are updated, or on error, no refs are updated.
If the server does not support atomic pushes the push will fail.
 
+-L::
+--push-option::
+   Transmit the given string to the server, which passes them to
+   the pre-receive as well as the post-receive hook. Only C strings
+   containing no new lines are allowed.
+
 --receive-pack=::
 --exec=::
Path to the 'git-receive-pack' program on the remote
diff --git a/builtin/push.c b/builtin/push.c
index 4e9e4db..418f786 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -353,7 +353,8 @@ static int push_with_options(struct transport *transport, 
int flags)
return 1;
 }
 
-static int do_push(const char *repo, int flags)
+static int do_push(const char *repo, int flags,
+  const struct string_list *push_options)
 {
int i, errs;
struct remote *remote = pushremote_get(repo);
@@ -376,6 +377,9 @@ static int do_push(const char *repo, int flags)
if (remote->mirror)
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 
+   if (push_options->nr)
+   flags |= TRANSPORT_PUSH_OPTIONS;
+
if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
if (!strcmp(*refspec, "refs/tags/*"))
return error(_("--all and --tags are incompatible"));
@@ -406,13 +410,16 @@ static int do_push(const char *repo, int flags)
for (i = 0; i < url_nr; i++) {
struct transport *transport =
transport_get(remote, url[i]);
+   if (flags & TRANSPORT_PUSH_OPTIONS)
+   transport->push_options = push_options;
if (push_with_options(transport, flags))
errs++;
}
} else {
struct transport *transport =
transport_get(remote, NULL);
-
+   if (flags & TRANSPORT_PUSH_OPTIONS)
+   transport->push_options = push_options;
if (push_with_options(transport, flags))
errs++;
}
@@ -500,6 +507,8 @@ int cmd_push(int argc, const char **argv, const char 
*prefix)
int push_cert = -1;
int rc;
const char *repo = NULL;/* default repository */
+   static struct string_list push_options = STRING_LIST_INIT_DUP;
+
struct option options[] = {
OPT__VERBOSITY(&verbosity),
OPT_STRING( 0 , "repo", &repo, N_("repository"), 
N_("repository")),
@@ -533,6 +542,7 @@ int cmd_push(int argc, const char **argv, const char 
*prefix)
  0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the 
push"),
  PARSE_OPT_OPTARG, option_parse_push_signed },
OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on 
remote side"), TRANSPORT_PUSH_ATOMIC),
+   OPT_STRING_LIST('L', "push-option", &push_options, 
N_("server-specific"), N_("options to transmit")),
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
TRANSPORT_FAMILY_IPV4),
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
@@ -563,7 +573,7 @@ int cmd_push(int argc, const char **argv, const char 
*prefix)
set_refspecs(argv + 1, argc - 1, repo);
}
 
-   rc = do_push(repo, flags);
+   rc = do_push(repo, flags, &push_options);
if (rc == -1)
usage_with_options(push_usage, options);
else
diff --git a/send-pack.c b/send-pack.c
index 37ee04e..17c30a1 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -261,6 +261,7 @@ static int generate_push_cert(struct strbuf *req_buf,
  const char *push_cert_nonce)
 {

[PATCH] builtin/apply: include declaration of cmd_apply()

2016-06-29 Thread Ramsay Jones

Signed-off-by: Ramsay Jones 
---

Hi Christian,

If you need to re-roll your 'cc/apply-am' branch, could you please
squash this into the relevant patch. Commit 95a3b0ba ("apply: move
libified code from builtin/apply.c to apply.{c,h}", 22-04-2016)
removed this '#include "builtin.h"' line, which causes sparse to
issue a warning.

Thanks!

ATB,
Ramsay Jones

 builtin/apply.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/apply.c b/builtin/apply.c
index 066cb29..9c66474 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "builtin.h"
 #include "parse-options.h"
 #include "lockfile.h"
 #include "apply.h"
-- 
2.9.0
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/9] Report bugs consistently

2016-06-29 Thread Johannes Sixt

Am 29.06.2016 um 13:36 schrieb Johannes Schindelin:

@@ -955,9 +955,8 @@ static struct merge_file_info merge_file_1(struct 
merge_options *o,

if (!sha_eq(a->sha1, b->sha1))
result.clean = 0;
-   } else {
-   die(_("unsupported object type in the tree"));
-   }
+   } else
+   die(_("BUG: unsupported object type in the tree"));


Would it perhaps make sense to remove the _() markup (here and a few 
more instances in this patch)? It's simpler for developers to find the 
code location when a "BUG:" is reported untranslated.


-- Hannes

--
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: git gui produces series of commits with exactly the same time

2016-06-29 Thread Andrei Faber

Hi everyone,

I've found one case when this bug happens.

1. Create a commit

2. Amend it

3. Create several new commits

All the new commits have the same "Author" timestamp until the git gui 
is restarted.


Can anyone reproduce this?

Best wishes,
Andrei Faber

On 29/06/2016 18:45, Johannes Schindelin wrote:

Hi Andrei,

On Wed, 29 Jun 2016, Andrei Faber wrote:


I've noticed that git history contains series of commits with exactly
the same time, despite the real commit time of these commits was
different. All these commit were made using the git gui tool. I'm the
only developer in this project.

Is it possible that you played games with your GIT_AUTHOR_DATE environment
variable?

Ciao,
Johannes



--
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] Refactor recv_sideband()

2016-06-29 Thread Lukas Fleischer
On Wed, 29 Jun 2016 at 18:40:16, Junio C Hamano wrote:
> Lukas, can you see what is in 'pu' after I push out today's
> integration result in several hours and tell us if you like the
> result of the SQUASH??? change?

Looks good to me. Thank you both for working on this. Note that you
should amend the last paragraph of the original commit message when you
squash Nicos patch into mine.

Oh, and one more detail: I wonder why we still use fwrite(), now that we
know we can use xwrite() which guarantees atomicity. Is there a reason
for that?

Regards,
Lukas
--
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: git tag --contains for cherry-picks

2016-06-29 Thread Jeff King
On Wed, Jun 29, 2016 at 12:48:33PM +0100, Laszlo Papp wrote:

> Old releases are maintained with important bug fixes or even new features
> in our case. It sometimes means that we need to cherry-pick commits across
> branches, like from master to a specific release branch.
> 
> Cherry-picking changes the hash of the commit, therefore, this may no
> longer work for cherry-picks:
> 
> git tag --contains
> 
> I am thinking of having something like:
> 
> git tag --contains-follow
> 
> which would follow cherry-picks. I am not sure how easily and/or
> efficiently this can be implemented, but my gut feeling is that in the vast
> majority of the cases, the content check would bail out already at the
> "subject line".

Git generally considers commits "equivalent" based on the patch-id, whic
his a sha1 of the diff (modulo some canonicalization).

So you could ask right now for the patch-id of a particular commit:

  git show $commit | git patch-id >needle

and then the patch-id of all tagged commits:

  git log -p --tags | git patch-id | sort >haystack

Each line will have the patch-id followed by the commit id. You can then
correlate them (join is part of GNU coreutils):

  join needle haystack | cut -d' ' -f2- >synonyms

That gives you a list of synonym commits, which you can use to ask git
which tags contain any of them:

  git tag $(for i in $(cat synonyms); do echo "--contains $i"; done)

The big downside is that generating the haystack is expensive (it has to
do a diff on every commit). But if this is something you do a lot, you
can save the haystack and incrementally update it with new commits.


Of course there are other ways of determining commit equivalence. You
could find ones with duplicate commit messages, or duplicate subjects,
or whatever. But if you have a cherry-picking workflow, I suspect the
easiest thing may be to simply use "git cherry-pick -x", which will
write the sha1 of the original commit into the cherry-picked commit
message. You can then use that to correlate directly.

So there's no specific "--contains-follow" as you want, but the tools
are there to do it (and more flexibly and efficiently, depending on your
needs). That doesn't necessarily mean it's not a good idea to make the
simple case easier, though.

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


Re: preview: What's cooking in git.git (Jun 2016, #10; Tue, 28)

2016-06-29 Thread Jeff King
On Wed, Jun 29, 2016 at 01:47:31PM +0200, Johannes Schindelin wrote:

> On Tue, 28 Jun 2016, Junio C Hamano wrote:
> 
> > * jk/ansi-color (2016-06-23) 7 commits
> >   (merged to 'next' on 2016-06-28 at 354989c)
> >  + color: support strike-through attribute
> >  + color: support "italic" attribute
> >  + color: allow "no-" for negating attributes
> >  + color: refactor parse_attr
> >  + add skip_prefix_mem helper
> >  + doc: refactor description of color format
> >  + color: fix max-size comment
> > 
> >  The output coloring scheme learned two new attributes, italic and
> >  strike, in addition to existing bold, reverse, etc.
> > 
> >  Will merge to 'master'.
> 
> Please note that those "colors" do not work on Windows, at least as far as
> I know, I only skimmed the code in set_attr():
> 
>   https://github.com/git/git/blob/v2.9.0/compat/winansi.c#L175-L314
> 
> ... and it looks as if italic is plainly unsupported, and strike-through
> is not handled.

I suspect winansi doesn't handle 256-color or 24-bit color modes either,
and those are also not supported on all terminals. All of the color
output is subject to the user's terminal supporting it.  It might be
that we should make a more clear disclaimer in the documentation.

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


Re: [PATCH v2 0/7] literal formatting in documentation

2016-06-29 Thread Jeff King
On Tue, Jun 28, 2016 at 01:40:08PM +0200, Matthieu Moy wrote:

> This should address all comments from Peff.

Thanks. The review is mind-numbing enough that I didn't do a complete
read-through again, but just spot-checked a few places. This version
looks good to me.

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


Re: [PATCH] t/Makefile: add a rule to re-run previously-failed tests

2016-06-29 Thread Jeff King
On Wed, Jun 29, 2016 at 09:02:37AM +0200, Johannes Schindelin wrote:

> It is the most convenient way to determine which tests failed after
> running the entire test suite, in parallel, to look for left-over "trash
> directory.t*" subdirectories in the t/ subdirectory.

As Junio noted, this doesn't work with --root. I have sometimes used:

  grep 'failed [^0]' test-results/*

for this purpose.

> This patch automates the process of determinig which tests failed
> previously and re-running them; It turned out to be quite convenient
> when trying to squash bugs that crept in during rebases.

I suspect your response will be "perl tools on Windows are too painful
to use", but the "prove" tool which comes with perl can do this and more
(e.g., running the failed tests first, and then following up with the
others to double-check), and our test suite supports it quite well.

  $ grep -B1 PROVE config.mak
  # run tests in parallel, with slow ones first to keep pipelines full
  GIT_PROVE_OPTS = -j16 --state=slow,save

  $ cd t
  $ make prove
  ... reports some test failed ...
  $ prove --state=failed
  ... re-runs just the failed test ...

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


[PATCH] t/Makefile: add a rule to re-run previously-failed tests

2016-06-29 Thread Johannes Schindelin
While developing patch series, it is a good practice to run the test
suite from time to time, just to make sure that obvious bugs are caught
early. With complex patch series, it is common to run `make -j15 -k
test`, i.e. run the tests in parallel and not stop at the first failing
test but continue. This has the advantage of identifying possibly
multiple problems without having to wait for the complete test suite to
finish.

It is particularly important to reduce the turn-around time thusly on
Windows, where the test suite spends 45 minutes on the computer on which
this patch was developed.

It is the most convenient way to determine which tests failed after
running the entire test suite, in parallel, to look for left-over "trash
directory.t*" subdirectories in the t/ subdirectory.

This patch automates the process of determinig which tests failed
previously and re-running them; It turned out to be quite convenient
when trying to squash bugs that crept in during rebases.

Signed-off-by: Johannes Schindelin 
---
Published-As: https://github.com/dscho/git/releases/tag/failing-tests-v1
 t/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/t/Makefile b/t/Makefile
index 18e2b28..1459a7f 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -35,6 +35,8 @@ all: $(DEFAULT_TEST_TARGET)
 test: pre-clean $(TEST_LINT)
$(MAKE) aggregate-results-and-cleanup
 
+failed: $(patsubst trash,,$(patsubst directory.%,%.sh,$(wildcard trash\ 
directory.t[0-9]*)))
+
 prove: pre-clean $(TEST_LINT)
@echo "*** prove ***"; $(PROVE) --exec '$(SHELL_PATH_SQ)' 
$(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
$(MAKE) clean-except-prove-cache
-- 
2.9.0.118.g0e1a633

base-commit: cf4c2cfe52be5bd973a4838f73a35d3959ce2f43
--
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: git svn clone segmentation faul issue

2016-06-29 Thread Johannes Schindelin
Hi Yannis,

On Tue, 28 Jun 2016, Johannes Schindelin wrote:

> On Tue, 28 Jun 2016, Ioannis Kappas wrote:
> 
> > Johannes Schindelin  gmx.de> writes:
> > 
> > > Would you mind giving them a whirl?
> > 
> > The patch in "source code (zip)" seems to be missing the line in the prepare
> > () section of PKGBUILD to actually apply the fix:
> > 
> > diff --git a/subversion/PKGBUILD b/subversion/PKGBUILD
> > --- a/subversion/PKGBUILD
> > +++ b/subversion/PKGBUILD
> > 
> > @@ -101,6 +103,7 @@ prepare() {
> >patch -p1 -i ${srcdir}/17-fix-test-link.patch
> >patch -p1 -i ${srcdir}/18-fix-serf-config.patch
> >patch -p1 -i ${srcdir}/19-remove-contrib-from-configure.patch
> > +  patch -p1 -i ${srcdir}/20-fix-stack-corruption-in-swig-wrappers.patch
> >patch -p1 -i ${srcdir}/subversion-1.9.1-msys2.patch
> >patch -p1 -i ${srcdir}/remove-checking-symlink.patch
> >patch -p1 -i ${srcdir}/90-use-copy-instead-symlink.patch
> > 
> > 
> > Would you be so kind to add the above and rebuild. 
> 
> Oh bummer. Sorry for that! I will fix it and rebuild tomorrow.
> 
> > I have just tested it locally to work successfully, but I do not mind 
> > retesting if you wish to provide another build :)
> 
> Thanks, that would be much appreciated! I'll send a reply when I rebuilt
> the packages.

I just re-uploaded new packages, after rebuilding them and making sure
that the patch was actually applied.

May I ask you to re-test, just to make extra sure that the bug in question
is fixed?

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


[PATCH v2] git-p4: place temporary refs used for branch import under refs/git-p4-tmp

2016-06-29 Thread larsxschneider
From: Lars Schneider 

Git-P4 used to place temporary refs under "git-p4-tmp". Since 3da1f37
Git checks that all refs are placed under "refs". Instruct Git-P4 to
place temporary refs under "refs/git-p4-tmp". There are no backwards
compatibility considerations as these refs are transient.

Use "git show-ref --verify" to check the (non-)existience of the refs
instead of file checks assuming the file-based ref backend.

All refs under "refs" are shared across all worktrees. This is not
desired for temporary Git-P4 refs and will be adressed in a later patch.

Signed-off-by: Lars Schneider 
---

Thank you Hannes for the sharp eye!

diff to v1:
* check non-existence of refs/git-p4-tmp instead of ref/git-p4-tmp
* use refs/git-p4-tmp instead of ref/git-p4-tmp in commit message
* check reference with "git show-ref --verify" to be future-proof (thanks 
Junio!)

Cheers,
Lars


 git-p4.py| 2 +-
 t/t9801-git-p4-branch.sh | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/git-p4.py b/git-p4.py
index b6593cf..6b252df 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -2274,7 +2274,7 @@ class P4Sync(Command, P4UserMap):
 self.useClientSpec_from_options = False
 self.clientSpecDirs = None
 self.tempBranches = []
-self.tempBranchLocation = "git-p4-tmp"
+self.tempBranchLocation = "refs/git-p4-tmp"
 self.largeFileSystem = None

 if gitConfig('git-p4.largeFileSystem'):
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index 0aafd03..6a86d69 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -300,7 +300,7 @@ test_expect_success 'git p4 clone complex branches' '
test_path_is_file file2 &&
test_path_is_file file3 &&
! grep update file2 &&
-   test_path_is_missing .git/git-p4-tmp
+   test_must_fail git show-ref --verify refs/git-p4-tmp
)
 '

@@ -352,7 +352,7 @@ test_expect_success 'git p4 sync changes to two branches in 
the same changelist'
test_path_is_file file2 &&
test_path_is_file file3 &&
! grep update file2 &&
-   test_path_is_missing .git/git-p4-tmp
+   test_must_fail git show-ref --verify refs/git-p4-tmp
)
 '

--
2.5.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: What's happening to the index

2016-06-29 Thread Matthieu Moy
"Andy Falanga (afalanga)"  writes:

> The strange thing now is, after the script exits, I then call "git 
> fetch" in the recipe.  I can see from the output of make that the remote 
> db is fetched.  However, when I call "git show 
> origin/rpm:path/to/rpm_build_num" from the makefile I get the *previous* 
> number.  Yet, as soon as the make process exits, I call "git show 
> origin/rpm:path/to/rpm_build_num" and it shows the correct number!

My bet would be that you are running the commands in two different
repositories. Try running

  pwd && git show origin/rpm:path/to/rpm_build_num

In the Makefile and after make completes, and check that pwd returns the
same thing. Also, to avoid getting the issue you previously had, try

  cd $(pwd) && pwd && git show origin/rpm:path/to/rpm_build_num

too.

> Is there some sort of strange file caching that happening
> when make starts that, although the local db is updated, I don't get
> what I'm after?

Git can keep information either in RAM, hence not shared between git
invocations (so running git within or outside the Makefile wouldn't
matter), or on disk, but then inside or outside the Makefile doesn't
matter either.

-- 
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: git svn clone segmentation faul issue

2016-06-29 Thread Ioannis Kappas
Hi Eric,

Eric Wong  80x24.org> writes:

> 
> Ioannis.Kappas  rbs.com wrote:
> > Fortunately, a patch has already been submitted to subversion
> > with (github) revision
> > a074af86c8764404b28ce99d0bedcb668a321408 (at
> > 
https://github.com/apache/subversion/commit/a074af86c8764404b28ce99d0bedcb66
8a321408
> > ) on the trunk to handle this and a couple of other similar
> > cases. But by the looks of it has not been picked up yet in
> > the latest subversion 1.9.4 release or the 1.9.x branch,
> > perhaps because this patch was identified in sanity checks
> > rather than coming out from a perceivable production issue?
> 
> Thank you for documenting this.  Curious, does this affect older
> SVN versions or only 1.9.x?

It does not appear so, at least not in the degree of failures that I am 
seeing it now, i.e. failing consistently. It only came to my attention 
after I upgraded to the latest git/perl/subversion release from a version 
that was more than a year's old.

Given that the issue is with corruption in the perl interpreter stack, I 
suspect is due to one, or combination, of the following:

- git in latest releases makes additional perl subversion calls, thus 
affecting the perl stack usage.
- perl in latest releases affected the stack allocation profile.
- subversion perl module in latest releases refactored/added new calls that 
has changed the perl stack usage.

> 
> I don't know Perl internals well or SWIG at all; so reports
> like these are very much appreciated.
> 

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


git gui produces series of commits with exactly the same time

2016-06-29 Thread Andrei Faber

Hi everyone,

I've noticed that git history contains series of commits with exactly 
the same time, despite the real commit time of these commits was 
different. All these commit were made using the git gui tool. I'm the 
only developer in this project.


Has anyone experienced the same problem?

(I'm currently using Git 2.9.0 x64 under Windows.)


--
Best wishes,
Andrei Faber

--
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: git svn clone segmentation faul issue

2016-06-29 Thread Ioannis Kappas
Hi Johannes,

Johannes Schindelin  gmx.de> writes:

> 
> Hi Yannis,
> 
> [...]
> 
> I just re-uploaded new packages, after rebuilding them and making sure
> that the patch was actually applied.
> 
> May I ask you to re-test, just to make extra sure that the bug in question
> is fixed?

I confirm the latest version, built from the 'source files (zip)' package, 
has resolved the issue.

Thanks for the prompt response! Next task is to get the patch through to 
the next subversion official release.

> 
> Ciao,
> Johannes
> 




--
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/9] Use merge_recursive() directly in the builtin am

2016-06-29 Thread Johannes Schindelin
This is the long-awaited re-roll of the attempt to avoid spawning
merge-recursive from the builtin am and use merge_recursive() directly
instead.

As indicated in the message of the final commit, the performance
improvement is modest, if noticable.

The *real* reason for the reroll is that I need a libified recursive
merge to accelerate the interactive rebase by teaching the sequencer to
do rebase -i's grunt work.

In other words, this is one of those 13 (now 14) patch series leading up
to a faster interactive rebase.

It did take quite a while to go through the code "with a fine-toothed
comb", and it did turn up a few surprises.

For example, the recursive merge calls remove_file() a couple of times
but actually does not always care about the return value, and rightfully
so. When updating a working tree, for example, where a file was
replaced by a directory, the code may create the directory first
(implicitly deleting the file) and only then attempt to remove the file,
failing because it is a directory already.

One might argue that this logic is flawed, then, and I would agree.
Right now my focus is on rebase -i and I want to avoid getting
side-tracked by the recursive merge logic. So the clean-up will need to
wait for another day (or week).

We also need to be extra careful to retain backwards-compatibility. The
test script t6022-merge-rename.sh, for example, verifies that `git pull`
exits with status 128 in case of a fatal error. To that end, we need to
make sure that fatal errors are handled by existing (builtin) users via
exit(128) (or die(), which calls exit(128) at the end). New users (such
as a builtin helper doing rebase -i's grunt work) may want to print some
helpful advice what happened and how to get out of this mess before
erroring out.

In contrast to the original attempt at libifying merge_recursive() (as
part of fixing a regression in the builtin am which wanted to print some
advice, but could not, because the merge machinery die()d before it
could), I no longer use the "gently" flag. Better to get it right to
begin with: fatal errors are indicated by a negative return value. No
dying without proper cause.

In an earlier iteration of this patch series which was not sent to the
mailing list, I used the special return vale -128 to indicate "real
fatal errors". This turned out to be unnecessary: returning -1 always,
to indicate that the operation could not complete successfully, is the
appropriate way to handle all errors.

As this patch series touches rather important code, I would really
appreciate thorough reviews, with a particular focus on what regressions
this patch series might introduce.


Johannes Schindelin (8):
  Report bugs consistently
  merge-recursive: clarify code in was_tracked()
  Prepare the builtins for a libified merge_recursive()
  merge_recursive: abort properly upon errors
  merge-recursive: avoid returning a wholesale struct
  merge-recursive: allow write_tree_from_memory() to error out
  merge-recursive: handle return values indicating errors
  merge-recursive: switch to returning errors instead of dying

Junio C Hamano (1):
  am: make a direct call to merge_recursive

 builtin/am.c   |  27 ++--
 builtin/checkout.c |   4 +-
 builtin/ls-files.c |   3 +-
 builtin/merge.c|   4 +
 builtin/update-index.c |   2 +-
 grep.c |   8 +-
 imap-send.c|   2 +-
 merge-recursive.c  | 397 ++---
 sequencer.c|   4 +
 sha1_file.c|   4 +-
 trailer.c  |   2 +-
 transport.c|   2 +-
 wt-status.c|   4 +-
 13 files changed, 279 insertions(+), 184 deletions(-)

Published-As: 
https://github.com/dscho/git/releases/tag/am-3-merge-recursive-direct-v1
-- 
2.9.0.268.gcabc8b0

base-commit: cf4c2cfe52be5bd973a4838f73a35d3959ce2f43
--
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/9] Report bugs consistently

2016-06-29 Thread Johannes Schindelin
The vast majority of error messages in Git's source code which report a
bug use the convention to prefix the message with "BUG:".

As part of cleaning up merge-recursive to stop die()ing except in case of
detected bugs, let's just make the remainder of the bug reports consistent
with the de facto rule.

Signed-off-by: Johannes Schindelin 
---
 builtin/ls-files.c |  3 ++-
 builtin/update-index.c |  2 +-
 grep.c |  8 
 imap-send.c|  2 +-
 merge-recursive.c  | 13 ++---
 sha1_file.c|  4 ++--
 trailer.c  |  2 +-
 transport.c|  2 +-
 wt-status.c|  4 ++--
 9 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index f02e3d2..00ea91a 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -118,7 +118,8 @@ static void show_killed_files(struct dir_struct *dir)
 */
pos = cache_name_pos(ent->name, ent->len);
if (0 <= pos)
-   die("bug in show-killed-files");
+   die("BUG: killed-file %.*s not found",
+   ent->len, ent->name);
pos = -pos - 1;
while (pos < active_nr &&
   ce_stage(active_cache[pos]))
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 6cdfd5f..ba04b19 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -1146,7 +1146,7 @@ int cmd_update_index(int argc, const char **argv, const 
char *prefix)
report(_("Untracked cache enabled for '%s'"), 
get_git_work_tree());
break;
default:
-   die("Bug: bad untracked_cache value: %d", untracked_cache);
+   die("BUG: bad untracked_cache value: %d", untracked_cache);
}
 
if (active_cache_changed) {
diff --git a/grep.c b/grep.c
index 1e15b62..f1ca0a0 100644
--- a/grep.c
+++ b/grep.c
@@ -643,10 +643,10 @@ static struct grep_expr *prep_header_patterns(struct 
grep_opt *opt)
 
for (p = opt->header_list; p; p = p->next) {
if (p->token != GREP_PATTERN_HEAD)
-   die("bug: a non-header pattern in grep header list.");
+   die("BUG: a non-header pattern in grep header list.");
if (p->field < GREP_HEADER_FIELD_MIN ||
GREP_HEADER_FIELD_MAX <= p->field)
-   die("bug: unknown header field %d", p->field);
+   die("BUG: unknown header field %d", p->field);
compile_regexp(p, opt);
}
 
@@ -659,7 +659,7 @@ static struct grep_expr *prep_header_patterns(struct 
grep_opt *opt)
 
h = compile_pattern_atom(&pp);
if (!h || pp != p->next)
-   die("bug: malformed header expr");
+   die("BUG: malformed header expr");
if (!header_group[p->field]) {
header_group[p->field] = h;
continue;
@@ -1464,7 +1464,7 @@ static int grep_source_1(struct grep_opt *opt, struct 
grep_source *gs, int colle
case GREP_BINARY_TEXT:
break;
default:
-   die("bug: unknown binary handling mode");
+   die("BUG: unknown binary handling mode");
}
}
 
diff --git a/imap-send.c b/imap-send.c
index 938c691..cd39805 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -511,7 +511,7 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, 
...)
 
va_start(va, fmt);
if (blen <= 0 || (unsigned)(ret = vsnprintf(buf, blen, fmt, va)) >= 
(unsigned)blen)
-   die("Fatal: buffer too small. Please report a bug.");
+   die("BUG: buffer too small (%d < %d)", ret, blen);
va_end(va);
return ret;
 }
diff --git a/merge-recursive.c b/merge-recursive.c
index 65cb5d6..98f4632 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -259,7 +259,7 @@ struct tree *write_tree_from_memory(struct merge_options *o)
fprintf(stderr, "BUG: %d %.*s\n", ce_stage(ce),
(int)ce_namelen(ce), ce->name);
}
-   die("Bug in merge-recursive.c");
+   die("BUG: unmerged index entries in merge-recursive.c");
}
 
if (!active_cache_tree)
@@ -955,9 +955,8 @@ static struct merge_file_info merge_file_1(struct 
merge_options *o,
 
if (!sha_eq(a->sha1, b->sha1))
result.clean = 0;
-   } else {
-   die(_("unsupported object type in the tree"));
-   }
+   } else
+   die(_("BUG: unsupported object t

[PATCH 2/9] merge-recursive: clarify code in was_tracked()

2016-06-29 Thread Johannes Schindelin
It can be puzzling to see that was_tracked() tries to match an index
entry by name even if cache_name_pos() returned a negative value. Let's
clarify that cache_name_pos() implicitly looks for stage 0, while we are
also okay with finding other stages.

Signed-off-by: Johannes Schindelin 
---
 merge-recursive.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/merge-recursive.c b/merge-recursive.c
index 98f4632..bcb53f0 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -658,6 +658,7 @@ static int was_tracked(const char *path)
 {
int pos = cache_name_pos(path, strlen(path));
 
+   /* cache_name_pos() looks for stage == 0, so pos may be < 0 */
if (pos < 0)
pos = -1 - pos;
while (pos < active_nr &&
-- 
2.9.0.268.gcabc8b0


--
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/9] merge-recursive: handle return values indicating errors

2016-06-29 Thread Johannes Schindelin
We are about to libify the recursive merge machinery, where we only
die() in case of a bug or memory contention. To that end, we must heed
negative return values as indicating errors.

This requires our functions to be careful to pass through error
conditions in call chains, and for quite a few functions this means
that they have to return values to begin with.

The next step will be to convert the places where we currently die() to
return negative values (read: -1) instead.

Note that we ignore errors reported by make_room_for_path(), consistent
with the previous behavior (update_file_flags() used the return value of
make_room_for_path() only to indicate an early return, but not a fatal
error): if the error is really a fatal error, we will notice later; If
not, it was not that serious a problem to begin with. (Witnesses in
favor of this reasoning are t4151-am-abort and t7610-mergetool, which
would start failing if we stopped on errors reported by
make_room_for_path()).

Signed-off-by: Johannes Schindelin 
---
 merge-recursive.c | 251 ++
 1 file changed, 158 insertions(+), 93 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index 6ab7dfc..bb075e3 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -266,8 +266,10 @@ struct tree *write_tree_from_memory(struct merge_options 
*o)
active_cache_tree = cache_tree();
 
if (!cache_tree_fully_valid(active_cache_tree) &&
-   cache_tree_update(&the_index, 0) < 0)
-   die(_("error building trees"));
+   cache_tree_update(&the_index, 0) < 0) {
+   error(_("error building trees"));
+   return NULL;
+   }
 
result = lookup_tree(active_cache_tree->sha1);
 
@@ -548,19 +550,17 @@ static int update_stages(const char *path, const struct 
diff_filespec *o,
 */
int clear = 1;
int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_SKIP_DFCHECK;
+   int ret = 0;
+
if (clear)
-   if (remove_file_from_cache(path))
-   return -1;
-   if (o)
-   if (add_cacheinfo(o->mode, o->sha1, path, 1, 0, options))
-   return -1;
-   if (a)
-   if (add_cacheinfo(a->mode, a->sha1, path, 2, 0, options))
-   return -1;
-   if (b)
-   if (add_cacheinfo(b->mode, b->sha1, path, 3, 0, options))
-   return -1;
-   return 0;
+   ret = remove_file_from_cache(path);
+   if (!ret && o)
+   ret = add_cacheinfo(o->mode, o->sha1, path, 1, 0, options);
+   if (!ret && a)
+   ret = add_cacheinfo(a->mode, a->sha1, path, 2, 0, options);
+   if (!ret && b)
+   ret = add_cacheinfo(b->mode, b->sha1, path, 3, 0, options);
+   return ret;
 }
 
 static void update_entry(struct stage_data *entry,
@@ -736,7 +736,7 @@ static int make_room_for_path(struct merge_options *o, 
const char *path)
return error(msg, path, _(": perhaps a D/F conflict?"));
 }
 
-static void update_file_flags(struct merge_options *o,
+static int update_file_flags(struct merge_options *o,
  const unsigned char *sha,
  unsigned mode,
  const char *path,
@@ -777,8 +777,7 @@ static void update_file_flags(struct merge_options *o,
 
if (make_room_for_path(o, path) < 0) {
update_wd = 0;
-   free(buf);
-   goto update_index;
+   goto free_buf;
}
if (S_ISREG(mode) || (!has_symlinks && S_ISLNK(mode))) {
int fd;
@@ -801,20 +800,22 @@ static void update_file_flags(struct merge_options *o,
} else
die(_("do not know what to do with %06o %s '%s'"),
mode, sha1_to_hex(sha), path);
+free_buf:
free(buf);
}
  update_index:
if (update_cache)
add_cacheinfo(mode, sha, path, 0, update_wd, 
ADD_CACHE_OK_TO_ADD);
+   return 0;
 }
 
-static void update_file(struct merge_options *o,
+static int update_file(struct merge_options *o,
int clean,
const unsigned char *sha,
unsigned mode,
const char *path)
 {
-   update_file_flags(o, sha, mode, path, o->call_depth || clean, 
!o->call_depth);
+   return update_file_flags(o, sha, mode, path, o->call_depth || clean, 
!o->call_depth);
 }
 
 /* Low level file merging, update and removal */
@@ -1010,7 +1011,7 @@ static int merge_file_one(struct merge_options *o,
return merge_file_1(o, &one, &a, &b, branch1, branch2, mfi);
 }
 
-static void handle_change_delete(struct merge_options *o,
+static int handle_change_delete(struct merge_options *o,
 const ch

[PATCH 4/9] merge_recursive: abort properly upon errors

2016-06-29 Thread Johannes Schindelin
There are a couple of places where return values indicating errors
are ignored. Let's teach them manners.

Signed-off-by: Johannes Schindelin 
---
 merge-recursive.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index bcb53f0..c4ece96 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1944,8 +1944,9 @@ int merge_recursive(struct merge_options *o,
saved_b2 = o->branch2;
o->branch1 = "Temporary merge branch 1";
o->branch2 = "Temporary merge branch 2";
-   merge_recursive(o, merged_common_ancestors, iter->item,
-   NULL, &merged_common_ancestors);
+   if (merge_recursive(o, merged_common_ancestors, iter->item,
+   NULL, &merged_common_ancestors) < 0)
+   return -1;
o->branch1 = saved_b1;
o->branch2 = saved_b2;
o->call_depth--;
@@ -1961,6 +1962,8 @@ int merge_recursive(struct merge_options *o,
o->ancestor = "merged common ancestors";
clean = merge_trees(o, h1->tree, h2->tree, 
merged_common_ancestors->tree,
&mrtree);
+   if (clean < 0)
+   return clean;
 
if (o->call_depth) {
*result = make_virtual_commit(mrtree, "merged tree");
@@ -2017,6 +2020,9 @@ int merge_recursive_generic(struct merge_options *o,
hold_locked_index(lock, 1);
clean = merge_recursive(o, head_commit, next_commit, ca,
result);
+   if (clean < 0)
+   return clean;
+
if (active_cache_changed &&
write_locked_index(&the_index, lock, COMMIT_LOCK))
return error(_("Unable to write index."));
-- 
2.9.0.268.gcabc8b0


--
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/9] merge-recursive: avoid returning a wholesale struct

2016-06-29 Thread Johannes Schindelin
It is technically allowed, as per C89, for functions' return type to
be complete structs (i.e. *not* just pointers to structs), but it is
bad practice.

This is a very late attempt to contain the damage done by this developer
in 6d297f8 (Status update on merge-recursive in C, 2006-07-08) which
introduced such a return type.

It will also help the current effort to libify merge-recursive.c, as
it will allow us to return proper error codes later.

Signed-off-by: Johannes Schindelin 
---
 merge-recursive.c | 93 ++-
 1 file changed, 50 insertions(+), 43 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index c4ece96..d56651c9 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -888,47 +888,47 @@ static int merge_3way(struct merge_options *o,
return merge_status;
 }
 
-static struct merge_file_info merge_file_1(struct merge_options *o,
+static int merge_file_1(struct merge_options *o,
   const struct diff_filespec *one,
   const struct diff_filespec *a,
   const struct diff_filespec *b,
   const char *branch1,
-  const char *branch2)
+  const char *branch2,
+  struct merge_file_info *result)
 {
-   struct merge_file_info result;
-   result.merge = 0;
-   result.clean = 1;
+   result->merge = 0;
+   result->clean = 1;
 
if ((S_IFMT & a->mode) != (S_IFMT & b->mode)) {
-   result.clean = 0;
+   result->clean = 0;
if (S_ISREG(a->mode)) {
-   result.mode = a->mode;
-   hashcpy(result.sha, a->sha1);
+   result->mode = a->mode;
+   hashcpy(result->sha, a->sha1);
} else {
-   result.mode = b->mode;
-   hashcpy(result.sha, b->sha1);
+   result->mode = b->mode;
+   hashcpy(result->sha, b->sha1);
}
} else {
if (!sha_eq(a->sha1, one->sha1) && !sha_eq(b->sha1, one->sha1))
-   result.merge = 1;
+   result->merge = 1;
 
/*
 * Merge modes
 */
if (a->mode == b->mode || a->mode == one->mode)
-   result.mode = b->mode;
+   result->mode = b->mode;
else {
-   result.mode = a->mode;
+   result->mode = a->mode;
if (b->mode != one->mode) {
-   result.clean = 0;
-   result.merge = 1;
+   result->clean = 0;
+   result->merge = 1;
}
}
 
if (sha_eq(a->sha1, b->sha1) || sha_eq(a->sha1, one->sha1))
-   hashcpy(result.sha, b->sha1);
+   hashcpy(result->sha, b->sha1);
else if (sha_eq(b->sha1, one->sha1))
-   hashcpy(result.sha, a->sha1);
+   hashcpy(result->sha, a->sha1);
else if (S_ISREG(a->mode)) {
mmbuffer_t result_buf;
int merge_status;
@@ -940,62 +940,63 @@ static struct merge_file_info merge_file_1(struct 
merge_options *o,
die(_("Failed to execute internal merge"));
 
if (write_sha1_file(result_buf.ptr, result_buf.size,
-   blob_type, result.sha))
+   blob_type, result->sha))
die(_("Unable to add %s to database"),
a->path);
 
free(result_buf.ptr);
-   result.clean = (merge_status == 0);
+   result->clean = (merge_status == 0);
} else if (S_ISGITLINK(a->mode)) {
-   result.clean = merge_submodule(result.sha,
+   result->clean = merge_submodule(result->sha,
   one->path, one->sha1,
   a->sha1, b->sha1,
   !o->call_depth);
} else if (S_ISLNK(a->mode)) {
-   hashcpy(result.sha, a->sha1);
+   hashcpy(result->sha, a->sha1);
 
if (!sha_eq(a->sha1, b->sha1))
-   result.clean = 0;
+   result->clean = 0;
} else
die(_("BUG: unsup

[PATCH 6/9] merge-recursive: allow write_tree_from_memory() to error out

2016-06-29 Thread Johannes Schindelin
It is possible that a tree cannot be written (think: disk full). We
will want to give the caller a chance to clean up instead of letting
the program die() in such a case.

Signed-off-by: Johannes Schindelin 
---
 merge-recursive.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index d56651c9..6ab7dfc 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1875,8 +1875,8 @@ int merge_trees(struct merge_options *o,
else
clean = 1;
 
-   if (o->call_depth)
-   *result = write_tree_from_memory(o);
+   if (o->call_depth && !(*result = write_tree_from_memory(o)))
+   return -1;
 
return clean;
 }
-- 
2.9.0.268.gcabc8b0


--
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 8/9] merge-recursive: switch to returning errors instead of dying

2016-06-29 Thread Johannes Schindelin
The recursive merge machinery is supposed to be a library function, i.e.
it should return an error when it fails. Originally the functions were
part of the builtin "merge-recursive", though, where it was simpler to
call die() and be done with error handling.

The existing callers were already prepared to detect negative return
values to indicate errors and to behave as previously: exit with code 128
(which is the same thing that die() does, after printing the message).

Signed-off-by: Johannes Schindelin 
---
 merge-recursive.c | 55 ++-
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index bb075e3..d5a593c 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -710,12 +710,10 @@ static int make_room_for_path(struct merge_options *o, 
const char *path)
/* Make sure leading directories are created */
status = safe_create_leading_directories_const(path);
if (status) {
-   if (status == SCLD_EXISTS) {
+   if (status == SCLD_EXISTS)
/* something else exists */
-   error(msg, path, _(": perhaps a D/F conflict?"));
-   return -1;
-   }
-   die(msg, path, "");
+   return error(msg, path, _(": perhaps a D/F conflict?"));
+   return error(msg, path, "");
}
 
/*
@@ -743,6 +741,8 @@ static int update_file_flags(struct merge_options *o,
  int update_cache,
  int update_wd)
 {
+   int ret = 0;
+
if (o->call_depth)
update_wd = 0;
 
@@ -763,9 +763,11 @@ static int update_file_flags(struct merge_options *o,
 
buf = read_sha1_file(sha, &type, &size);
if (!buf)
-   die(_("cannot read object %s '%s'"), sha1_to_hex(sha), 
path);
-   if (type != OBJ_BLOB)
-   die(_("blob expected for %s '%s'"), sha1_to_hex(sha), 
path);
+   return error(_("cannot read object %s '%s'"), 
sha1_to_hex(sha), path);
+   if (type != OBJ_BLOB) {
+   ret = error(_("blob expected for %s '%s'"), 
sha1_to_hex(sha), path);
+   goto free_buf;
+   }
if (S_ISREG(mode)) {
struct strbuf strbuf = STRBUF_INIT;
if (convert_to_working_tree(path, buf, size, &strbuf)) {
@@ -786,8 +788,10 @@ static int update_file_flags(struct merge_options *o,
else
mode = 0666;
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
-   if (fd < 0)
-   die_errno(_("failed to open '%s'"), path);
+   if (fd < 0) {
+   ret = error_errno(_("failed to open '%s'"), 
path);
+   goto free_buf;
+   }
write_in_full(fd, buf, size);
close(fd);
} else if (S_ISLNK(mode)) {
@@ -795,18 +799,18 @@ static int update_file_flags(struct merge_options *o,
safe_create_leading_directories_const(path);
unlink(path);
if (symlink(lnk, path))
-   die_errno(_("failed to symlink '%s'"), path);
+   ret = error_errno(_("failed to symlink '%s'"), 
path);
free(lnk);
} else
-   die(_("do not know what to do with %06o %s '%s'"),
-   mode, sha1_to_hex(sha), path);
+   ret = error_errno(_("do not know what to do with %06o 
%s '%s'"),
+   mode, sha1_to_hex(sha), path);
 free_buf:
free(buf);
}
  update_index:
-   if (update_cache)
+   if (!ret && update_cache)
add_cacheinfo(mode, sha, path, 0, update_wd, 
ADD_CACHE_OK_TO_ADD);
-   return 0;
+   return ret;
 }
 
 static int update_file(struct merge_options *o,
@@ -932,20 +936,22 @@ static int merge_file_1(struct merge_options *o,
hashcpy(result->sha, a->sha1);
else if (S_ISREG(a->mode)) {
mmbuffer_t result_buf;
-   int merge_status;
+   int ret = 0, merge_status;
 
merge_status = merge_3way(o, &result_buf, one, a, b,
  branch1, branch2);
 
if ((merge_status < 0) || !result_buf.ptr)
-   die(_("Failed to execute internal merge"));
+   ret = error(_("Failed to execute internal 
merge"));
 
-   if (write_sha1_file(resul

[PATCH 3/9] Prepare the builtins for a libified merge_recursive()

2016-06-29 Thread Johannes Schindelin
A truly libified function does not die() just for fun. As such, the
recursive merge will convert all die() calls to return -1 instead in the
next commits, giving the caller a chance at least to print some helpful
message.

Let's prepare the builtins for this fatal error condition, even if we do
not really do more than imitating the previous die()'s exit(128): this is
what callers of e.g. `git merge` have come to expect.

Note that the callers of the sequencer (revert and cherry-pick) already
fail fast even for the return value -1; The only difference is that they
now get a chance to say " failed".

Signed-off-by: Johannes Schindelin 
---
 builtin/checkout.c | 4 +++-
 builtin/merge.c| 4 
 sequencer.c| 4 
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index c3486bd..14312f7 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -567,8 +567,10 @@ static int merge_working_tree(const struct checkout_opts 
*opts,
o.ancestor = old->name;
o.branch1 = new->name;
o.branch2 = "local";
-   merge_trees(&o, new->commit->tree, work,
+   ret = merge_trees(&o, new->commit->tree, work,
old->commit->tree, &result);
+   if (ret < 0)
+   exit(128);
ret = reset_tree(new->commit->tree, opts, 0,
 writeout_error);
if (ret)
diff --git a/builtin/merge.c b/builtin/merge.c
index b555a1b..133b853 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -682,6 +682,8 @@ static int try_merge_strategy(const char *strategy, struct 
commit_list *common,
hold_locked_index(&lock, 1);
clean = merge_recursive(&o, head,
remoteheads->item, reversed, &result);
+   if (clean < 0)
+   exit(128);
if (active_cache_changed &&
write_locked_index(&the_index, &lock, COMMIT_LOCK))
die (_("unable to write %s"), get_index_file());
@@ -1550,6 +1552,8 @@ int cmd_merge(int argc, const char **argv, const char 
*prefix)
ret = try_merge_strategy(use_strategies[i]->name,
 common, remoteheads,
 head_commit, head_arg);
+   if (ret < 0)
+   exit(128);
if (!option_commit && !ret) {
merge_was_ok = 1;
/*
diff --git a/sequencer.c b/sequencer.c
index c6362d6..13b794a 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -293,6 +293,8 @@ static int do_recursive_merge(struct commit *base, struct 
commit *next,
clean = merge_trees(&o,
head_tree,
next_tree, base_tree, &result);
+   if (clean < 0)
+   return clean;
 
if (active_cache_changed &&
write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
@@ -561,6 +563,8 @@ static int do_pick_commit(struct commit *commit, struct 
replay_opts *opts)
if (!opts->strategy || !strcmp(opts->strategy, "recursive") || 
opts->action == REPLAY_REVERT) {
res = do_recursive_merge(base, next, base_label, next_label,
 head, &msgbuf, opts);
+   if (res < 0)
+   return res;
write_message(&msgbuf, git_path_merge_msg());
} else {
struct commit_list *common = NULL;
-- 
2.9.0.268.gcabc8b0


--
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 9/9] am: make a direct call to merge_recursive

2016-06-29 Thread Johannes Schindelin
From: Junio C Hamano 

Instead of spawning merge-recursive via run_command() in
run_fallback_merge_recursive(), make a direct call to the internal
merge_recursive_generic().

Here is a quick benchmark result, applying a patch for b4391657
(merge: drop 'git merge  HEAD ' syntax, 2015-03-25)
that was still cooking in 'next' on 4b1fd356 (git-multimail: update
to release 1.2.0, 2015-10-11) which was the tip of 'master' at some
stage, on an x86-64 running Ubuntu:

  real0m0.169s  real0m0.163s
  user0m0.108s  user0m0.134s
  sys 0m0.068s  sys 0m0.033s

  real0m0.175s  real0m0.161s
  user0m0.110s  user0m0.120s
  sys 0m0.066s  sys 0m0.047s

  real0m0.168s  real0m0.162s
  user0m0.124s  user0m0.114s
  sys 0m0.045s  sys 0m0.051s

  real0m0.167s  real0m0.152s
  user0m0.124s  user0m0.122s
  sys 0m0.045s  sys 0m0.031s

  real0m0.169s  real0m0.164s
  user0m0.131s  user0m0.129s
  sys 0m0.043s  sys 0m0.041s

Left-hand side shows the original, right-hand side shows the result
of this optimization.

Timings on Windows:

original:
0.00user 0.01system 0:00.29elapsed
0.00user 0.00system 0:00.25elapsed
0.01user 0.00system 0:00.24elapsed
0.01user 0.00system 0:00.26elapsed
0.00user 0.01system 0:00.23elapsed

with optimization:
0.00user 0.01system 0:00.22elapsed
0.00user 0.00system 0:00.25elapsed
0.00user 0.01system 0:00.22elapsed
0.00user 0.00system 0:00.22elapsed
0.01user 0.00system 0:00.21elapsed

Signed-off-by: Junio C Hamano 
Signed-off-by: Johannes Schindelin 
---

It feels *slightly* wrong to submit your own patch to review,
however, please keep in mind that

1) I changed the patch (o.gently does not exist anymore, so I do
   not set it), and

2) I added my own timings performed on Windows.

 builtin/am.c | 27 ++-
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index 3dfe70b..dd41154 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1587,25 +1587,26 @@ static int run_fallback_merge_recursive(const struct 
am_state *state,
unsigned char *our_tree,
unsigned char *his_tree)
 {
-   struct child_process cp = CHILD_PROCESS_INIT;
+   const unsigned char *bases[1] = {orig_tree};
+   struct merge_options o;
+   struct commit *result;
+   char *his_tree_name;
int status;
 
-   cp.git_cmd = 1;
+   init_merge_options(&o);
+
+   o.branch1 = "HEAD";
+   his_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
+   o.branch2 = his_tree_name;
 
-   argv_array_pushf(&cp.env_array, "GITHEAD_%s=%.*s",
-sha1_to_hex(his_tree), linelen(state->msg), 
state->msg);
if (state->quiet)
-   argv_array_push(&cp.env_array, "GIT_MERGE_VERBOSITY=0");
+   o.verbosity = 0;
 
-   argv_array_push(&cp.args, "merge-recursive");
-   argv_array_push(&cp.args, sha1_to_hex(orig_tree));
-   argv_array_push(&cp.args, "--");
-   argv_array_push(&cp.args, sha1_to_hex(our_tree));
-   argv_array_push(&cp.args, sha1_to_hex(his_tree));
+   status = merge_recursive_generic(&o, our_tree, his_tree, 1, bases, 
&result);
+   if (status < 0)
+   exit(128);
+   free(his_tree_name);
 
-   status = run_command(&cp) ? (-1) : 0;
-   discard_cache();
-   read_cache();
return status;
 }
 
-- 
2.9.0.268.gcabc8b0
--
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: git svn clone segmentation faul issue

2016-06-29 Thread Johannes Schindelin
Hi Yannis,

On Wed, 29 Jun 2016, Ioannis Kappas wrote:

> Johannes Schindelin  gmx.de> writes:
> 
> > I just re-uploaded new packages, after rebuilding them and making sure
> > that the patch was actually applied.
> > 
> > May I ask you to re-test, just to make extra sure that the bug in
> > question is fixed?
> 
> I confirm the latest version, built from the 'source files (zip)'
> package, has resolved the issue.

Thank you so much!

> Thanks for the prompt response! Next task is to get the patch through to
> the next subversion official release.

My more immediate concern is MSYS2 (the POSIX-emulating basis of Git for
Windows), and I opened a Pull Request there:

https://github.com/Alexpux/MSYS2-packages/pull/647

If this Pull Request is not picked up in time for the next Git for Windows
version, I plan to use the packages that you tested.

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


Re: git gui produces series of commits with exactly the same time

2016-06-29 Thread Johannes Schindelin
Hi Andrei,

On Wed, 29 Jun 2016, Andrei Faber wrote:

> I've noticed that git history contains series of commits with exactly
> the same time, despite the real commit time of these commits was
> different. All these commit were made using the git gui tool. I'm the
> only developer in this project.

Is it possible that you played games with your GIT_AUTHOR_DATE environment
variable?

Ciao,
Johannes
--
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: preview: What's cooking in git.git (Jun 2016, #10; Tue, 28)

2016-06-29 Thread Johannes Schindelin
Hi Junio,

On Tue, 28 Jun 2016, Junio C Hamano wrote:

> * jk/ansi-color (2016-06-23) 7 commits
>   (merged to 'next' on 2016-06-28 at 354989c)
>  + color: support strike-through attribute
>  + color: support "italic" attribute
>  + color: allow "no-" for negating attributes
>  + color: refactor parse_attr
>  + add skip_prefix_mem helper
>  + doc: refactor description of color format
>  + color: fix max-size comment
> 
>  The output coloring scheme learned two new attributes, italic and
>  strike, in addition to existing bold, reverse, etc.
> 
>  Will merge to 'master'.

Please note that those "colors" do not work on Windows, at least as far as
I know, I only skimmed the code in set_attr():

https://github.com/git/git/blob/v2.9.0/compat/winansi.c#L175-L314

... and it looks as if italic is plainly unsupported, and strike-through
is not handled.

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


git tag --contains for cherry-picks

2016-06-29 Thread Laszlo Papp
Dear List,

We have several release branches as well as a master branch where the
active development happens.

Old releases are maintained with important bug fixes or even new features
in our case. It sometimes means that we need to cherry-pick commits across
branches, like from master to a specific release branch.

Cherry-picking changes the hash of the commit, therefore, this may no
longer work for cherry-picks:

git tag --contains

I am thinking of having something like:

git tag --contains-follow

which would follow cherry-picks. I am not sure how easily and/or
efficiently this can be implemented, but my gut feeling is that in the vast
majority of the cases, the content check would bail out already at the
"subject line".

Again, just to recap: I would like to be able to list of releases (i.e.
tags) in which a commit occurs even if it is cherry-picked because what
matters for us in the end of the day is whether the feature or bugfix goes
into a release.

Best Regards,
Laszlo Papp
--
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: git gui produces series of commits with exactly the same time

2016-06-29 Thread Andrei Faber

Hi Johannes,

No.

Another thing I've found is that these commits have different timestamp 
in the "Author" and "Committer" lines. The "Committer" lines have 
correct timestamps, and the "Author" timestamp is wrong.


Best wishes,
Andrei Faber

On 29/06/2016 18:45, Johannes Schindelin wrote:

Hi Andrei,

On Wed, 29 Jun 2016, Andrei Faber wrote:


I've noticed that git history contains series of commits with exactly
the same time, despite the real commit time of these commits was
different. All these commit were made using the git gui tool. I'm the
only developer in this project.

Is it possible that you played games with your GIT_AUTHOR_DATE environment
variable?

Ciao,
Johannes



--
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] rebase -i: restore autostash on abort

2016-06-29 Thread Johannes Schindelin
Hi Patrick,

On Wed, 29 Jun 2016, Patrick Steinhardt wrote:

> When we abort an interactive rebase we do so by calling
> `die_abort`, which cleans up after us by removing the rebase
> state directory. If the user has requested to use the autostash
> feature, though, the state directory may also contain a reference
> to the autostash, which will now be deleted.
> 
> Fix the issue by trying to re-apply the autostash in `die_abort`.
> This will also handle the case where the autostash does not apply
> cleanly anymore by recording it in a user-visible stash.

I like it. Thanks for including the tests, they were very helpful to
verify that my rebase--helper work is unaffected: the patch touches only
those parts that are not moved into the rebase--helper.

Thanks,
Johannes
--
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] Use skip_blank_lines() for more commit messages

2016-06-29 Thread Johannes Schindelin
These patches are on top of js/find-commit-subject-ignore-leading-blanks
(whether you want to put them into the same topic branch before merging
or put them into their own add-on topic branch does not really matter to
me).

It occurred to me that there might be more code locations where finding
the commit object's body is hand-rolled, and could benefit from using
the skip_blank_lines() function to handle not-quite-standard but
still-allowed objects from being processed correctly.

I found a couple of instances, and made them consistent with the
pretty-printing machinery.

I made fine-grained commits to allow for dropping contentious patches
more easily.

There are four more instances which I did *not* change:

- fast-export: I designed this command to be as faithful in exporting
  the commits as possible. As such, even non-standard commit objects
  should be kept as-are.

- fmt-merge-msg: when showing signed commit messages, it is better to
  show the commit messages verbatim rather than trimming them.

- when signing a commit, it is better to use the original commit message
  than a munged one.

- notes' messages are left alone. I do not know whether there might be
  an intentional use of leading blank lines, but I wanted to err on the
  safe side.

I also considered treating tag messages the same way, but tags are much
more likely to be signed, and I did not want to risk munging the tag
messages just before signing them.


Johannes Schindelin (5):
  commit -C: skip blank lines at the beginning of the message
  sequencer: use skip_blank_lines() to find the commit subject
  reset --hard: skip blank lines when reporting the commit subject
  commit -S: avoid invalid pointer with empty message
  Skip blank lines when matching ^{/foo}

 builtin/commit.c | 2 +-
 builtin/reset.c  | 2 +-
 commit.c | 6 +-
 sequencer.c  | 6 ++
 sha1_name.c  | 3 ++-
 5 files changed, 11 insertions(+), 8 deletions(-)

Published-As: 
https://github.com/dscho/git/releases/tag/more-blank-line-skipping-v1
-- 
2.9.0.270.g810e421

base-commit: 38a2ea1900489a76d9840002bf60bd7ff29f07cd
--
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] sequencer: use skip_blank_lines() to find the commit subject

2016-06-29 Thread Johannes Schindelin
Just like we already taught the find_commit_subject() function (to make
it consistent with the code in pretty.c), we now simply skip leading
blank lines of the commit message.

Signed-off-by: Johannes Schindelin 
---
 sequencer.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 7d7add6..cdfac82 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -544,10 +544,8 @@ static int do_pick_commit(struct commit *commit, struct 
replay_opts *opts)
 * information followed by "\n\n".
 */
p = strstr(msg.message, "\n\n");
-   if (p) {
-   p += 2;
-   strbuf_addstr(&msgbuf, p);
-   }
+   if (p)
+   strbuf_addstr(&msgbuf, skip_blank_lines(p + 2));
 
if (opts->record_origin) {
if (!has_conforming_footer(&msgbuf, NULL, 0))
-- 
2.9.0.270.g810e421


--
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] commit -C: skip blank lines at the beginning of the message

2016-06-29 Thread Johannes Schindelin
Consistent with the pretty-printing machinery, we skip leading blank
lines (if any) of existing commit messages.

While Git itself only produces commit objects with a single empty line
between commit header and commit message, it is legal to have more than
one blank line (i.e. lines containing only white space, or no
characters) at the beginning of the commit message, and the
pretty-printing code already handles that.

Signed-off-by: Johannes Schindelin 
---
 builtin/commit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 3f18942..1f6dbcd 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -715,7 +715,7 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
char *buffer;
buffer = strstr(use_message_buffer, "\n\n");
if (buffer)
-   strbuf_addstr(&sb, buffer + 2);
+   strbuf_addstr(&sb, skip_blank_lines(buffer + 2));
hook_arg1 = "commit";
hook_arg2 = use_message;
} else if (fixup_message) {
-- 
2.9.0.270.g810e421


--
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] Skip blank lines when matching ^{/foo}

2016-06-29 Thread Johannes Schindelin
When trying to match a pattern in the commit subject, simply skip leading
blank lines in the commit message. This is consistent with the
pretty-printing machinery: it silently ignores leading blank lines in the
commit object's body.

Signed-off-by: Johannes Schindelin 
---
 sha1_name.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sha1_name.c b/sha1_name.c
index ca7ddd6..da354a5 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -912,7 +912,8 @@ static int get_sha1_oneline(const char *prefix, unsigned 
char *sha1,
continue;
buf = get_commit_buffer(commit, NULL);
p = strstr(buf, "\n\n");
-   matches = negative ^ (p && !regexec(®ex, p + 2, 0, NULL, 0));
+   matches = negative ^ (p && !regexec(®ex,
+   skip_blank_lines(p + 2), 0, NULL, 0));
unuse_commit_buffer(commit, buf);
 
if (matches) {
-- 
2.9.0.270.g810e421
--
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] commit -S: avoid invalid pointer with empty message

2016-06-29 Thread Johannes Schindelin
While it is not recommended, `git fsck` says that:

Not having a body is not a crime [...]

... which means that we cannot assume that the commit buffer contains an
empty line to separate header from body (essentially saying that there
is only a header).

So let's tread carefully here.

Signed-off-by: Johannes Schindelin 
---
 commit.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/commit.c b/commit.c
index 24d4715..0bb51a2 100644
--- a/commit.c
+++ b/commit.c
@@ -1090,11 +1090,15 @@ static const int gpg_sig_header_len = 
sizeof(gpg_sig_header) - 1;
 
 static int do_sign_commit(struct strbuf *buf, const char *keyid)
 {
+   const char *eoh = strstr(buf->buf, "\n\n");
struct strbuf sig = STRBUF_INIT;
int inspos, copypos;
 
/* find the end of the header */
-   inspos = strstr(buf->buf, "\n\n") - buf->buf + 1;
+   if (!eoh)
+   inspos = buf->len;
+   else
+   inspos = eoh - buf->buf + 1;
 
if (!keyid || !*keyid)
keyid = get_signing_key();
-- 
2.9.0.270.g810e421


--
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] reset --hard: skip blank lines when reporting the commit subject

2016-06-29 Thread Johannes Schindelin
When there are blank lines at the beginning of a commit message, the
pretty printing machinery already skips them when showing a commit
subject (or the complete commit message). We shall henceforth do the
same when reporting the commit subject after the user called

git reset --hard 

Signed-off-by: Johannes Schindelin 
---
 builtin/reset.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/reset.c b/builtin/reset.c
index acd6278..5c6206b 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -103,7 +103,7 @@ static void print_new_head_line(struct commit *commit)
if (body) {
const char *eol;
size_t len;
-   body += 2;
+   body = skip_blank_lines(body + 2);
eol = strchr(body, '\n');
len = eol ? eol - body : strlen(body);
printf(" %.*s\n", (int) len, body);
-- 
2.9.0.270.g810e421


--
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/2] Late edits to the rebase -i tests

2016-06-29 Thread Johannes Schindelin
I meant to send the first patch much earlier, but got side-tracked
before I could add the --gpg-sign test.

This is just another patch series in preparation for the rebase--helper
(to be precise, this is the seventh out of fourteen patch series that
have not yet been merged to master; Six are already in flight, so I will
stop here until the queue empties a little.)


Johannes Schindelin (2):
  t3404: fix another typo
  t3404: add a test for the --gpg-sign option

 t/t3404-rebase-interactive.sh | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

Published-As: https://github.com/dscho/git/releases/tag/rebase-i-tests-v1
-- 
2.9.0.270.g810e421

base-commit: cf4c2cfe52be5bd973a4838f73a35d3959ce2f43
--
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] t3404: add a test for the --gpg-sign option

2016-06-29 Thread Johannes Schindelin
To keep the time t3404 requires short (in this developer's Windows
setup, this single test already takes a painful 8 minutes to pass),
we avoid a full-blown GPG test and cop out by verifying the message
displayed to the user upon an 'edit' command.

Signed-off-by: Johannes Schindelin 
---
 t/t3404-rebase-interactive.sh | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index c7ea8ba..4c96075 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1281,4 +1281,11 @@ test_expect_success 'editor saves as CR/LF' '
)
 '
 
+EPIPHANY="'"
+test_expect_success 'rebase -i --gpg-sign=' '
+   set_fake_editor &&
+   FAKE_LINES="edit 1" git rebase -i --gpg-sign=\" HEAD^ >out 2>err &&
+   grep "$EPIPHANY-S\"$EPIPHANY" err
+'
+
 test_done
-- 
2.9.0.270.g810e421
--
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/2] t3404: fix another typo

2016-06-29 Thread Johannes Schindelin
The past tense of "to run" is "run", not "ran".

Signed-off-by: Johannes Schindelin 
---
 t/t3404-rebase-interactive.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 66348f1..c7ea8ba 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -60,7 +60,7 @@ test_expect_success 'setup' '
test_commit P fileP
 '
 
-# "exec" commands are ran with the user shell by default, but this may
+# "exec" commands are run with the user shell by default, but this may
 # be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work
 # to create a file. Unsetting SHELL avoids such non-portable behavior
 # in tests. It must be exported for it to take effect where needed.
-- 
2.9.0.270.g810e421


--
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 01/11] i18n: add--interactive: mark strings for translation

2016-06-29 Thread Vasco Almeida
Mark simple strings (without interpolation) for translation.

Brackets around first parameter of ternary operator is necessary because
otherwise xgettext fails to extract strings marked for translation from
the rest of the file.

Signed-off-by: Vasco Almeida 
---
 git-add--interactive.perl | 68 +--
 1 file changed, 36 insertions(+), 32 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 822f857..fb8e5de 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -4,6 +4,7 @@ use 5.008;
 use strict;
 use warnings;
 use Git;
+use Git::I18N;
 
 binmode(STDOUT, ":raw");
 
@@ -252,7 +253,7 @@ sub list_untracked {
 }
 
 my $status_fmt = '%12s %12s %s';
-my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');
+my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), 
__('path'));
 
 {
my $initial;
@@ -678,7 +679,7 @@ sub update_cmd {
my @mods = list_modified('file-only');
return if (!@mods);
 
-   my @update = list_and_choose({ PROMPT => 'Update',
+   my @update = list_and_choose({ PROMPT => __('Update'),
   HEADER => $status_head, },
 @mods);
if (@update) {
@@ -690,7 +691,7 @@ sub update_cmd {
 }
 
 sub revert_cmd {
-   my @update = list_and_choose({ PROMPT => 'Revert',
+   my @update = list_and_choose({ PROMPT => __('Revert'),
   HEADER => $status_head, },
 list_modified());
if (@update) {
@@ -724,13 +725,13 @@ sub revert_cmd {
 }
 
 sub add_untracked_cmd {
-   my @add = list_and_choose({ PROMPT => 'Add untracked' },
+   my @add = list_and_choose({ PROMPT => __('Add untracked') },
  list_untracked());
if (@add) {
system(qw(git update-index --add --), @add);
say_n_paths('added', @add);
} else {
-   print "No untracked files.\n";
+   print __("No untracked files.\n");
}
print "\n";
 }
@@ -1159,8 +1160,11 @@ sub edit_hunk_loop {
}
else {
prompt_yesno(
-   'Your edited hunk does not apply. Edit again '
-   . '(saying "no" discards!) [y/n]? '
+   # TRANSLATORS: do not translate [y/n]
+   # The program will only accept that input
+   # at this point.
+   __('Your edited hunk does not apply. Edit again 
'
+  . '(saying "no" discards!) [y/n]? ')
) or return undef;
}
}
@@ -1206,11 +1210,11 @@ sub apply_patch_for_checkout_commit {
run_git_apply 'apply '.$reverse, @_;
return 1;
} elsif (!$applies_index) {
-   print colored $error_color, "The selected hunks do not apply to 
the index!\n";
-   if (prompt_yesno "Apply them to the worktree anyway? ") {
+   print colored $error_color, __("The selected hunks do not apply 
to the index!\n");
+   if (prompt_yesno __("Apply them to the worktree anyway? ")) {
return run_git_apply 'apply '.$reverse, @_;
} else {
-   print colored $error_color, "Nothing was applied.\n";
+   print colored $error_color, __("Nothing was 
applied.\n");
return 0;
}
} else {
@@ -1230,9 +1234,9 @@ sub patch_update_cmd {
 
if (!@mods) {
if (@all_mods) {
-   print STDERR "Only binary files changed.\n";
+   print STDERR __("Only binary files changed.\n");
} else {
-   print STDERR "No changes.\n";
+   print STDERR __("No changes.\n");
}
return 0;
}
@@ -1390,12 +1394,12 @@ sub patch_update_file {
my $response = $1;
my $no = $ix > 10 ? $ix - 10 : 0;
while ($response eq '') {
-   my $extra = "";
$no = display_hunks(\@hunk, $no);
if ($no < $num) {
-   $extra = " ( to see more)";
+   print __("go to which hunk 
( to see more)? ");
+   } else {
+   print __("go to which hunk? ");
}
-   print "go to which hunk$extra? ";
 

[PATCH v2 04/11] i18n: add--interactive: mark plural strings

2016-06-29 Thread Vasco Almeida
Mark plural strings for translation.  Unfold each action case in one
entire sentence.

Pass new keyword for xgettext to extract.

Update test to include new subrotine Q__() for plural strings handling.

Signed-off-by: Vasco Almeida 
---
 Makefile  |  3 ++-
 git-add--interactive.perl | 24 
 perl/Git/I18N.pm  |  4 +++-
 t/t0202/test.pl   | 11 ++-
 4 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile
index de5a030..eedf1fa 100644
--- a/Makefile
+++ b/Makefile
@@ -2061,7 +2061,8 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
--keyword=_ --keyword=N_ --keyword="Q_:1,2"
 XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \
--keyword=gettextln --keyword=eval_gettextln
-XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
+XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \
+   --keyword=__ --keyword="Q__:1,2"
 LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
 LOCALIZED_SH = $(SCRIPT_SH) git-parse-remote.sh
 LOCALIZED_PERL = $(SCRIPT_PERL)
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 4e1e857..08badfa 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -666,12 +666,18 @@ sub status_cmd {
 sub say_n_paths {
my $did = shift @_;
my $cnt = scalar @_;
-   print "$did ";
-   if (1 < $cnt) {
-   print "$cnt paths\n";
-   }
-   else {
-   print "one path\n";
+   if ($did eq 'added') {
+   printf(Q__("added one path\n", "added %d paths\n",
+  $cnt), $cnt);
+   } elsif ($did eq 'updated') {
+   printf(Q__("updated one path\n", "updated %d paths\n",
+  $cnt), $cnt);
+   } elsif ($did eq 'reversed') {
+   printf(Q__("reversed one path\n", "reversed %d paths\n",
+  $cnt), $cnt);
+   } else {
+   printf(Q__("touched one path\n", "touched %d paths\n",
+  $cnt), $cnt);
}
 }
 
@@ -1508,8 +1514,10 @@ sub patch_update_file {
elsif ($other =~ /s/ && $line =~ /^s/) {
my @split = split_hunk($hunk[$ix]{TEXT}, 
$hunk[$ix]{DISPLAY});
if (1 < @split) {
-   print colored $header_color, "Split 
into ",
-   scalar(@split), " hunks.\n";
+   print colored $header_color, sprintf(
+   Q__("Split into %d hunk.\n",
+   "Split into %d hunks.\n",
+   scalar(@split)), 
scalar(@split));
}
splice (@hunk, $ix, 1, @split);
$num = scalar @hunk;
diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm
index f889fd6..5a75dd5 100644
--- a/perl/Git/I18N.pm
+++ b/perl/Git/I18N.pm
@@ -13,7 +13,7 @@ BEGIN {
}
 }
 
-our @EXPORT = qw(__);
+our @EXPORT = qw(__ Q__);
 our @EXPORT_OK = @EXPORT;
 
 sub __bootstrap_locale_messages {
@@ -44,6 +44,7 @@ BEGIN
eval {
__bootstrap_locale_messages();
*__ = \&Locale::Messages::gettext;
+   *Q__ = \&Locale::Messages::ngettext;
1;
} or do {
# Tell test.pl that we couldn't load the gettext library.
@@ -51,6 +52,7 @@ BEGIN
 
# Just a fall-through no-op
*__ = sub ($) { $_[0] };
+   *Q__ = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };
};
 }
 
diff --git a/t/t0202/test.pl b/t/t0202/test.pl
index 2c10cb4..98aa9a3 100755
--- a/t/t0202/test.pl
+++ b/t/t0202/test.pl
@@ -4,7 +4,7 @@ use lib (split(/:/, $ENV{GITPERLLIB}));
 use strict;
 use warnings;
 use POSIX qw(:locale_h);
-use Test::More tests => 8;
+use Test::More tests => 11;
 use Git::I18N;
 
 my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;
@@ -31,6 +31,7 @@ is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, 
"sanity: Git::I18N export
# more gettext wrapper functions.
my %prototypes = (qw(
__  $
+   Q__ $$$
));
while (my ($sub, $proto) = each %prototypes) {
is(prototype(\&{"Git::I18N::$sub"}), $proto, "sanity: $sub has 
a $proto prototype");
@@ -46,6 +47,14 @@ is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, 
"sanity: Git::I18N export
my ($got, $expect) = (('TEST: A Perl test string') x 2);
 
is(__($got), $expect, "Passing a string through __() in the C locale 
works");
+
+   my ($got_singular, $got_plural, $expect_singular, $expect_plural) =
+   (('TEST: 1 file', 'TEST: n files') x 2);
+
+   is(Q__($got_singular, $got_plural, 1), $expect_singular,
+   "Get sing

[PATCH v2 05/11] i18n: add--interactive: mark message for translation

2016-06-29 Thread Vasco Almeida
Mark message assembled in place for translation, unfolding each use case
for each entry in the %patch_modes hash table.

Previously, this script relied on whether $patch_mode was set to run the
command patch_update_cmd() or show status and loop the main loop. Now,
it uses $cmd to indicate we must run patch_update_cmd() and $patch_mode
is used to tell which flavor of the %patch_modes are we on.  This is
introduced in order to be able to mark and unfold the message prompt
knowing in which context we are.

The tracking of context was done previously by point %patch_mode_flavour
hash table to the correct entry of %patch_modes, focusing only on value
of %patch_modes. Now, we are also interested in the key ('staged',
'stash', 'checkout_head', ...).

Signed-off-by: Vasco Almeida 
---
 git-add--interactive.perl | 91 ++-
 1 file changed, 83 insertions(+), 8 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 08badfa..5b89b97 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -91,6 +91,7 @@ sub colored {
 }
 
 # command line options
+my $cmd;
 my $patch_mode;
 my $patch_mode_revision;
 
@@ -171,7 +172,8 @@ my %patch_modes = (
},
 );
 
-my %patch_mode_flavour = %{$patch_modes{stage}};
+$patch_mode = 'stage';
+my %patch_mode_flavour = %{$patch_modes{$patch_mode}};
 
 sub run_cmd_pipe {
if ($^O eq 'MSWin32') {
@@ -1372,12 +1374,84 @@ sub patch_update_file {
for (@{$hunk[$ix]{DISPLAY}}) {
print;
}
-   print colored $prompt_color, $patch_mode_flavour{VERB},
- ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :
-  $hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :
-  ' this hunk'),
- $patch_mode_flavour{TARGET},
- " [y,n,q,a,d,/$other,?]? ";
+   if ($patch_mode eq 'stage') {
+   if ($hunk[$ix]{TYPE} eq 'mode') {
+ print colored $prompt_color,
+   sprintf(__("Stage mode change [y,n,q,a,d,/%s,?]? 
"), $other);
+   } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
+ print colored $prompt_color,
+   sprintf(__("Stage deletion [y,n,q,a,d,/%s,?]? "), 
$other);
+   } else {
+ print colored $prompt_color,
+   sprintf(__("Stage this hunk [y,n,q,a,d,/%s,?]? "), 
$other);
+   }
+   } elsif ($patch_mode eq 'stash') {
+   if ($hunk[$ix]{TYPE} eq 'mode') {
+ print colored $prompt_color,
+   sprintf(__("Stash mode change [y,n,q,a,d,/%s,?]? 
"), $other);
+   } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
+ print colored $prompt_color,
+   sprintf(__("Stash deletion [y,n,q,a,d,/%s,?]? "), 
$other);
+   } else {
+ print colored $prompt_color,
+   sprintf(__("Stash this hunk [y,n,q,a,d,/%s,?]? "), 
$other);
+   }
+   } elsif ($patch_mode eq 'reset_head') {
+   if ($hunk[$ix]{TYPE} eq 'mode') {
+ print colored $prompt_color,
+   sprintf(__("Unstage mode change [y,n,q,a,d,/%s,?]? 
"), $other);
+   } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
+ print colored $prompt_color,
+   sprintf(__("Unstage deletion [y,n,q,a,d,/%s,?]? "), 
$other);
+   } else {
+ print colored $prompt_color,
+   sprintf(__("Unstage this hunk [y,n,q,a,d,/%s,?]? 
"), $other);
+   }
+   } elsif ($patch_mode eq 'reset_nothead') {
+   if ($hunk[$ix]{TYPE} eq 'mode') {
+ print colored $prompt_color,
+   sprintf(__("Apply mode change to index 
[y,n,q,a,d,/%s,?]? "), $other);
+   } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
+ print colored $prompt_color,
+   sprintf(__("Apply deletion to index 
[y,n,q,a,d,/%s,?]? "), $other);
+   } else {
+ print colored $prompt_color,
+   sprintf(__("Apply this hunk to index 
[y,n,q,a,d,/%s,?]? "), $other);
+   }
+   } elsif ($patch_mode eq 'checkout_index') {
+   if ($hunk[$ix]{TYPE} eq 'mode') {
+ print colored $prompt_color,
+   sprintf(__("Discard mode change from worktree 
[y,n,q,a,d,/%s,?]? "), $other);
+   } elsif ($hunk[$ix]{TYPE} eq 'deletion') {
+ pr

[PATCH v2 02/11] i18n: add--interactive: mark simple here documents for translation

2016-06-29 Thread Vasco Almeida
Mark messages in here document without interpolation for translation.

Marking for translation by removing here documents this way, rather than
take advantage of "print __ << EOF" way, makes other instances of help
messages in clean.c match the first two in this file.  Otherwise,
reusing here document would add a trailer newline to the message, making
them not match 100%, hence creating two entries in pot template for
translation rather than a single entry.

Signed-off-by: Vasco Almeida 
---
 git-add--interactive.perl | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index fb8e5de..e11a33d 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -636,25 +636,25 @@ sub list_and_choose {
 }
 
 sub singleton_prompt_help_cmd {
-   print colored $help_color, <<\EOF ;
-Prompt help:
+   print colored $help_color, __(
+"Prompt help:
 1  - select a numbered item
 foo- select item based on unique prefix
-   - (empty) select nothing
-EOF
+   - (empty) select nothing"),
+"\n";
 }
 
 sub prompt_help_cmd {
-   print colored $help_color, <<\EOF ;
-Prompt help:
+   print colored $help_color, __(
+"Prompt help:
 1  - select a single item
 3-5- select a range of items
 2-3,6-9- select multiple ranges
 foo- select item based on unique prefix
 -...   - unselect specified items
 *  - choose all items
-   - (empty) finish selecting
-EOF
+   - (empty) finish selecting"),
+"\n";
 }
 
 sub status_cmd {
@@ -1573,14 +1573,14 @@ sub quit_cmd {
 }
 
 sub help_cmd {
-   print colored $help_color, <<\EOF ;
-status- show paths with changes
+   print colored $help_color, __(
+"status- show paths with changes
 update- add working tree state to the staged set of changes
 revert- revert staged set of changes back to the HEAD version
 patch - pick hunks and update selectively
 diff - view diff between HEAD and index
-add untracked - add contents of untracked files to the staged set of changes
-EOF
+add untracked - add contents of untracked files to the staged set of changes"),
+"\n";
 }
 
 sub process_args {
-- 
2.7.4

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


[PATCH v2 06/11] i18n: add--interactive: i18n of help_patch_cmd

2016-06-29 Thread Vasco Almeida
Mark help message of help_patch_cmd for translation.  The message must
be unfolded to be free of variables so we can have high quality
translations.

Signed-off-by: Vasco Almeida 
---
 git-add--interactive.perl | 65 +++
 1 file changed, 54 insertions(+), 11 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 5b89b97..acbfa4e 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1179,15 +1179,58 @@ sub edit_hunk_loop {
 }
 
 sub help_patch_cmd {
-   my $verb = lc $patch_mode_flavour{VERB};
-   my $target = $patch_mode_flavour{TARGET};
-   print colored $help_color, 

[PATCH v2 08/11] i18n: send-email: mark strings for translation

2016-06-29 Thread Vasco Almeida
Mark strings often displayed to user for translation.

Signed-off-by: Vasco Almeida 
---
 git-send-email.perl | 53 +++--
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 6958785..2521832 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -28,6 +28,7 @@ use File::Temp qw/ tempdir tempfile /;
 use File::Spec::Functions qw(catfile);
 use Error qw(:try);
 use Git;
+use Git::I18N;
 
 Getopt::Long::Configure qw/ pass_through /;
 
@@ -795,12 +796,12 @@ foreach my $f (@files) {
 }
 
 if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
-   print "The following files are 8bit, but do not declare " .
-   "a Content-Transfer-Encoding.\n";
+   print __("The following files are 8bit, but do not declare " .
+"a Content-Transfer-Encoding.\n");
foreach my $f (sort keys %broken_encoding) {
print "$f\n";
}
-   $auto_8bit_encoding = ask("Which 8bit encoding should I declare 
[UTF-8]? ",
+   $auto_8bit_encoding = ask(__("Which 8bit encoding should I declare 
[UTF-8]? "),
  valid_re => qr/.{4}/, confirm_only => 1,
  default => "UTF-8");
 }
@@ -827,7 +828,7 @@ if (defined $sender) {
 # But it's a no-op to run sanitize_address on an already sanitized address.
 $sender = sanitize_address($sender);
 
-my $to_whom = "To whom should the emails be sent (if anyone)?";
+my $to_whom = __("To whom should the emails be sent (if anyone)?");
 my $prompting = 0;
 if (!@initial_to && !defined $to_cmd) {
my $to = ask("$to_whom ",
@@ -857,7 +858,7 @@ sub expand_one_alias {
 
 if ($thread && !defined $initial_reply_to && $prompting) {
$initial_reply_to = ask(
-   "Message-ID to be used as In-Reply-To for the first email (if 
any)? ",
+   __("Message-ID to be used as In-Reply-To for the first email 
(if any)? "),
default => "",
valid_re => qr/\@.*\./, confirm_only => 1);
 }
@@ -916,7 +917,10 @@ sub validate_address {
my $address = shift;
while (!extract_valid_address($address)) {
print STDERR "error: unable to extract a valid address from: 
$address\n";
-   $_ = ask("What to do with this address? ([q]uit|[d]rop|[e]dit): 
",
+   # TRANSLATORS: Make sure to include [q] [d] [e] in your
+   # translation. The program will only accept English input
+   # at this point.
+   $_ = ask(__("What to do with this address? 
([q]uit|[d]rop|[e]dit): "),
valid_re => qr/^(?:quit|q|drop|d|edit|e)/i,
default => 'q');
if (/^d/i) {
@@ -1291,17 +1295,22 @@ Message-Id: $message_id
if ($needs_confirm eq "inform") {
$confirm_unconfigured = 0; # squelch this message for 
the rest of this run
$ask_default = "y"; # assume yes on EOF since user 
hasn't explicitly asked for confirmation
-   print "The Cc list above has been expanded by 
additional\n";
-   print "addresses found in the patch commit message. 
By default\n";
-   print "send-email prompts before sending whenever 
this occurs.\n";
-   print "This behavior is controlled by the 
sendemail.confirm\n";
-   print "configuration setting.\n";
-   print "\n";
-   print "For additional information, run 'git 
send-email --help'.\n";
-   print "To retain the current behavior, but squelch 
this message,\n";
-   print "run 'git config --global sendemail.confirm 
auto'.\n\n";
+   print __(
+"The Cc list above has been expanded by additional
+addresses found in the patch commit message. By default
+send-email prompts before sending whenever this occurs.
+This behavior is controlled by the sendemail.confirm
+configuration setting.
+
+For additional information, run 'git send-email --help'.
+To retain the current behavior, but squelch this message,
+run 'git config --global sendemail.confirm auto'."),
+"\n\n";
}
-   $_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ",
+   # TRANSLATORS: Make sure to include [y] [n] [q] [a] in your
+   # translation. The program will only accept English input
+   # at this point.
+   $_ = ask(__("Send this email? ([y]es|[n]o|[q]uit|[a]ll): "),
 valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
 default => $ask_default);
die "Send this email reply required" unless defined $_;
@@ -1403,7 +1412,7 @@ Message-Id: $message_id
if ($quiet) {
 

[PATCH v2 03/11] i18n: add--interactive: mark strings with interpolation for translation

2016-06-29 Thread Vasco Almeida
Use of sprintf following die or error_msg is necessary for placeholder
substitution take place.

Signed-off-by: Vasco Almeida 
---
 git-add--interactive.perl | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index e11a33d..4e1e857 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -612,12 +612,12 @@ sub list_and_choose {
else {
$bottom = $top = find_unique($choice, @stuff);
if (!defined $bottom) {
-   error_msg "Huh ($choice)?\n";
+   error_msg sprintf(__("Huh (%s)?\n"), 
$choice);
next TOPLOOP;
}
}
if ($opts->{SINGLETON} && $bottom != $top) {
-   error_msg "Huh ($choice)?\n";
+   error_msg sprintf(__("Huh (%s)?\n"), $choice);
next TOPLOOP;
}
for ($i = $bottom-1; $i <= $top-1; $i++) {
@@ -1048,7 +1048,7 @@ sub edit_hunk_manually {
my $hunkfile = $repo->repo_path . "/addp-hunk-edit.diff";
my $fh;
open $fh, '>', $hunkfile
-   or die "failed to open hunk edit file for writing: " . $!;
+   or die sprintf(__("failed to open hunk edit file for writing: 
%s"), $!);
print $fh "# Manual hunk edit mode -- see bottom for a quick guide\n";
print $fh @$oldtext;
my $participle = $patch_mode_flavour{PARTICIPLE};
@@ -1075,7 +1075,7 @@ EOF
}
 
open $fh, '<', $hunkfile
-   or die "failed to open hunk edit file for reading: " . $!;
+   or die sprintf(__("failed to open hunk edit file for reading: 
%s"), $!);
my @newtext = grep { !/^#/ } <$fh>;
close $fh;
unlink $hunkfile;
@@ -1225,7 +1225,7 @@ sub apply_patch_for_checkout_commit {
 
 sub patch_update_cmd {
my @all_mods = list_modified($patch_mode_flavour{FILTER});
-   error_msg "ignoring unmerged: $_->{VALUE}\n"
+   error_msg sprintf(__("ignoring unmerged: %s\n"), $_->{VALUE})
for grep { $_->{UNMERGED} } @all_mods;
@all_mods = grep { !$_->{UNMERGED} } @all_mods;
 
@@ -1407,11 +1407,13 @@ sub patch_update_file {
chomp $response;
}
if ($response !~ /^\s*\d+\s*$/) {
-   error_msg "Invalid number: 
'$response'\n";
+   error_msg sprintf(__("Invalid number: 
'%s'\n"),
+$response);
} elsif (0 < $response && $response <= $num) {
$ix = $response - 1;
} else {
-   error_msg "Sorry, only $num hunks 
available.\n";
+   error_msg sprintf(__("Sorry, only %s 
hunks available.\n"),
+$num);
}
next;
}
@@ -1449,7 +1451,7 @@ sub patch_update_file {
if ($@) {
my ($err,$exp) = ($@, $1);
$err =~ s/ at .*git-add--interactive 
line \d+,  line \d+.*$//;
-   error_msg "Malformed search regexp 
$exp: $err\n";
+   error_msg sprintf(__("Malformed search 
regexp %s: %s\n"), $exp, $err);
next;
}
my $iy = $ix;
@@ -1612,18 +1614,18 @@ sub process_args {
$patch_mode = $1;
$arg = shift @ARGV or die __("missing --");
} else {
-   die "unknown --patch mode: $1";
+   die sprintf(__("unknown --patch mode: %s"), $1);
}
} else {
$patch_mode = 'stage';
$arg = shift @ARGV or die __("missing --");
}
-   die "invalid argument $arg, expecting --"
-   unless $arg eq "--";
+   die sprintf(__("invalid argument %s, expecting --"),
+  $arg) unless $arg eq "--";
%patch_mode_flavour = %{$patch_modes{$patch_mode}};
}
elsif ($arg ne "--") {
-   die "invalid argument $arg, expecting --";
+   die sprintf(__("invalid argument %s, expe

[PATCH v2 09/11] i18n: send-email: mark warnings and errors for translation

2016-06-29 Thread Vasco Almeida
Mark warnings, errors and other messages for translation.

Signed-off-by: Vasco Almeida 
---
 git-send-email.perl | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 2521832..e7f712e 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -118,20 +118,20 @@ sub format_2822_time {
my $localmin = $localtm[1] + $localtm[2] * 60;
my $gmtmin = $gmttm[1] + $gmttm[2] * 60;
if ($localtm[0] != $gmttm[0]) {
-   die "local zone differs from GMT by a non-minute interval\n";
+   die __("local zone differs from GMT by a non-minute 
interval\n");
}
if ((($gmttm[6] + 1) % 7) == $localtm[6]) {
$localmin += 1440;
} elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {
$localmin -= 1440;
} elsif ($gmttm[6] != $localtm[6]) {
-   die "local time offset greater than or equal to 24 hours\n";
+   die __("local time offset greater than or equal to 24 hours\n");
}
my $offset = $localmin - $gmtmin;
my $offhour = $offset / 60;
my $offmin = abs($offset % 60);
if (abs($offhour) >= 24) {
-   die ("local time offset greater than or equal to 24 hours\n");
+   die __("local time offset greater than or equal to 24 hours\n");
}
 
return sprintf("%s, %2d %s %d %02d:%02d:%02d %s%02d%02d",
@@ -199,13 +199,13 @@ sub do_edit {
map {
system('sh', '-c', $editor.' "$@"', $editor, $_);
if (($? & 127) || ($? >> 8)) {
-   die("the editor exited uncleanly, aborting 
everything");
+   die(__("the editor exited uncleanly, aborting 
everything"));
}
} @_;
} else {
system('sh', '-c', $editor.' "$@"', $editor, @_);
if (($? & 127) || ($? >> 8)) {
-   die("the editor exited uncleanly, aborting everything");
+   die(__("the editor exited uncleanly, aborting 
everything"));
}
}
 }
@@ -299,7 +299,7 @@ my $help;
 my $rc = GetOptions("h" => \$help,
 "dump-aliases" => \$dump_aliases);
 usage() unless $rc;
-die "--dump-aliases incompatible with other options\n"
+die __("--dump-aliases incompatible with other options\n")
 if !$help and $dump_aliases and @ARGV;
 $rc = GetOptions(
"sender|from=s" => \$sender,
@@ -362,7 +362,7 @@ unless ($rc) {
 usage();
 }
 
-die "Cannot run git format-patch from outside a repository\n"
+die __("Cannot run git format-patch from outside a repository\n")
if $format_patch and not $repo;
 
 # Now, let's fill any that aren't set in with defaults:
@@ -617,7 +617,7 @@ while (defined(my $f = shift @ARGV)) {
 }
 
 if (@rev_list_opts) {
-   die "Cannot run git format-patch from outside a repository\n"
+   die __("Cannot run git format-patch from outside a repository\n")
unless $repo;
push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 
1), @rev_list_opts);
 }
@@ -636,7 +636,7 @@ if (@files) {
print $_,"\n" for (@files);
}
 } else {
-   print STDERR "\nNo patch files specified!\n\n";
+   print STDERR __("\nNo patch files specified!\n\n");
usage();
 }
 
@@ -728,7 +728,7 @@ EOT
$sender = $1;
next;
} elsif (/^(?:To|Cc|Bcc):/i) {
-   print "To/Cc/Bcc fields are not interpreted yet, they 
have been ignored\n";
+   print __("To/Cc/Bcc fields are not interpreted yet, 
they have been ignored\n");
next;
}
print $c2 $_;
@@ -737,7 +737,7 @@ EOT
close $c2;
 
if ($summary_empty) {
-   print "Summary email is empty, skipping it\n";
+   print __("Summary email is empty, skipping it\n");
$compose = -1;
}
 } elsif ($annotate) {
@@ -1313,7 +1313,7 @@ Message-Id: $message_id
$_ = ask(__("Send this email? ([y]es|[n]o|[q]uit|[a]ll): "),
 valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
 default => $ask_default);
-   die "Send this email reply required" unless defined $_;
+   die __("Send this email reply required") unless defined $_;
if (/^n/i) {
return 0;
} elsif (/^q/i) {
@@ -1339,7 +1339,7 @@ Message-Id: $message_id
} else {
 
if (!defined $smtp_server) {
-   die "The required SMTP server is not properly defined."
+   die __("The required SMTP server is not properly 
defined.")
}
 
if ($smtp_encrypt

  1   2   >