Re: Git tag: pre-receive hook issue

2015-07-19 Thread Jacob Keller
On Sun, Jul 19, 2015 at 12:55 AM, Gaurav Chhabra
varuag.chha...@gmail.com wrote:
 @Junio: So from your detailed explanation (and Jake's comment), i
 understand that since my ref wasn't updated on remote so querying the
 same using git describe resulted in failure, and hence, code was not
 entering the IF block. Correct?


I assume so.

 Also, while i was reading your replies, i was just thinking that the
 following question that i asked Jake doesn't really make sense because
 a commit object _is_ being passed (on local machine) to git
 describe, which is what it expects so it should work for sure:


It works yes. Git describe finds the nearest tag. --exact-match fails
unless it can find a tag at the commit specified.

 If i got the above right, then shouldn't Git throw an error even on
 my local machine when i'm running git describe --exact-match
 ac28ca721e67a?


only if ac28ca721e67a does not have an annotated tag associated to it



 @Junio: You wrote: The part that I find questionable is that by
 checking with is this commit a tagged one? and doing different
 things. What makes the initial and the third special to deserve
 checking (because they are not annotated with a tag) while skipping
 the validation for the second (merely because it has an annotated tag
 added to it)?
 Isn't the code that i shared doing just the opposite of what you've written? 
 It's checking for annotated tags only and skipping the lightweight ones 
 (although it shouldn't be doing all such things in the first place). Was it 
 a typo on your part?



I'm not sure what the code you have is trying to do. See below.

 @Jake: For the question you asked: It would help a lot if we
 understood exactly what you are trying to accomplish.
 I'm not sure how my colleague zeroed in on this git describe command but i 
 at least know what we observed (and 'seemed' to work).  We saw that if we 
 use git-describe and pass a commit object, it throws fatal error message. On 
 the other hand, if we pass a tag object, it doesn't throw any fatal error. 
 That's the reason he added that tag check portion.


Hmmm


 @Junio/Jake: After going through all the responses that i've received
 so far on this forum, i'm thinking how this nonsense code worked for
 few cases in the past? When this check was put in place, devs were
 getting error while pushing annotated tags. Since we use Gitolite, we
 added the following to gitolite.conf and the tag push worked for them:

 RW+ refs/tags=developer_name


Sounds like you needed to add RW permissions to the refs/tags namespace.

 I'm wondering why.


Ok, so normally, pre-receive hook is used to implement policy. Ie:
prevent acceptance of pushes that have bad content as defined by the
repository owner. For example, preventing push of tags that don't
match some format, or preventing pushes which contain bad stuff.

I could provide some examples or suggestions if you would describe
what sort of policy you're trying to enforce..

git describe will tell you if the commit you're passing it is
associated with an annotated tag. I do not understand who this
information can help you implement any policy, so understanding what
the policy you want is would be the most helpful.

I can't really help more or understand exactly what you were doing
without understanding what policy you were/are trying to implement.

The thing your code is doing today is something like:

for each reference update, locate every commit

for each commit in this reference update, check to see if it already
has an associated tag connected to it.

If it doesn't have a tag, then do some more checks which are not
described here.

This doesn't make sense to me at all. I think what you *meant* was this:

for each reference update, if the reference being updated is a tag, skip it

otherwise, for each commit in the reference update do some checks on it.

That is *completely* different from the code you've written today.

Regards,
Jake
--
To unsubscribe from this list: send the line 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] Fix sed usage in tests to work around broken xpg4/sed on Solaris

2015-07-19 Thread Johannes Schindelin
Hi,

On 2015-07-19 08:54, Johannes Sixt wrote:
 Am 18.07.2015 um 17:21 schrieb Ben Walton:
  test_expect_success clone ssh://$tuah/home/user/repo 
test_clone_url ssh://$tuah/home/user/repo $ehost /home/user/repo
  
 diff --git a/t/t9500-gitweb-standalone-no-errors.sh 
 b/t/t9500-gitweb-standalone-no-errors.sh
 index e94b2f1..eb264f9 100755
 --- a/t/t9500-gitweb-standalone-no-errors.sh
 +++ b/t/t9500-gitweb-standalone-no-errors.sh
 @@ -290,8 +290,7 @@ test_expect_success 'setup incomplete lines' '
  echo incomplete | tr -d \\012 file 
  git commit -a -m Add incomplete line 
  git tag incomplete_lines_add 
 -sed -e s/CHANGE_ME/change_me/ file file+ 
 -mv -f file+ file 
 +perl -pi -e s/CHANGE_ME/change_me/ file 
 
 This is problematic. On Windows, perl -i fails when no backup file
 extension is specified because perl attempts to replace a file that is
 still open; that does not work on Windows.

Let's qualify this a bit better: it actually works with the SDK of Git for 
Windows 2.x. It is therefore incomplete and partially incorrect to say that 
does not work on Windows. It is true that Git for Windows 1.x' perl bails out 
with Can't do inplace edit.

 This should work, but I haven't tested, yet:
 
   perl -pi.bak -e s/CHANGE_ME/change_me/ file 

This works, of course, but it leaves an extra file behind.

I really wonder why the previous file+  mv -f file+ file dance needs to be 
replaced?

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: Git tag: pre-receive hook issue

2015-07-19 Thread Gaurav Chhabra
@Junio: So from your detailed explanation (and Jake's comment), i
understand that since my ref wasn't updated on remote so querying the
same using git describe resulted in failure, and hence, code was not
entering the IF block. Correct?

Also, while i was reading your replies, i was just thinking that the
following question that i asked Jake doesn't really make sense because
a commit object _is_ being passed (on local machine) to git
describe, which is what it expects so it should work for sure:

If i got the above right, then shouldn't Git throw an error even on
my local machine when i'm running git describe --exact-match
ac28ca721e67a?

@Junio: You wrote: The part that I find questionable is that by
checking with is this commit a tagged one? and doing different
things. What makes the initial and the third special to deserve
checking (because they are not annotated with a tag) while skipping
the validation for the second (merely because it has an annotated tag
added to it)?
 Isn't the code that i shared doing just the opposite of what you've written? 
 It's checking for annotated tags only and skipping the lightweight ones 
 (although it shouldn't be doing all such things in the first place). Was it a 
 typo on your part?


@Jake: For the question you asked: It would help a lot if we
understood exactly what you are trying to accomplish.
 I'm not sure how my colleague zeroed in on this git describe command but i 
 at least know what we observed (and 'seemed' to work).  We saw that if we use 
 git-describe and pass a commit object, it throws fatal error message. On the 
 other hand, if we pass a tag object, it doesn't throw any fatal error. That's 
 the reason he added that tag check portion.


@Junio/Jake: After going through all the responses that i've received
so far on this forum, i'm thinking how this nonsense code worked for
few cases in the past? When this check was put in place, devs were
getting error while pushing annotated tags. Since we use Gitolite, we
added the following to gitolite.conf and the tag push worked for them:

RW+ refs/tags=developer_name

I'm wondering why.


On Sun, Jul 19, 2015 at 3:52 AM, Jacob Keller [via git]
ml-node+s661346n7635854...@n2.nabble.com wrote:
 On Sat, Jul 18, 2015 at 1:08 PM, Gaurav Chhabra
 [hidden email] wrote:

 Thanks for the comments Junio/Jacob! Actually, the script was written
 by someone before i came and the tag check was also done by my
 colleague recently. I was also trying to implement the tag check
 (using refs/tags which i did saw in few links online) but since my
 colleague implemented this 'git describe' thing first and it looked
 like it was working for few cases that we tried, so we left it as is.
 Frankly, since everything 'seemed' to be working well so far, i never
 really quite looked into it. Now i guess, it's time to correct it.


 @Junio: From the example you gave, i could conclude the following:

 1) : gitster garbage/master; git commit --allow-empty -m third
   [master d1f1360] third
   : gitster garbage/master; git describe --exact-match HEAD ;# third
   fatal: no tag exactly matches 'd1f1360b46dfde8c6f341e48ce45d761ed37e357'

 Since after # third commit, no tag was applied to HEAD, so --exact-match
 resulted in fatal error

 2)  : gitster garbage/master; git commit --allow-empty -m second
 [master d1de78e] second
 : gitster garbage/master; git tag -a -m 'v0.1' v0.1
 : gitster garbage/master; git describe --exact-match HEAD^ ;# second
 v0.1
 Since annotated tag was applied after # second commit, so --exact-match
 did referenced the commit as expected.

 3) : gitster garbage/master; git commit --allow-empty -m initial
   [master (root-commit) b18cac2] initial
   : gitster garbage/master; git tag v0.0 ;# lightweight
   : gitster garbage/master; git describe --exact-match HEAD^^ ;# first
   fatal: no tag exactly matches 'b18cac237055d9518f9f92bb4c0a4dac825dce17'

 In this case, it's a lightweight tag and i read today that by default,
 git describe only shows annotated tags (without --all or --tags). I think
 it's because of the missing option (--all or --tags) that it resulted in
 fatal error in this case.

 Please correct me if i misunderstood any/all of the above cases.

 My queries:
 A) When you mentioned: I am feeding three _commits_, not tags., i
 didn't really get what you're trying to highlight. Is it that the code
 i shared 'incorrectly' uses 'git describe' command because it's
 passing the commit ($new_sha1) associated with pushing of the tag
 _instead_ of passing the commit id that the tag actually points to?

 B) Coming to the earlier part of the code that you questioned. Thanks
 for that. As i mentioned above, some guy had written it long time back
 (few years). And again, since this never caused any issue, we never
 looked into it. I did read a little about rev-list today but i think
 i'll have to try it out on my machine to understand it well. Will read
 more and then implement the check but yes, i do get an idea what
 

Re: [PATCH 2/2] Fix sed usage in tests to work around broken xpg4/sed on Solaris

2015-07-19 Thread Johannes Sixt

Am 19.07.2015 um 09:37 schrieb Johannes Schindelin:

On 2015-07-19 08:54, Johannes Sixt wrote:

Am 18.07.2015 um 17:21 schrieb Ben Walton:

-   sed -e s/CHANGE_ME/change_me/ file file+ 
-   mv -f file+ file 
+   perl -pi -e s/CHANGE_ME/change_me/ file 


This is problematic. On Windows, perl -i fails when no backup file
extension is specified because perl attempts to replace a file that is
still open; that does not work on Windows.


Let's qualify this a bit better: it actually works with the SDK of
Git  for Windows 2.x.


Good to know!


I really wonder why the previous file+  mv -f file+ file dance
needs to be replaced?


The sed must be replaced because some versions on Solaris choke on the 
incomplete last line in the file.


-- 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: [PATCH 2/2] Fix sed usage in tests to work around broken xpg4/sed on Solaris

2015-07-19 Thread Johannes Sixt

Am 18.07.2015 um 17:21 schrieb Ben Walton:

The space following the last / in a sed command caused Solaris'
xpg4/sed to fail, claiming the program was garbled and exit with
status 2:

% echo 'foo' | /usr/xpg4/bin/sed -e 's/foo/bar/ '
sed: command garbled: s/foo/bar/
% echo $?
2

Fix this by simply removing the unnecessary space.

Additionally, in 99094a7a, a trivial  breakage was fixed. This
exposed a problem with the test when run on Solaris with xpg4/sed that
had gone silently undetected since its introduction in
e4bd10b2. Solaris' sed executes the requested substitution but prints
a warning about the missing newline at the end of the file and exits
with status 2.

% echo CHANGE_ME | \
tr -d \\012 | /usr/xpg4/bin/sed -e 's/CHANGE_ME/change_me/'
sed: Missing newline at end of file standard input.
change_me
% echo $?
2

To work around this, use perl to execute the substitution instead. By
using inplace replacement, we can subsequently drop the mv command.

Signed-off-by: Ben Walton bdwal...@gmail.com
---
  t/t5601-clone.sh   |2 +-
  t/t9500-gitweb-standalone-no-errors.sh |3 +--
  2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index fa6be3c..2583f84 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -445,7 +445,7 @@ test_expect_success 'clone ssh://host.xz:22/~repo' '
  #IPv6
  for tuah in ::1 [::1] [::1]: user@::1 user@[::1] user@[::1]: [user@::1] 
[user@::1]:
  do
-   ehost=$(echo $tuah | sed -e s/1]:/1]/  | tr -d \133\135)
+   ehost=$(echo $tuah | sed -e s/1]:/1]/ | tr -d \133\135)


Can this not be rewritten as

ehost=$(echo $tuah | sed -e s/1]:/1]/ -e s/[][]//g)

But I admit that it looks like black magic without a comment...


test_expect_success clone ssh://$tuah/home/user/repo 
  test_clone_url ssh://$tuah/home/user/repo $ehost /home/user/repo

diff --git a/t/t9500-gitweb-standalone-no-errors.sh 
b/t/t9500-gitweb-standalone-no-errors.sh
index e94b2f1..eb264f9 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -290,8 +290,7 @@ test_expect_success 'setup incomplete lines' '
echo incomplete | tr -d \\012 file 
git commit -a -m Add incomplete line 
git tag incomplete_lines_add 
-   sed -e s/CHANGE_ME/change_me/ file file+ 
-   mv -f file+ file 
+   perl -pi -e s/CHANGE_ME/change_me/ file 


This is problematic. On Windows, perl -i fails when no backup file 
extension is specified because perl attempts to replace a file that is 
still open; that does not work on Windows. This should work, but I 
haven't tested, yet:


perl -pi.bak -e s/CHANGE_ME/change_me/ file 


git commit -a -m Incomplete context line 
git tag incomplete_lines_ctx 
echo Dominus regit me, file 



-- 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: [PATCH] userdiff: add support for Fountain documents

2015-07-19 Thread Zoë Blade
On 17 Jul 2015, at 23:43, Junio C Hamano gits...@pobox.com wrote:

 * Although uppercase is recommended for Scene Headings to increase
   readability, it is not required.
 
 * A line beginning with any of the following, followed by either a
   dot or a space, is considered a Scene Heading (unless the line is
   preceded by an exclamation point !). Case insensitive.
 
  INT
  EXT
  EST
  INT./EXT
  INT/EXT
  I/E
 
 * You can force a Scene Heading by starting the line with a
   single period.
 
 * Scene Headings can optionally be appended with Scene
   Numbers. Scene numbers are any alphanumerics (plus dashes and
   periods), wrapped in #.
 
 So, it appears wrong to insist on capital letters in the patterns.
 The pattern in the patch does not even accept punctuations on the
 line other than apostrophe.  I won't judge if it is OK to limit to
 US-ASCII ;-)
 
 IPATTERNS(fountain,
^([.][^.]|(INT|EXT|EST|INT./EXT|INT/EXT|I/E)[. ],
[^ \t-]+),
 
 or something like this, perhaps?

Good points, thanks!

This regex should be a bit sturdier:

$ cat scenes.txt 
int. yes - day
INT. YES - DAY #1A#
EXT. YES - DAY
.YES TOO
!EXT. NO
INT/EXT YES - DAY
INT./EXT YES - DAY
I/E YES - DAY
no
NO
NO.
!.NO.
int yes - day
est yes - day
!EXT. NO - DAY

$ grep -E 
^((\.|(([Ii][Nn][Tt]|[Ee][Ss][Tt]|[Ee][Xx][Tt])?\\.?|[Ii]([Nn][Tt])?\.?/[Ee]([Xx][Tt])?\.?)
 ).+)$ scenes.txt 
int. yes - day
INT. YES - DAY #1A#
EXT. YES - DAY
.YES TOO
INT/EXT YES - DAY
INT./EXT YES - DAY
I/E YES - DAY
int yes - day
est yes - day

Revised version of patch incoming...--
To unsubscribe from this list: send the line 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: pre-receive hook issue

2015-07-19 Thread Gaurav Chhabra
The only thing we wanted to check was whether a ref is a tag. :) Rest
other things are working fine (except for the commits=$new_sha1
thing which Junio already pointed out and corrected). I will correct
the pre-receive hook.

The only mystery that remains is about the current nonsensical code
working fine in the past for few annotated tag pushes. It shouldn't
have worked just by providing:

RW+ refs/tags=developer_name

Ref: http://gitolite.com/gitolite/g2/aac.html (Section: deny rules
for refs in a repo)


On Sun, Jul 19, 2015 at 2:09 PM, Jacob Keller [via git]
ml-node+s661346n7635875...@n2.nabble.com wrote:
 On Sun, Jul 19, 2015 at 12:55 AM, Gaurav Chhabra
 [hidden email] wrote:
 @Junio: So from your detailed explanation (and Jake's comment), i
 understand that since my ref wasn't updated on remote so querying the
 same using git describe resulted in failure, and hence, code was not
 entering the IF block. Correct?


 I assume so.

 Also, while i was reading your replies, i was just thinking that the
 following question that i asked Jake doesn't really make sense because
 a commit object _is_ being passed (on local machine) to git
 describe, which is what it expects so it should work for sure:


 It works yes. Git describe finds the nearest tag. --exact-match fails
 unless it can find a tag at the commit specified.

 If i got the above right, then shouldn't Git throw an error even on
 my local machine when i'm running git describe --exact-match
 ac28ca721e67a?


 only if ac28ca721e67a does not have an annotated tag associated to it



 @Junio: You wrote: The part that I find questionable is that by
 checking with is this commit a tagged one? and doing different
 things. What makes the initial and the third special to deserve
 checking (because they are not annotated with a tag) while skipping
 the validation for the second (merely because it has an annotated tag
 added to it)?
 Isn't the code that i shared doing just the opposite of what you've
 written? It's checking for annotated tags only and skipping the lightweight
 ones (although it shouldn't be doing all such things in the first place).
 Was it a typo on your part?



 I'm not sure what the code you have is trying to do. See below.

 @Jake: For the question you asked: It would help a lot if we
 understood exactly what you are trying to accomplish.
 I'm not sure how my colleague zeroed in on this git describe command
 but i at least know what we observed (and 'seemed' to work).  We saw that if
 we use git-describe and pass a commit object, it throws fatal error message.
 On the other hand, if we pass a tag object, it doesn't throw any fatal
 error. That's the reason he added that tag check portion.


 Hmmm


 @Junio/Jake: After going through all the responses that i've received
 so far on this forum, i'm thinking how this nonsense code worked for
 few cases in the past? When this check was put in place, devs were
 getting error while pushing annotated tags. Since we use Gitolite, we
 added the following to gitolite.conf and the tag push worked for them:

 RW+ refs/tags=developer_name


 Sounds like you needed to add RW permissions to the refs/tags namespace.

 I'm wondering why.


 Ok, so normally, pre-receive hook is used to implement policy. Ie:
 prevent acceptance of pushes that have bad content as defined by the
 repository owner. For example, preventing push of tags that don't
 match some format, or preventing pushes which contain bad stuff.

 I could provide some examples or suggestions if you would describe
 what sort of policy you're trying to enforce..

 git describe will tell you if the commit you're passing it is
 associated with an annotated tag. I do not understand who this
 information can help you implement any policy, so understanding what
 the policy you want is would be the most helpful.

 I can't really help more or understand exactly what you were doing
 without understanding what policy you were/are trying to implement.

 The thing your code is doing today is something like:

 for each reference update, locate every commit

 for each commit in this reference update, check to see if it already
 has an associated tag connected to it.

 If it doesn't have a tag, then do some more checks which are not
 described here.

 This doesn't make sense to me at all. I think what you *meant* was this:

 for each reference update, if the reference being updated is a tag, skip it

 otherwise, for each commit in the reference update do some checks on it.

 That is *completely* different from the code you've written today.

 Regards,
 Jake
 --
 To unsubscribe from this list: send the line unsubscribe git in
 the body of a message to [hidden email]
 More majordomo info at  http://vger.kernel.org/majordomo-info.html


 
 If you reply to this email, your message will be added to the discussion
 below:
 http://git.661346.n2.nabble.com/Git-tag-pre-receive-hook-issue-tp7635764p7635875.html
 To unsubscribe from Git 

[PATCH 1/2] bash prompt: test untracked files status indicator with untracked dirs

2015-07-19 Thread SZEDER Gábor
The next commit will tweak the way __git_ps1() decides whether to display
the untracked files status indicator in the presence of untracked
directories.  Add tests to make sure it doesn't change current behavior,
in particular that an empty untracked directory doesn't trigger the
untracked files status indicator.

Signed-off-by: SZEDER Gábor sze...@ira.uka.de
---
 t/t9903-bash-prompt.sh | 25 +
 1 file changed, 25 insertions(+)

diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 49d58e6726..6b68777b98 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -397,6 +397,31 @@ test_expect_success 'prompt - untracked files status 
indicator - untracked files
test_cmp expected $actual
 '
 
+test_expect_success 'prompt - untracked files status indicator - empty 
untracked dir' '
+   printf  (master) expected 
+   mkdir otherrepo/untracked-dir 
+   test_when_finished rm -rf otherrepo/untracked-dir 
+   (
+   GIT_PS1_SHOWUNTRACKEDFILES=y 
+   cd otherrepo 
+   __git_ps1 $actual
+   ) 
+   test_cmp expected $actual
+'
+
+test_expect_success 'prompt - untracked files status indicator - non-empty 
untracked dir' '
+   printf  (master %%) expected 
+   mkdir otherrepo/untracked-dir 
+   test_when_finished rm -rf otherrepo/untracked-dir 
+   otherrepo/untracked-dir/untracked-file 
+   (
+   GIT_PS1_SHOWUNTRACKEDFILES=y 
+   cd otherrepo 
+   __git_ps1 $actual
+   ) 
+   test_cmp expected $actual
+'
+
 test_expect_success 'prompt - untracked files status indicator - untracked 
files outside cwd' '
printf  (master %%) expected 
(
-- 
2.5.0.rc2.15.gd82f7f6

--
To unsubscribe from this list: send the line 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] bash prompt: faster untracked status indicator with untracked directories

2015-07-19 Thread SZEDER Gábor
If the untracked status indicator is enabled, __git_ps1() looks for
untracked files by running 'git ls-files'.  This can be perceptibly slow
in case of an untracked directory containing lot of files, because it
lists all files found in the untracked directory only to be redirected
into /dev/null right away (this is the actual command run by __git_ps1()):

  $ ls untracked-dir/ |wc -l
  10
  $ time git ls-files --others --exclude-standard --error-unmatch \
-- ':/*' /dev/null 2/dev/null

  real  0m0.955s
  user  0m0.936s
  sys   0m0.016s

Eliminate this delay by additionally passing the '--directory
--no-empty-directory' options to 'git ls-files' to show only the name of
non-empty untracked directories instead of all their content:

  $ time git ls-files --others --exclude-standard --directory \
--no-empty-directory --error-unmatch -- ':/*' /dev/null 2/dev/null

  real  0m0.010s
  user  0m0.008s
  sys   0m0.000s

This follows suit of ea95c7b8f5 (completion: improve untracked directory
filtering for filename completion, 2013-09-18).

Signed-off-by: SZEDER Gábor sze...@ira.uka.de
---
 contrib/completion/git-prompt.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 366f0bc1e9..07b52bedf1 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -491,7 +491,7 @@ __git_ps1 ()
 
if [ -n ${GIT_PS1_SHOWUNTRACKEDFILES-} ] 
   [ $(git config --bool bash.showUntrackedFiles) != false 
] 
-  git ls-files --others --exclude-standard --error-unmatch -- 
':/*' /dev/null 2/dev/null
+  git ls-files --others --exclude-standard --directory 
--no-empty-directory --error-unmatch -- ':/*' /dev/null 2/dev/null
then
u=%${ZSH_VERSION+%}
fi
-- 
2.5.0.rc2.15.gd82f7f6

--
To unsubscribe from this list: send the line 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] userdiff: add support for Fountain documents

2015-07-19 Thread Zoë Blade
Add support for Fountain, a plain text screenplay format.  Git
facilitates not just programming specifically, but creative writing
in general, so it makes sense to also support other plain text
documents besides source code.

In the structure of a screenplay specifically, scenes are roughly
analogous to functions, in the sense that it makes your job easier
if you can see which ones were changed in a given range of patches.

More information about the Fountain format can be found on its
official website, at http://fountain.io .

Signed-off-by: Zoë Blade z...@bytenoise.co.uk
---
 Documentation/gitattributes.txt | 2 ++
 t/t4018-diff-funcname.sh| 1 +
 t/t4018/fountain-scene  | 4 
 userdiff.c  | 2 ++
 4 files changed, 9 insertions(+)
 create mode 100644 t/t4018/fountain-scene

diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 81fe586..e3b1de8 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -527,6 +527,8 @@ patterns are available:
 
 - `fortran` suitable for source code in the Fortran language.
 
+- `fountain` suitable for Fountain documents.
+
 - `html` suitable for HTML/XHTML documents.
 
 - `java` suitable for source code in the Java language.
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 1dbaa38..67373dc 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -31,6 +31,7 @@ diffpatterns=
cpp
csharp
fortran
+   fountain
html
java
matlab
diff --git a/t/t4018/fountain-scene b/t/t4018/fountain-scene
new file mode 100644
index 000..6b3257d
--- /dev/null
+++ b/t/t4018/fountain-scene
@@ -0,0 +1,4 @@
+EXT. STREET RIGHT OUTSIDE - DAY
+
+CHARACTER
+You didn't say the magic phrase, ChangeMe.
diff --git a/userdiff.c b/userdiff.c
index 2ccbee5..5a600d6 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -35,6 +35,8 @@ IPATTERN(fortran,
  * they would have been matched above as a variable anyway. */
 
|[-+]?[0-9.]+([AaIiDdEeFfLlTtXx][Ss]?[-+]?[0-9.]*)?(_[a-zA-Z0-9][a-zA-Z0-9_]*)?
 |//|\\*\\*|::|[/=]=),
+PATTERNS(fountain, 
^((\\.|(([Ii][Nn][Tt]|[Ee][Ss][Tt]|[Ee][Xx][Tt])?\\.?|[Ii]([Nn][Tt])?\\.?/[Ee]([Xx][Tt])?\\.?)
 ).+)$,
+[^ \t-]+),
 PATTERNS(html, ^[ \t]*([Hh][1-6][ \t].*.*)$,
 [^= \t]+),
 PATTERNS(java,
-- 
2.5.0.rc2.28.g6003e7f.dirty

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


[PATCH v6 21/45] builtin-am: implement --rebasing mode

2015-07-19 Thread Paul Tan
Since 3041c32 (am: --rebasing, 2008-03-04), git-am.sh supported the
--rebasing option, which is used internally by git-rebase to tell git-am
that it is being used for its purpose. It would create the empty file
$state_dir/rebasing to help completion scripts tell if the ongoing
operation is am or rebase.

As of 0fbb95d (am: don't call mailinfo if $rebasing, 2012-06-26),
--rebasing also implies --3way as well.

Since a1549e1 (am: return control to caller, for housekeeping,
2013-05-12), git-am.sh would only clean up the state directory when it
is not --rebasing, instead deferring cleanup to git-rebase.sh.

Re-implement the above in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 30 ++
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index 7237fff..3107aba 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -89,6 +89,7 @@ struct am_state {
int quiet;
int append_signoff;
const char *resolvemsg;
+   int rebasing;
 };
 
 /**
@@ -366,6 +367,8 @@ static void am_load(struct am_state *state)
read_state_file(sb, state, sign, 1);
state-append_signoff = !strcmp(sb.buf, t);
 
+   state-rebasing = !!file_exists(am_path(state, rebasing));
+
strbuf_release(sb);
 }
 
@@ -544,18 +547,29 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
die(_(Failed to split patches.));
}
 
+   if (state-rebasing)
+   state-threeway = 1;
+
write_file(am_path(state, threeway), 1, state-threeway ? t : f);
 
write_file(am_path(state, quiet), 1, state-quiet ? t : f);
 
write_file(am_path(state, sign), 1, state-append_signoff ? t : 
f);
 
+   if (state-rebasing)
+   write_file(am_path(state, rebasing), 1, %s, );
+   else
+   write_file(am_path(state, applying), 1, %s, );
+
if (!get_sha1(HEAD, curr_head)) {
write_file(am_path(state, abort-safety), 1, %s, 
sha1_to_hex(curr_head));
-   update_ref(am, ORIG_HEAD, curr_head, NULL, 0, 
UPDATE_REFS_DIE_ON_ERR);
+   if (!state-rebasing)
+   update_ref(am, ORIG_HEAD, curr_head, NULL, 0,
+   UPDATE_REFS_DIE_ON_ERR);
} else {
write_file(am_path(state, abort-safety), 1, %s, );
-   delete_ref(ORIG_HEAD, NULL, 0);
+   if (!state-rebasing)
+   delete_ref(ORIG_HEAD, NULL, 0);
}
 
/*
@@ -1056,8 +1070,14 @@ next:
am_next(state);
}
 
-   am_destroy(state);
-   run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+   /*
+* In rebasing mode, it's up to the caller to take care of
+* housekeeping.
+*/
+   if (!state-rebasing) {
+   am_destroy(state);
+   run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+   }
 }
 
 /**
@@ -1326,6 +1346,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
OPT_CMDMODE(0, abort, resume,
N_(restore the original branch and abort the patching 
operation.),
RESUME_ABORT),
+   OPT_HIDDEN_BOOL(0, rebasing, state.rebasing,
+   N_((internal use for git-rebase))),
OPT_END()
};
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 13/45] builtin-am: implement --skip

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07), git-am
supported resuming from a failed patch application by skipping the
current patch. Re-implement this feature by introducing am_skip().

Helped-by: Stefan Beller sbel...@google.com
Signed-off-by: Paul Tan pyoka...@gmail.com
---

Notes:
v6

* Moved lock_file memory allocation to just before the
  hold_locked_index() to prevent memory leaks.

 builtin/am.c | 123 ++-
 1 file changed, 121 insertions(+), 2 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index ec579a6..765844b 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -16,6 +16,8 @@
 #include commit.h
 #include diff.h
 #include diffcore.h
+#include unpack-trees.h
+#include branch.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -868,6 +870,116 @@ static void am_resolve(struct am_state *state)
 }
 
 /**
+ * Performs a checkout fast-forward from `head` to `remote`. If `reset` is
+ * true, any unmerged entries will be discarded. Returns 0 on success, -1 on
+ * failure.
+ */
+static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
+{
+   struct lock_file *lock_file;
+   struct unpack_trees_options opts;
+   struct tree_desc t[2];
+
+   if (parse_tree(head) || parse_tree(remote))
+   return -1;
+
+   lock_file = xcalloc(1, sizeof(struct lock_file));
+   hold_locked_index(lock_file, 1);
+
+   refresh_cache(REFRESH_QUIET);
+
+   memset(opts, 0, sizeof(opts));
+   opts.head_idx = 1;
+   opts.src_index = the_index;
+   opts.dst_index = the_index;
+   opts.update = 1;
+   opts.merge = 1;
+   opts.reset = reset;
+   opts.fn = twoway_merge;
+   init_tree_desc(t[0], head-buffer, head-size);
+   init_tree_desc(t[1], remote-buffer, remote-size);
+
+   if (unpack_trees(2, t, opts)) {
+   rollback_lock_file(lock_file);
+   return -1;
+   }
+
+   if (write_locked_index(the_index, lock_file, COMMIT_LOCK))
+   die(_(unable to write new index file));
+
+   return 0;
+}
+
+/**
+ * Clean the index without touching entries that are not modified between
+ * `head` and `remote`.
+ */
+static int clean_index(const unsigned char *head, const unsigned char *remote)
+{
+   struct lock_file *lock_file;
+   struct tree *head_tree, *remote_tree, *index_tree;
+   unsigned char index[GIT_SHA1_RAWSZ];
+   struct pathspec pathspec;
+
+   head_tree = parse_tree_indirect(head);
+   if (!head_tree)
+   return error(_(Could not parse object '%s'.), 
sha1_to_hex(head));
+
+   remote_tree = parse_tree_indirect(remote);
+   if (!remote_tree)
+   return error(_(Could not parse object '%s'.), 
sha1_to_hex(remote));
+
+   read_cache_unmerged();
+
+   if (fast_forward_to(head_tree, head_tree, 1))
+   return -1;
+
+   if (write_cache_as_tree(index, 0, NULL))
+   return -1;
+
+   index_tree = parse_tree_indirect(index);
+   if (!index_tree)
+   return error(_(Could not parse object '%s'.), 
sha1_to_hex(index));
+
+   if (fast_forward_to(index_tree, remote_tree, 0))
+   return -1;
+
+   memset(pathspec, 0, sizeof(pathspec));
+
+   lock_file = xcalloc(1, sizeof(struct lock_file));
+   hold_locked_index(lock_file, 1);
+
+   if (read_tree(remote_tree, 0, pathspec)) {
+   rollback_lock_file(lock_file);
+   return -1;
+   }
+
+   if (write_locked_index(the_index, lock_file, COMMIT_LOCK))
+   die(_(unable to write new index file));
+
+   remove_branch_state();
+
+   return 0;
+}
+
+/**
+ * Resume the current am session by skipping the current patch.
+ */
+static void am_skip(struct am_state *state)
+{
+   unsigned char head[GIT_SHA1_RAWSZ];
+
+   if (get_sha1(HEAD, head))
+   hashcpy(head, EMPTY_TREE_SHA1_BIN);
+
+   if (clean_index(head, head))
+   die(_(failed to clean index));
+
+   am_next(state);
+   am_run(state, 0);
+}
+
+/**
  * parse_options() callback that validates and sets opt-value to the
  * PATCH_FORMAT_* enum value corresponding to `arg`.
  */
@@ -885,7 +997,8 @@ static int parse_opt_patchformat(const struct option *opt, 
const char *arg, int
 enum resume_mode {
RESUME_FALSE = 0,
RESUME_APPLY,
-   RESUME_RESOLVED
+   RESUME_RESOLVED,
+   RESUME_SKIP
 };
 
 int cmd_am(int argc, const char **argv, const char *prefix)
@@ -896,7 +1009,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 
const char * const usage[] = {
N_(git am [options] [(mbox|Maildir)...]),
-   N_(git am [options] --continue),
+   N_(git am [options] (--continue | --skip)),
NULL
};
 
@@ -910,6 +1023,9 @@ int cmd_am(int argc, const char **argv, const char 

[PATCH v6 12/45] builtin-am: don't parse mail when resuming

2015-07-19 Thread Paul Tan
Since 271440e (git-am: make it easier after fixing up an unapplicable
patch., 2005-10-25), when git am is run again after being paused, the
current mail message will not be re-parsed, but instead the contents of
the state directory's patch, msg and author-script files will be used
as-is instead.

Re-implement this in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---

Notes:
v6

New patch. A test for this in t4150 would be something like this:

test_expect_success 'do not parse mail when resuming' '
rm -fr .git/rebase-apply 
git reset --hard 
git checkout lorem2^^ 
test_must_fail git am lorem-move.patch 
test_path_is_dir .git/rebase-apply 
test_cmp_rev lorem2^^ HEAD 
echo resolved file 
git diff .git/rebase-apply/patch 
git reset --hard 
git am 6 
test_path_is_missing .git/rebase-apply 
test resolved = $(cat file)
'

However, it relies on stdin being a TTY so I can't add it to the
more-am-tests patch series :-/

 builtin/am.c | 34 +-
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index fd26721..ec579a6 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -776,8 +776,12 @@ static void validate_resume_state(const struct am_state 
*state)
 
 /**
  * Applies all queued mail.
+ *
+ * If `resume` is true, we are resuming. The msg and authorship fields, as
+ * well as the state directory's patch file is used as-is for applying the
+ * patch and committing it.
  */
-static void am_run(struct am_state *state)
+static void am_run(struct am_state *state, int resume)
 {
const char *argv_gc_auto[] = {gc, --auto, NULL};
struct strbuf sb = STRBUF_INIT;
@@ -795,11 +799,16 @@ static void am_run(struct am_state *state)
if (!file_exists(mail))
goto next;
 
-   if (parse_mail(state, mail))
-   goto next; /* mail should be skipped */
+   if (resume) {
+   validate_resume_state(state);
+   resume = 0;
+   } else {
+   if (parse_mail(state, mail))
+   goto next; /* mail should be skipped */
 
-   write_author_script(state);
-   write_commit_msg(state);
+   write_author_script(state);
+   write_commit_msg(state);
+   }
 
printf_ln(_(Applying: %.*s), linelen(state-msg), state-msg);
 
@@ -855,7 +864,7 @@ static void am_resolve(struct am_state *state)
do_commit(state);
 
am_next(state);
-   am_run(state);
+   am_run(state, 0);
 }
 
 /**
@@ -875,6 +884,7 @@ static int parse_opt_patchformat(const struct option *opt, 
const char *arg, int
 
 enum resume_mode {
RESUME_FALSE = 0,
+   RESUME_APPLY,
RESUME_RESOLVED
 };
 
@@ -927,9 +937,12 @@ int cmd_am(int argc, const char **argv, const char *prefix)
if (read_index_preload(the_index, NULL)  0)
die(_(failed to read the index));
 
-   if (am_in_progress(state))
+   if (am_in_progress(state)) {
+   if (resume == RESUME_FALSE)
+   resume = RESUME_APPLY;
+
am_load(state);
-   else {
+   } else {
struct argv_array paths = ARGV_ARRAY_INIT;
int i;
 
@@ -950,7 +963,10 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 
switch (resume) {
case RESUME_FALSE:
-   am_run(state);
+   am_run(state, 0);
+   break;
+   case RESUME_APPLY:
+   am_run(state, 1);
break;
case RESUME_RESOLVED:
am_resolve(state);
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 10/45] builtin-am: refuse to apply patches if index is dirty

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07), git-am
will refuse to apply patches if the index is dirty. Re-implement this
behavior in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 45 +
 1 file changed, 45 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index a2811b6..537ad62 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -14,6 +14,8 @@
 #include cache-tree.h
 #include refs.h
 #include commit.h
+#include diff.h
+#include diffcore.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -565,6 +567,43 @@ static void refresh_and_write_cache(void)
 }
 
 /**
+ * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn
+ * branch, returns 1 if there are entries in the index, 0 otherwise. If an
+ * strbuf is provided, the space-separated list of files that differ will be
+ * appended to it.
+ */
+static int index_has_changes(struct strbuf *sb)
+{
+   unsigned char head[GIT_SHA1_RAWSZ];
+   int i;
+
+   if (!get_sha1_tree(HEAD, head)) {
+   struct diff_options opt;
+
+   diff_setup(opt);
+   DIFF_OPT_SET(opt, EXIT_WITH_STATUS);
+   if (!sb)
+   DIFF_OPT_SET(opt, QUICK);
+   do_diff_cache(head, opt);
+   diffcore_std(opt);
+   for (i = 0; sb  i  diff_queued_diff.nr; i++) {
+   if (i)
+   strbuf_addch(sb, ' ');
+   strbuf_addstr(sb, diff_queued_diff.queue[i]-two-path);
+   }
+   diff_flush(opt);
+   return DIFF_OPT_TST(opt, HAS_CHANGES) != 0;
+   } else {
+   for (i = 0; sb  i  active_nr; i++) {
+   if (i)
+   strbuf_addch(sb, ' ');
+   strbuf_addstr(sb, active_cache[i]-name);
+   }
+   return !!active_nr;
+   }
+}
+
+/**
  * Parses `mail` using git-mailinfo, extracting its patch and authorship info.
  * state-msg will be set to the patch message. state-author_name,
  * state-author_email and state-author_date will be set to the patch author's
@@ -726,9 +765,15 @@ static void do_commit(const struct am_state *state)
 static void am_run(struct am_state *state)
 {
const char *argv_gc_auto[] = {gc, --auto, NULL};
+   struct strbuf sb = STRBUF_INIT;
 
refresh_and_write_cache();
 
+   if (index_has_changes(sb))
+   die(_(Dirty index: cannot apply patches (dirty: %s)), sb.buf);
+
+   strbuf_release(sb);
+
while (state-cur = state-last) {
const char *mail = am_path(state, msgnum(state));
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 20/45] builtin-am: implement --3way, am.threeWay

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sh supported the --3way option, and if set, would attempt to do a
3-way merge if the initial patch application fails.

Since d96a275 (git-am: add am.threeWay config variable, 2015-06-04), the
setting am.threeWay configures if the --3way option is set by default.

Since 5d86861 (am -3: list the paths that needed 3-way fallback,
2012-03-28), in a 3-way merge git-am.sh would list the paths that needed
3-way fallback, so that the user can review them more carefully to spot
mismerges.

Re-implement the above in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 156 +--
 1 file changed, 152 insertions(+), 4 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index 7c0f604..7237fff 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -19,6 +19,8 @@
 #include unpack-trees.h
 #include branch.h
 #include sequencer.h
+#include revision.h
+#include merge-recursive.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -83,6 +85,7 @@ struct am_state {
int prec;
 
/* various operating modes and command line options */
+   int threeway;
int quiet;
int append_signoff;
const char *resolvemsg;
@@ -100,6 +103,8 @@ static void am_state_init(struct am_state *state, const 
char *dir)
state-dir = xstrdup(dir);
 
state-prec = 4;
+
+   git_config_get_bool(am.threeway, state-threeway);
 }
 
 /**
@@ -352,6 +357,9 @@ static void am_load(struct am_state *state)
 
read_commit_msg(state);
 
+   read_state_file(sb, state, threeway, 1);
+   state-threeway = !strcmp(sb.buf, t);
+
read_state_file(sb, state, quiet, 1);
state-quiet = !strcmp(sb.buf, t);
 
@@ -536,6 +544,8 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
die(_(Failed to split patches.));
}
 
+   write_file(am_path(state, threeway), 1, state-threeway ? t : f);
+
write_file(am_path(state, quiet), 1, state-quiet ? t : f);
 
write_file(am_path(state, sign), 1, state-append_signoff ? t : 
f);
@@ -766,16 +776,34 @@ finish:
 }
 
 /**
- * Applies current patch with git-apply. Returns 0 on success, -1 otherwise.
+ * Applies current patch with git-apply. Returns 0 on success, -1 otherwise. If
+ * `index_file` is not NULL, the patch will be applied to that index.
  */
-static int run_apply(const struct am_state *state)
+static int run_apply(const struct am_state *state, const char *index_file)
 {
struct child_process cp = CHILD_PROCESS_INIT;
 
cp.git_cmd = 1;
 
+   if (index_file)
+   argv_array_pushf(cp.env_array, GIT_INDEX_FILE=%s, 
index_file);
+
+   /*
+* If we are allowed to fall back on 3-way merge, don't give false
+* errors during the initial attempt.
+*/
+   if (state-threeway  !index_file) {
+   cp.no_stdout = 1;
+   cp.no_stderr = 1;
+   }
+
argv_array_push(cp.args, apply);
-   argv_array_push(cp.args, --index);
+
+   if (index_file)
+   argv_array_push(cp.args, --cached);
+   else
+   argv_array_push(cp.args, --index);
+
argv_array_push(cp.args, am_path(state, patch));
 
if (run_command(cp))
@@ -783,8 +811,106 @@ static int run_apply(const struct am_state *state)
 
/* Reload index as git-apply will have modified it. */
discard_cache();
+   read_cache_from(index_file ? index_file : get_index_file());
+
+   return 0;
+}
+
+/**
+ * Builds an index that contains just the blobs needed for a 3way merge.
+ */
+static int build_fake_ancestor(const struct am_state *state, const char 
*index_file)
+{
+   struct child_process cp = CHILD_PROCESS_INIT;
+
+   cp.git_cmd = 1;
+   argv_array_push(cp.args, apply);
+   argv_array_pushf(cp.args, --build-fake-ancestor=%s, index_file);
+   argv_array_push(cp.args, am_path(state, patch));
+
+   if (run_command(cp))
+   return -1;
+
+   return 0;
+}
+
+/**
+ * Attempt a threeway merge, using index_path as the temporary index.
+ */
+static int fall_back_threeway(const struct am_state *state, const char 
*index_path)
+{
+   unsigned char orig_tree[GIT_SHA1_RAWSZ], his_tree[GIT_SHA1_RAWSZ],
+ our_tree[GIT_SHA1_RAWSZ];
+   const unsigned char *bases[1] = {orig_tree};
+   struct merge_options o;
+   struct commit *result;
+   char *his_tree_name;
+
+   if (get_sha1(HEAD, our_tree)  0)
+   hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);
+
+   if (build_fake_ancestor(state, index_path))
+   return error(could not build fake ancestor);
+
+   discard_cache();
+   read_cache_from(index_path);
+
+   if (write_index_as_tree(orig_tree, the_index, index_path, 0, NULL))
+   return error(_(Repository lacks necessary blobs 

[PATCH v6 24/45] builtin-am: implement -u/--utf8

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sh supported the -u,--utf8 option. If set, the -u option will be
passed to git-mailinfo to re-code the commit log message and authorship
in the charset specified by i18n.commitencoding. If unset, the -n option
will be passed to git-mailinfo, which disables the re-encoding.

Since d84029b (--utf8 is now default for 'git-am', 2007-01-08), --utf8
is specified by default in git-am.sh.

Re-implement the above in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 398debf..a64a859 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -90,6 +90,7 @@ struct am_state {
int threeway;
int quiet;
int append_signoff;
+   int utf8;
const char *resolvemsg;
int rebasing;
 };
@@ -108,6 +109,8 @@ static void am_state_init(struct am_state *state, const 
char *dir)
state-prec = 4;
 
git_config_get_bool(am.threeway, state-threeway);
+
+   state-utf8 = 1;
 }
 
 /**
@@ -369,6 +372,9 @@ static void am_load(struct am_state *state)
read_state_file(sb, state, sign, 1);
state-append_signoff = !strcmp(sb.buf, t);
 
+   read_state_file(sb, state, utf8, 1);
+   state-utf8 = !strcmp(sb.buf, t);
+
state-rebasing = !!file_exists(am_path(state, rebasing));
 
strbuf_release(sb);
@@ -558,6 +564,8 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
 
write_file(am_path(state, sign), 1, state-append_signoff ? t : 
f);
 
+   write_file(am_path(state, utf8), 1, state-utf8 ? t : f);
+
if (state-rebasing)
write_file(am_path(state, rebasing), 1, %s, );
else
@@ -724,6 +732,7 @@ static int parse_mail(struct am_state *state, const char 
*mail)
cp.out = xopen(am_path(state, info), O_WRONLY | O_CREAT, 0777);
 
argv_array_push(cp.args, mailinfo);
+   argv_array_push(cp.args, state-utf8 ? -u : -n);
argv_array_push(cp.args, am_path(state, msg));
argv_array_push(cp.args, am_path(state, patch));
 
@@ -1461,6 +1470,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
OPT__QUIET(state.quiet, N_(be quiet)),
OPT_BOOL('s', signoff, state.append_signoff,
N_(add a Signed-off-by line to the commit message)),
+   OPT_BOOL('u', utf8, state.utf8,
+   N_(recode into utf8 (default))),
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 17/45] builtin-am: exit with user friendly message on failure

2015-07-19 Thread Paul Tan
Since ced9456 (Give the user a hint for how to continue in the case that
git-am fails because it requires user intervention, 2006-05-02), git-am
prints additional information on how the user can re-invoke git-am to
resume patch application after resolving the failure. Re-implement this
through the die_user_resolve() function.

Since cc12005 (Make git rebase interactive help match documentation.,
2006-05-13), git-am supports the --resolvemsg option which is used by
git-rebase to override the message printed out when git-am fails.
Re-implement this option.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 30 ++
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index e0b86d1..fb428f9 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -83,6 +83,7 @@ struct am_state {
 
/* various operating modes and command line options */
int quiet;
+   const char *resolvemsg;
 };
 
 /**
@@ -647,6 +648,25 @@ static int index_has_changes(struct strbuf *sb)
 }
 
 /**
+ * Dies with a user-friendly message on how to proceed after resolving the
+ * problem. This message can be overridden with state-resolvemsg.
+ */
+static void NORETURN die_user_resolve(const struct am_state *state)
+{
+   if (state-resolvemsg) {
+   printf_ln(%s, state-resolvemsg);
+   } else {
+   const char *cmdline = git am;
+
+   printf_ln(_(When you have resolved this problem, run \%s 
--continue\.), cmdline);
+   printf_ln(_(If you prefer to skip this patch, run \%s 
--skip\ instead.), cmdline);
+   printf_ln(_(To restore the original branch and stop patching, 
run \%s --abort\.), cmdline);
+   }
+
+   exit(128);
+}
+
+/**
  * Parses `mail` using git-mailinfo, extracting its patch and authorship info.
  * state-msg will be set to the patch message. state-author_name,
  * state-author_email and state-author_date will be set to the patch author's
@@ -706,7 +726,7 @@ static int parse_mail(struct am_state *state, const char 
*mail)
 
if (is_empty_file(am_path(state, patch))) {
printf_ln(_(Patch is empty. Was it split wrong?));
-   exit(128);
+   die_user_resolve(state);
}
 
strbuf_addstr(msg, \n\n);
@@ -871,7 +891,7 @@ static void am_run(struct am_state *state, int resume)
printf_ln(_(The copy of the patch that failed 
is found in: %s),
am_path(state, patch));
 
-   exit(128);
+   die_user_resolve(state);
}
 
do_commit(state);
@@ -899,13 +919,13 @@ static void am_resolve(struct am_state *state)
printf_ln(_(No changes - did you forget to use 'git add'?\n
If there is nothing left to stage, chances are that 
something else\n
already introduced the same changes; you might want to 
skip this patch.));
-   exit(128);
+   die_user_resolve(state);
}
 
if (unmerged_cache()) {
printf_ln(_(You still have unmerged paths in your index.\n
Did you forget to use 'git add'?));
-   exit(128);
+   die_user_resolve(state);
}
 
do_commit(state);
@@ -1132,6 +1152,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
+   OPT_STRING(0, resolvemsg, state.resolvemsg, NULL,
+   N_(override error message when patch failure occurs)),
OPT_CMDMODE(0, continue, resume,
N_(continue applying patches after resolving a 
conflict),
RESUME_RESOLVED),
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 11/45] builtin-am: implement --resolved/--continue

2015-07-19 Thread Paul Tan
Since 0c15cc9 (git-am: --resolved., 2005-11-16), git-am supported
resuming from a failed patch application. The user will manually apply
the patch, and the run git am --resolved which will then commit the
resulting index. Re-implement this feature by introducing am_resolve().

Since it makes no sense for the user to run am --resolved when there is
no session in progress, we error out in this case.

Signed-off-by: Paul Tan pyoka...@gmail.com
---

Notes:
v6

* Extracted out the validation of the state directory for resuming into
  a separate validate_resume_state() function, so that it can be shared
  with the next patch.

 builtin/am.c | 72 +++-
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/builtin/am.c b/builtin/am.c
index 537ad62..fd26721 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -760,6 +760,21 @@ static void do_commit(const struct am_state *state)
 }
 
 /**
+ * Validates the am_state for resuming -- the msg and authorship fields must
+ * be filled up.
+ */
+static void validate_resume_state(const struct am_state *state)
+{
+   if (!state-msg)
+   die(_(cannot resume: %s does not exist.),
+   am_path(state, final-commit));
+
+   if (!state-author_name || !state-author_email || !state-author_date)
+   die(_(cannot resume: %s does not exist.),
+   am_path(state, author-script));
+}
+
+/**
  * Applies all queued mail.
  */
 static void am_run(struct am_state *state)
@@ -814,6 +829,36 @@ next:
 }
 
 /**
+ * Resume the current am session after patch application failure. The user did
+ * all the hard work, and we do not have to do any patch application. Just
+ * trust and commit what the user has in the index and working tree.
+ */
+static void am_resolve(struct am_state *state)
+{
+   validate_resume_state(state);
+
+   printf_ln(_(Applying: %.*s), linelen(state-msg), state-msg);
+
+   if (!index_has_changes(NULL)) {
+   printf_ln(_(No changes - did you forget to use 'git add'?\n
+   If there is nothing left to stage, chances are that 
something else\n
+   already introduced the same changes; you might want to 
skip this patch.));
+   exit(128);
+   }
+
+   if (unmerged_cache()) {
+   printf_ln(_(You still have unmerged paths in your index.\n
+   Did you forget to use 'git add'?));
+   exit(128);
+   }
+
+   do_commit(state);
+
+   am_next(state);
+   am_run(state);
+}
+
+/**
  * parse_options() callback that validates and sets opt-value to the
  * PATCH_FORMAT_* enum value corresponding to `arg`.
  */
@@ -828,13 +873,20 @@ static int parse_opt_patchformat(const struct option 
*opt, const char *arg, int
return 0;
 }
 
+enum resume_mode {
+   RESUME_FALSE = 0,
+   RESUME_RESOLVED
+};
+
 int cmd_am(int argc, const char **argv, const char *prefix)
 {
struct am_state state;
int patch_format = PATCH_FORMAT_UNKNOWN;
+   enum resume_mode resume = RESUME_FALSE;
 
const char * const usage[] = {
N_(git am [options] [(mbox|Maildir)...]),
+   N_(git am [options] --continue),
NULL
};
 
@@ -842,6 +894,12 @@ int cmd_am(int argc, const char **argv, const char *prefix)
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
+   OPT_CMDMODE(0, continue, resume,
+   N_(continue applying patches after resolving a 
conflict),
+   RESUME_RESOLVED),
+   OPT_CMDMODE('r', resolved, resume,
+   N_(synonyms for --continue),
+   RESUME_RESOLVED),
OPT_END()
};
 
@@ -875,6 +933,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
struct argv_array paths = ARGV_ARRAY_INIT;
int i;
 
+   if (resume)
+   die(_(Resolve operation not in progress, we are not 
resuming.));
+
for (i = 0; i  argc; i++) {
if (is_absolute_path(argv[i]) || !prefix)
argv_array_push(paths, argv[i]);
@@ -887,7 +948,16 @@ int cmd_am(int argc, const char **argv, const char *prefix)
argv_array_clear(paths);
}
 
-   am_run(state);
+   switch (resume) {
+   case RESUME_FALSE:
+   am_run(state);
+   break;
+   case RESUME_RESOLVED:
+   am_resolve(state);
+   break;
+   default:
+   die(BUG: invalid resume value);
+   }
 
am_state_release(state);
 
-- 
2.5.0.rc2.110.gb39b692

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to 

[PATCH v6 22/45] builtin-am: bypass git-mailinfo when --rebasing

2015-07-19 Thread Paul Tan
Since 5e835ca (rebase: do not munge commit log message, 2008-04-16),
git am --rebasing no longer gets the commit log message from the patch,
but reads it directly from the commit identified by the From  header
line.

Since 43c2325 (am: use get_author_ident_from_commit instead of mailinfo
when rebasing, 2010-06-16), git am --rebasing also gets the author name,
email and date directly from the commit.

Since 0fbb95d (am: don't call mailinfo if $rebasing, 2012-06-26), git am
--rebasing does not use git-mailinfo to get the patch body, but rather
generates it directly from the commit itself.

The above 3 commits introduced a separate parse_mail() code path in
git-am.sh's --rebasing mode that bypasses git-mailinfo. Re-implement
this code path in builtin/am.c as parse_mail_rebase().

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 134 ++-
 1 file changed, 133 insertions(+), 1 deletion(-)

diff --git a/builtin/am.c b/builtin/am.c
index 3107aba..01f01bf 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -21,6 +21,8 @@
 #include sequencer.h
 #include revision.h
 #include merge-recursive.h
+#include revision.h
+#include log-tree.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -790,6 +792,129 @@ finish:
 }
 
 /**
+ * Sets commit_id to the commit hash where the mail was generated from.
+ * Returns 0 on success, -1 on failure.
+ */
+static int get_mail_commit_sha1(unsigned char *commit_id, const char *mail)
+{
+   struct strbuf sb = STRBUF_INIT;
+   FILE *fp = xfopen(mail, r);
+   const char *x;
+
+   if (strbuf_getline(sb, fp, '\n'))
+   return -1;
+
+   if (!skip_prefix(sb.buf, From , x))
+   return -1;
+
+   if (get_sha1_hex(x, commit_id)  0)
+   return -1;
+
+   strbuf_release(sb);
+   fclose(fp);
+   return 0;
+}
+
+/**
+ * Sets state-msg, state-author_name, state-author_email, state-author_date
+ * to the commit's respective info.
+ */
+static void get_commit_info(struct am_state *state, struct commit *commit)
+{
+   const char *buffer, *ident_line, *author_date, *msg;
+   size_t ident_len;
+   struct ident_split ident_split;
+   struct strbuf sb = STRBUF_INIT;
+
+   buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding());
+
+   ident_line = find_commit_header(buffer, author, ident_len);
+
+   if (split_ident_line(ident_split, ident_line, ident_len)  0) {
+   strbuf_add(sb, ident_line, ident_len);
+   die(_(invalid ident line: %s), sb.buf);
+   }
+
+   assert(!state-author_name);
+   if (ident_split.name_begin) {
+   strbuf_add(sb, ident_split.name_begin,
+   ident_split.name_end - ident_split.name_begin);
+   state-author_name = strbuf_detach(sb, NULL);
+   } else
+   state-author_name = xstrdup();
+
+   assert(!state-author_email);
+   if (ident_split.mail_begin) {
+   strbuf_add(sb, ident_split.mail_begin,
+   ident_split.mail_end - ident_split.mail_begin);
+   state-author_email = strbuf_detach(sb, NULL);
+   } else
+   state-author_email = xstrdup();
+
+   author_date = show_ident_date(ident_split, DATE_NORMAL);
+   strbuf_addstr(sb, author_date);
+   assert(!state-author_date);
+   state-author_date = strbuf_detach(sb, NULL);
+
+   assert(!state-msg);
+   msg = strstr(buffer, \n\n);
+   if (!msg)
+   die(_(unable to parse commit %s), 
sha1_to_hex(commit-object.sha1));
+   state-msg = xstrdup(msg + 2);
+   state-msg_len = strlen(state-msg);
+}
+
+/**
+ * Writes `commit` as a patch to the state directory's patch file.
+ */
+static void write_commit_patch(const struct am_state *state, struct commit 
*commit)
+{
+   struct rev_info rev_info;
+   FILE *fp;
+
+   fp = xfopen(am_path(state, patch), w);
+   init_revisions(rev_info, NULL);
+   rev_info.diff = 1;
+   rev_info.abbrev = 0;
+   rev_info.disable_stdin = 1;
+   rev_info.show_root_diff = 1;
+   rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
+   rev_info.no_commit_id = 1;
+   DIFF_OPT_SET(rev_info.diffopt, BINARY);
+   DIFF_OPT_SET(rev_info.diffopt, FULL_INDEX);
+   rev_info.diffopt.use_color = 0;
+   rev_info.diffopt.file = fp;
+   rev_info.diffopt.close_file = 1;
+   add_pending_object(rev_info, commit-object, );
+   diff_setup_done(rev_info.diffopt);
+   log_tree_commit(rev_info, commit);
+}
+
+/**
+ * Like parse_mail(), but parses the mail by looking up its commit ID
+ * directly. This is used in --rebasing mode to bypass git-mailinfo's munging
+ * of patches.
+ *
+ * Will always return 0 as the patch should never be skipped.
+ */
+static int parse_mail_rebase(struct am_state *state, const char *mail)
+{
+   struct commit *commit;
+   unsigned char 

[PATCH v6 08/45] builtin-am: apply patch with git-apply

2015-07-19 Thread Paul Tan
Implement applying the patch to the index using git-apply.

If a file is unchanged but stat-dirty, git-apply may erroneously fail to
apply patches, thinking that they conflict with a dirty working tree.

As such, since 2a6f08a (am: refresh the index at start and --resolved,
2011-08-15), git-am will refresh the index before applying patches.
Re-implement this behavior.

Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Paul Tan pyoka...@gmail.com
---

Notes:
v6

* refresh_and_write_cache(): use a heap-allocated lock_file instead of a
  static-allocated one to allow the function to be reentrant.

* refresh_and_write_cache(): remove the rollback_lock_file() -- since we
  ensure that the write_locked_index() succeeds there is no need to call
  it.

 builtin/am.c | 72 +++-
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/builtin/am.c b/builtin/am.c
index 63f0fa4..1f198e4 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -10,6 +10,7 @@
 #include dir.h
 #include run-command.h
 #include quote.h
+#include lockfile.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -42,6 +43,14 @@ static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
return 0;
 }
 
+/**
+ * Returns the length of the first line of msg.
+ */
+static int linelen(const char *msg)
+{
+   return strchrnul(msg, '\n') - msg;
+}
+
 enum patch_format {
PATCH_FORMAT_UNKNOWN = 0,
PATCH_FORMAT_MBOX
@@ -540,6 +549,19 @@ static const char *msgnum(const struct am_state *state)
 }
 
 /**
+ * Refresh and write index.
+ */
+static void refresh_and_write_cache(void)
+{
+   struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
+
+   hold_locked_index(lock_file, 1);
+   refresh_cache(REFRESH_QUIET);
+   if (write_locked_index(the_index, lock_file, COMMIT_LOCK))
+   die(_(unable to write index file));
+}
+
+/**
  * Parses `mail` using git-mailinfo, extracting its patch and authorship info.
  * state-msg will be set to the patch message. state-author_name,
  * state-author_email and state-author_date will be set to the patch author's
@@ -629,10 +651,35 @@ finish:
 }
 
 /**
+ * Applies current patch with git-apply. Returns 0 on success, -1 otherwise.
+ */
+static int run_apply(const struct am_state *state)
+{
+   struct child_process cp = CHILD_PROCESS_INIT;
+
+   cp.git_cmd = 1;
+
+   argv_array_push(cp.args, apply);
+   argv_array_push(cp.args, --index);
+   argv_array_push(cp.args, am_path(state, patch));
+
+   if (run_command(cp))
+   return -1;
+
+   /* Reload index as git-apply will have modified it. */
+   discard_cache();
+   read_cache();
+
+   return 0;
+}
+
+/**
  * Applies all queued mail.
  */
 static void am_run(struct am_state *state)
 {
+   refresh_and_write_cache();
+
while (state-cur = state-last) {
const char *mail = am_path(state, msgnum(state));
 
@@ -645,7 +692,27 @@ static void am_run(struct am_state *state)
write_author_script(state);
write_commit_msg(state);
 
-   /* NEEDSWORK: Patch application not implemented yet */
+   printf_ln(_(Applying: %.*s), linelen(state-msg), state-msg);
+
+   if (run_apply(state)  0) {
+   int advice_amworkdir = 1;
+
+   printf_ln(_(Patch failed at %s %.*s), msgnum(state),
+   linelen(state-msg), state-msg);
+
+   git_config_get_bool(advice.amworkdir, 
advice_amworkdir);
+
+   if (advice_amworkdir)
+   printf_ln(_(The copy of the patch that failed 
is found in: %s),
+   am_path(state, patch));
+
+   exit(128);
+   }
+
+   /*
+* NEEDSWORK: After the patch has been applied to the index
+* with git-apply, we need to make commit as well.
+*/
 
 next:
am_next(state);
@@ -707,6 +774,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 
argc = parse_options(argc, argv, prefix, options, usage, 0);
 
+   if (read_index_preload(the_index, NULL)  0)
+   die(_(failed to read the index));
+
if (am_in_progress(state))
am_load(state);
else {
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 16/45] builtin-am: implement -q/--quiet

2015-07-19 Thread Paul Tan
Since 0e987a1 (am, rebase: teach quiet option, 2009-06-16), git-am
supported the --quiet option, and when told to be quiet, would only
speak on failure. Re-implement this by introducing the say() function,
which works like fprintf_ln(), but would only write to the stream when
state-quiet is false.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 31 ---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index fa522f5..e0b86d1 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -80,6 +80,9 @@ struct am_state {
 
/* number of digits in patch filename */
int prec;
+
+   /* various operating modes and command line options */
+   int quiet;
 };
 
 /**
@@ -117,6 +120,22 @@ static inline const char *am_path(const struct am_state 
*state, const char *path
 }
 
 /**
+ * If state-quiet is false, calls fprintf(fp, fmt, ...), and appends a newline
+ * at the end.
+ */
+static void say(const struct am_state *state, FILE *fp, const char *fmt, ...)
+{
+   va_list ap;
+
+   va_start(ap, fmt);
+   if (!state-quiet) {
+   vfprintf(fp, fmt, ap);
+   putc('\n', fp);
+   }
+   va_end(ap);
+}
+
+/**
  * Returns 1 if there is an am session in progress, 0 otherwise.
  */
 static int am_in_progress(const struct am_state *state)
@@ -330,6 +349,9 @@ static void am_load(struct am_state *state)
 
read_commit_msg(state);
 
+   read_state_file(sb, state, quiet, 1);
+   state-quiet = !strcmp(sb.buf, t);
+
strbuf_release(sb);
 }
 
@@ -508,6 +530,8 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
die(_(Failed to split patches.));
}
 
+   write_file(am_path(state, quiet), 1, state-quiet ? t : f);
+
if (!get_sha1(HEAD, curr_head)) {
write_file(am_path(state, abort-safety), 1, %s, 
sha1_to_hex(curr_head));
update_ref(am, ORIG_HEAD, curr_head, NULL, 0, 
UPDATE_REFS_DIE_ON_ERR);
@@ -756,7 +780,7 @@ static void do_commit(const struct am_state *state)
commit_list_insert(lookup_commit(parent), parents);
} else {
ptr = NULL;
-   fprintf_ln(stderr, _(applying to an empty history));
+   say(state, stderr, _(applying to an empty history));
}
 
author = fmt_ident(state-author_name, state-author_email,
@@ -833,7 +857,7 @@ static void am_run(struct am_state *state, int resume)
write_commit_msg(state);
}
 
-   printf_ln(_(Applying: %.*s), linelen(state-msg), state-msg);
+   say(state, stdout, _(Applying: %.*s), linelen(state-msg), 
state-msg);
 
if (run_apply(state)  0) {
int advice_amworkdir = 1;
@@ -869,7 +893,7 @@ static void am_resolve(struct am_state *state)
 {
validate_resume_state(state);
 
-   printf_ln(_(Applying: %.*s), linelen(state-msg), state-msg);
+   say(state, stdout, _(Applying: %.*s), linelen(state-msg), 
state-msg);
 
if (!index_has_changes(NULL)) {
printf_ln(_(No changes - did you forget to use 'git add'?\n
@@ -1104,6 +1128,7 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
};
 
struct option options[] = {
+   OPT__QUIET(state.quiet, N_(be quiet)),
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 15/45] builtin-am: reject patches when there's a session in progress

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07), git-am
would error out if the user gave it mbox(s) on the command-line, but
there was a session in progress.

Since c95b138 (Fix git-am safety checks, 2006-09-15), git-am would
detect if the user attempted to feed it a mbox via stdin, by checking if
stdin is not a tty and there is no resume command given.

Re-implement the above two safety checks.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 8a054ee..fa522f5 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1147,6 +1147,21 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
die(_(failed to read the index));
 
if (am_in_progress(state)) {
+   /*
+* Catch user error to feed us patches when there is a session
+* in progress:
+*
+* 1. mbox path(s) are provided on the command-line.
+* 2. stdin is not a tty: the user is trying to feed us a patch
+*from standard input. This is somewhat unreliable -- stdin
+*could be /dev/null for example and the caller did not
+*intend to feed us a patch but wanted to continue
+*unattended.
+*/
+   if (argc || (resume == RESUME_FALSE  !isatty(0)))
+   die(_(previous rebase directory %s still exists but 
mbox given.),
+   state.dir);
+
if (resume == RESUME_FALSE)
resume = RESUME_APPLY;
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 18/45] builtin-am: implement -s/--signoff

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07), git-am
supported the --signoff option which will append a signoff at the end of
the commit messsage. Re-implement this feature in parse_mail() by
calling append_signoff() if the option is set.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index fb428f9..7c0f604 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -18,6 +18,7 @@
 #include diffcore.h
 #include unpack-trees.h
 #include branch.h
+#include sequencer.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -83,6 +84,7 @@ struct am_state {
 
/* various operating modes and command line options */
int quiet;
+   int append_signoff;
const char *resolvemsg;
 };
 
@@ -353,6 +355,9 @@ static void am_load(struct am_state *state)
read_state_file(sb, state, quiet, 1);
state-quiet = !strcmp(sb.buf, t);
 
+   read_state_file(sb, state, sign, 1);
+   state-append_signoff = !strcmp(sb.buf, t);
+
strbuf_release(sb);
 }
 
@@ -533,6 +538,8 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
 
write_file(am_path(state, quiet), 1, state-quiet ? t : f);
 
+   write_file(am_path(state, sign), 1, state-append_signoff ? t : 
f);
+
if (!get_sha1(HEAD, curr_head)) {
write_file(am_path(state, abort-safety), 1, %s, 
sha1_to_hex(curr_head));
update_ref(am, ORIG_HEAD, curr_head, NULL, 0, 
UPDATE_REFS_DIE_ON_ERR);
@@ -734,6 +741,9 @@ static int parse_mail(struct am_state *state, const char 
*mail)
die_errno(_(could not read '%s'), am_path(state, msg));
stripspace(msg, 0);
 
+   if (state-append_signoff)
+   append_signoff(msg, 0, 0);
+
assert(!state-author_name);
state-author_name = strbuf_detach(author_name, NULL);
 
@@ -1149,6 +1159,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
 
struct option options[] = {
OPT__QUIET(state.quiet, N_(be quiet)),
+   OPT_BOOL('s', signoff, state.append_signoff,
+   N_(add a Signed-off-by line to the commit message)),
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 14/45] builtin-am: implement --abort

2015-07-19 Thread Paul Tan
Since 3e5057a (git am --abort, 2008-07-16), git-am supported the --abort
option that will rewind HEAD back to the original commit. Re-implement
this through am_abort().

Since 7b3b7e3 (am --abort: keep unrelated commits since the last failure
and warn, 2010-12-21), to prevent commits made since the last failure
from being lost, git-am will not rewind HEAD back to the original
commit if HEAD moved since the last failure. Re-implement this through
safe_to_abort().

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 102 +--
 1 file changed, 99 insertions(+), 3 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index 765844b..8a054ee 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -490,6 +490,8 @@ static int split_mail(struct am_state *state, enum 
patch_format patch_format,
 static void am_setup(struct am_state *state, enum patch_format patch_format,
const char **paths)
 {
+   unsigned char curr_head[GIT_SHA1_RAWSZ];
+
if (!patch_format)
patch_format = detect_patch_format(paths);
 
@@ -506,6 +508,14 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
die(_(Failed to split patches.));
}
 
+   if (!get_sha1(HEAD, curr_head)) {
+   write_file(am_path(state, abort-safety), 1, %s, 
sha1_to_hex(curr_head));
+   update_ref(am, ORIG_HEAD, curr_head, NULL, 0, 
UPDATE_REFS_DIE_ON_ERR);
+   } else {
+   write_file(am_path(state, abort-safety), 1, %s, );
+   delete_ref(ORIG_HEAD, NULL, 0);
+   }
+
/*
 * NOTE: Since the next and last files determine if an am_state
 * session is in progress, they should be written last.
@@ -522,6 +532,8 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
  */
 static void am_next(struct am_state *state)
 {
+   unsigned char head[GIT_SHA1_RAWSZ];
+
free(state-author_name);
state-author_name = NULL;
 
@@ -538,6 +550,11 @@ static void am_next(struct am_state *state)
unlink(am_path(state, author-script));
unlink(am_path(state, final-commit));
 
+   if (!get_sha1(HEAD, head))
+   write_file(am_path(state, abort-safety), 1, %s, 
sha1_to_hex(head));
+   else
+   write_file(am_path(state, abort-safety), 1, %s, );
+
state-cur++;
write_file(am_path(state, next), 1, %d, state-cur);
 }
@@ -788,10 +805,14 @@ static void am_run(struct am_state *state, int resume)
const char *argv_gc_auto[] = {gc, --auto, NULL};
struct strbuf sb = STRBUF_INIT;
 
+   unlink(am_path(state, dirtyindex));
+
refresh_and_write_cache();
 
-   if (index_has_changes(sb))
+   if (index_has_changes(sb)) {
+   write_file(am_path(state, dirtyindex), 1, t);
die(_(Dirty index: cannot apply patches (dirty: %s)), sb.buf);
+   }
 
strbuf_release(sb);
 
@@ -980,6 +1001,74 @@ static void am_skip(struct am_state *state)
 }
 
 /**
+ * Returns true if it is safe to reset HEAD to the ORIG_HEAD, false otherwise.
+ *
+ * It is not safe to reset HEAD when:
+ * 1. git-am previously failed because the index was dirty.
+ * 2. HEAD has moved since git-am previously failed.
+ */
+static int safe_to_abort(const struct am_state *state)
+{
+   struct strbuf sb = STRBUF_INIT;
+   unsigned char abort_safety[GIT_SHA1_RAWSZ], head[GIT_SHA1_RAWSZ];
+
+   if (file_exists(am_path(state, dirtyindex)))
+   return 0;
+
+   if (read_state_file(sb, state, abort-safety, 1)  0) {
+   if (get_sha1_hex(sb.buf, abort_safety))
+   die(_(could not parse %s), am_path(state, 
abort_safety));
+   } else
+   hashclr(abort_safety);
+
+   if (get_sha1(HEAD, head))
+   hashclr(head);
+
+   if (!hashcmp(head, abort_safety))
+   return 1;
+
+   error(_(You seem to have moved HEAD since the last 'am' failure.\n
+   Not rewinding to ORIG_HEAD));
+
+   return 0;
+}
+
+/**
+ * Aborts the current am session if it is safe to do so.
+ */
+static void am_abort(struct am_state *state)
+{
+   unsigned char curr_head[GIT_SHA1_RAWSZ], orig_head[GIT_SHA1_RAWSZ];
+   int has_curr_head, has_orig_head;
+   const char *curr_branch;
+
+   if (!safe_to_abort(state)) {
+   am_destroy(state);
+   return;
+   }
+
+   curr_branch = resolve_refdup(HEAD, 0, curr_head, NULL);
+   has_curr_head = !is_null_sha1(curr_head);
+   if (!has_curr_head)
+   hashcpy(curr_head, EMPTY_TREE_SHA1_BIN);
+
+   has_orig_head = !get_sha1(ORIG_HEAD, orig_head);
+   if (!has_orig_head)
+   hashcpy(orig_head, EMPTY_TREE_SHA1_BIN);
+
+   clean_index(curr_head, orig_head);
+
+   if (has_orig_head)
+   update_ref(am --abort, HEAD, orig_head,
+

[PATCH v6 28/45] builtin-am: implement --[no-]scissors

2015-07-19 Thread Paul Tan
Since 017678b (am/mailinfo: Disable scissors processing by default,
2009-08-26), git-am supported the --[no-]scissors option, passing it to
git-mailinfo.

Re-implement support for this option in builtin/am.c.

Since the default setting of --scissors in git-mailinfo can be
configured with mailinfo.scissors (and perhaps through other settings in
the future), to be safe we make an explicit distinction between
SCISSORS_UNSET, SCISSORS_TRUE and SCISSORS_FALSE.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 48 
 1 file changed, 48 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 80f091e..1f79750 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -74,6 +74,12 @@ enum keep_type {
KEEP_NON_PATCH  /* pass -b flag to git-mailinfo */
 };
 
+enum scissors_type {
+   SCISSORS_UNSET = -1,
+   SCISSORS_FALSE = 0,  /* pass --no-scissors to git-mailinfo */
+   SCISSORS_TRUE/* pass --scissors to git-mailinfo */
+};
+
 struct am_state {
/* state directory path */
char *dir;
@@ -99,6 +105,7 @@ struct am_state {
int utf8;
int keep; /* enum keep_type */
int message_id;
+   int scissors; /* enum scissors_type */
const char *resolvemsg;
int rebasing;
 };
@@ -121,6 +128,8 @@ static void am_state_init(struct am_state *state, const 
char *dir)
state-utf8 = 1;
 
git_config_get_bool(am.messageid, state-message_id);
+
+   state-scissors = SCISSORS_UNSET;
 }
 
 /**
@@ -396,6 +405,14 @@ static void am_load(struct am_state *state)
read_state_file(sb, state, messageid, 1);
state-message_id = !strcmp(sb.buf, t);
 
+   read_state_file(sb, state, scissors, 1);
+   if (!strcmp(sb.buf, t))
+   state-scissors = SCISSORS_TRUE;
+   else if (!strcmp(sb.buf, f))
+   state-scissors = SCISSORS_FALSE;
+   else
+   state-scissors = SCISSORS_UNSET;
+
state-rebasing = !!file_exists(am_path(state, rebasing));
 
strbuf_release(sb);
@@ -616,6 +633,22 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
 
write_file(am_path(state, messageid), 1, state-message_id ? t : 
f);
 
+   switch (state-scissors) {
+   case SCISSORS_UNSET:
+   str = ;
+   break;
+   case SCISSORS_FALSE:
+   str = f;
+   break;
+   case SCISSORS_TRUE:
+   str = t;
+   break;
+   default:
+   die(BUG: invalid value for state-scissors);
+   }
+
+   write_file(am_path(state, scissors), 1, %s, str);
+
if (state-rebasing)
write_file(am_path(state, rebasing), 1, %s, );
else
@@ -800,6 +833,19 @@ static int parse_mail(struct am_state *state, const char 
*mail)
if (state-message_id)
argv_array_push(cp.args, -m);
 
+   switch (state-scissors) {
+   case SCISSORS_UNSET:
+   break;
+   case SCISSORS_FALSE:
+   argv_array_push(cp.args, --no-scissors);
+   break;
+   case SCISSORS_TRUE:
+   argv_array_push(cp.args, --scissors);
+   break;
+   default:
+   die(BUG: invalid value for state-scissors);
+   }
+
argv_array_push(cp.args, am_path(state, msg));
argv_array_push(cp.args, am_path(state, patch));
 
@@ -1552,6 +1598,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
{ OPTION_SET_INT, 0, no-keep-cr, keep_cr, NULL,
  N_(do not pass --keep-cr flag to git-mailsplit independent 
of am.keepcr),
  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 0},
+   OPT_BOOL('c', scissors, state.scissors,
+   N_(strip everything before a scissors line)),
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 29/45] builtin-am: pass git-apply's options to git-apply

2015-07-19 Thread Paul Tan
git-am.sh recognizes some of git-apply's options, and would pass them to
git-apply:

* --whitespace, since 8c31cb8 (git-am: --whitespace=x option.,
  2006-02-28)

* -C, since 67dad68 (add -C[NUM] to git-am, 2007-02-08)

* -p, since 2092a1f (Teach git-am to pass -p option down to git-apply,
  2007-02-11)

* --directory, since b47dfe9 (git-am: add --directory=dir option,
  2009-01-11)

* --reject, since b80da42 (git-am: implement --reject option passed to
  git-apply, 2009-01-23)

* --ignore-space-change, --ignore-whitespace, since 86c91f9 (git apply:
  option to ignore whitespace differences, 2009-08-04)

* --exclude, since 77e9e49 (am: pass exclude down to apply, 2011-08-03)

* --include, since 58725ef (am: support --include option, 2012-03-28)

* --reject, since b80da42 (git-am: implement --reject option passed to
  git-apply, 2009-01-23)

Re-implement support for these options in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 45 +
 1 file changed, 45 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 1f79750..9ff0736 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -106,6 +106,7 @@ struct am_state {
int keep; /* enum keep_type */
int message_id;
int scissors; /* enum scissors_type */
+   struct argv_array git_apply_opts;
const char *resolvemsg;
int rebasing;
 };
@@ -130,6 +131,8 @@ static void am_state_init(struct am_state *state, const 
char *dir)
git_config_get_bool(am.messageid, state-message_id);
 
state-scissors = SCISSORS_UNSET;
+
+   argv_array_init(state-git_apply_opts);
 }
 
 /**
@@ -142,6 +145,7 @@ static void am_state_release(struct am_state *state)
free(state-author_email);
free(state-author_date);
free(state-msg);
+   argv_array_clear(state-git_apply_opts);
 }
 
 /**
@@ -413,6 +417,11 @@ static void am_load(struct am_state *state)
else
state-scissors = SCISSORS_UNSET;
 
+   read_state_file(sb, state, apply-opt, 1);
+   argv_array_clear(state-git_apply_opts);
+   if (sq_dequote_to_argv_array(sb.buf, state-git_apply_opts)  0)
+   die(_(could not parse %s), am_path(state, apply-opt));
+
state-rebasing = !!file_exists(am_path(state, rebasing));
 
strbuf_release(sb);
@@ -587,6 +596,7 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
 {
unsigned char curr_head[GIT_SHA1_RAWSZ];
const char *str;
+   struct strbuf sb = STRBUF_INIT;
 
if (!patch_format)
patch_format = detect_patch_format(paths);
@@ -649,6 +659,9 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
 
write_file(am_path(state, scissors), 1, %s, str);
 
+   sq_quote_argv(sb, state-git_apply_opts.argv, 0);
+   write_file(am_path(state, apply-opt), 1, %s, sb.buf);
+
if (state-rebasing)
write_file(am_path(state, rebasing), 1, %s, );
else
@@ -673,6 +686,8 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
write_file(am_path(state, next), 1, %d, state-cur);
 
write_file(am_path(state, last), 1, %d, state-last);
+
+   strbuf_release(sb);
 }
 
 /**
@@ -1060,6 +1075,8 @@ static int run_apply(const struct am_state *state, const 
char *index_file)
 
argv_array_push(cp.args, apply);
 
+   argv_array_pushv(cp.args, state-git_apply_opts.argv);
+
if (index_file)
argv_array_push(cp.args, --cached);
else
@@ -1086,6 +1103,7 @@ static int build_fake_ancestor(const struct am_state 
*state, const char *index_f
 
cp.git_cmd = 1;
argv_array_push(cp.args, apply);
+   argv_array_pushv(cp.args, state-git_apply_opts.argv);
argv_array_pushf(cp.args, --build-fake-ancestor=%s, index_file);
argv_array_push(cp.args, am_path(state, patch));
 
@@ -1600,9 +1618,36 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 0},
OPT_BOOL('c', scissors, state.scissors,
N_(strip everything before a scissors line)),
+   OPT_PASSTHRU_ARGV(0, whitespace, state.git_apply_opts, 
N_(action),
+   N_(pass it through git-apply),
+   0),
+   OPT_PASSTHRU_ARGV(0, ignore-space-change, 
state.git_apply_opts, NULL,
+   N_(pass it through git-apply),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU_ARGV(0, ignore-whitespace, 
state.git_apply_opts, NULL,
+   N_(pass it through git-apply),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU_ARGV(0, directory, state.git_apply_opts, 
N_(root),
+   N_(pass it through git-apply),
+   0),
+   OPT_PASSTHRU_ARGV(0, exclude, 

[PATCH v6 30/45] builtin-am: implement --ignore-date

2015-07-19 Thread Paul Tan
Since a79ec62 (git-am: Add --ignore-date option, 2009-01-24), git-am.sh
supported the --ignore-date option, and would use the current timestamp
instead of the one provided in the patch if the option was set.

Re-implement this option in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/builtin/am.c b/builtin/am.c
index 9ff0736..7f068e2 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -108,6 +108,7 @@ struct am_state {
int scissors; /* enum scissors_type */
struct argv_array git_apply_opts;
const char *resolvemsg;
+   int ignore_date;
int rebasing;
 };
 
@@ -1219,7 +1220,8 @@ static void do_commit(const struct am_state *state)
}
 
author = fmt_ident(state-author_name, state-author_email,
-   state-author_date, IDENT_STRICT);
+   state-ignore_date ? NULL : state-author_date,
+   IDENT_STRICT);
 
if (commit_tree(state-msg, state-msg_len, tree, parents, commit,
author, NULL))
@@ -1662,6 +1664,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
OPT_CMDMODE(0, abort, resume,
N_(restore the original branch and abort the patching 
operation.),
RESUME_ABORT),
+   OPT_BOOL(0, ignore-date, state.ignore_date,
+   N_(use current timestamp for author date)),
OPT_HIDDEN_BOOL(0, rebasing, state.rebasing,
N_((internal use for git-rebase))),
OPT_END()
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 02/45] wrapper: implement xfopen()

2015-07-19 Thread Paul Tan
A common usage pattern of fopen() is to check if it succeeded, and die()
if it failed:

FILE *fp = fopen(path, w);
if (!fp)
die_errno(_(could not open '%s' for writing), path);

Implement a wrapper function xfopen() for the above, so that we can save
a few lines of code and make the die() messages consistent.

Helped-by: Jeff King p...@peff.net
Helped-by: Johannes Schindelin johannes.schinde...@gmx.de
Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 git-compat-util.h |  1 +
 wrapper.c | 21 +
 2 files changed, 22 insertions(+)

diff --git a/git-compat-util.h b/git-compat-util.h
index e168dfd..392da79 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -722,6 +722,7 @@ extern ssize_t xread(int fd, void *buf, size_t len);
 extern ssize_t xwrite(int fd, const void *buf, size_t len);
 extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset);
 extern int xdup(int fd);
+extern FILE *xfopen(const char *path, const char *mode);
 extern FILE *xfdopen(int fd, const char *mode);
 extern int xmkstemp(char *template);
 extern int xmkstemp_mode(char *template, int mode);
diff --git a/wrapper.c b/wrapper.c
index 0a4502d..e451463 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -346,6 +346,27 @@ int xdup(int fd)
return ret;
 }
 
+/**
+ * xfopen() is the same as fopen(), but it die()s if the fopen() fails.
+ */
+FILE *xfopen(const char *path, const char *mode)
+{
+   for (;;) {
+   FILE *fp = fopen(path, mode);
+   if (fp)
+   return fp;
+   if (errno == EINTR)
+   continue;
+
+   if (*mode  mode[1] == '+')
+   die_errno(_(could not open '%s' for reading and 
writing), path);
+   else if (*mode == 'w' || *mode == 'a')
+   die_errno(_(could not open '%s' for writing), path);
+   else
+   die_errno(_(could not open '%s' for reading), path);
+   }
+}
+
 FILE *xfdopen(int fd, const char *mode)
 {
FILE *stream = fdopen(fd, mode);
-- 
2.5.0.rc2.110.gb39b692

--
To unsubscribe from this list: send the line 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/3] Fix sed usage in tests to work around broken xpg4/sed on Solaris

2015-07-19 Thread Ben Walton
The space following the last / in a sed command caused Solaris'
xpg4/sed to fail, claiming the program was garbled and exit with
status 2:

% echo 'foo' | /usr/xpg4/bin/sed -e 's/foo/bar/ '
sed: command garbled: s/foo/bar/
% echo $?
2

Fix this by simply removing the unnecessary space.

Signed-off-by: Ben Walton bdwal...@gmail.com
---
 t/t5601-clone.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 8299d14..8b7f8e1 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -445,7 +445,7 @@ test_expect_success 'clone ssh://host.xz:22/~repo' '
 #IPv6
 for tuah in ::1 [::1] [::1]: user@::1 user@[::1] user@[::1]: [user@::1] 
[user@::1]:
 do
-   ehost=$(echo $tuah | sed -e s/1]:/1]/  | tr -d $squarebrackets)
+   ehost=$(echo $tuah | sed -e s/1]:/1]/ | tr -d $squarebrackets)
test_expect_success clone ssh://$tuah/home/user/repo 
  test_clone_url ssh://$tuah/home/user/repo $ehost /home/user/repo

-- 
2.1.4

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


Adapt some tests to work around broken Solaris tools

2015-07-19 Thread Ben Walton
This series is a respin of the previous submission, taking feedback
into account.

--
To unsubscribe from this list: send the line 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/3] Fix sed usage in tests to work around broken xpg4/sed on Solaris

2015-07-19 Thread Ben Walton
In 99094a7a, a trivial  breakage was fixed. This exposed a problem
with the test when run on Solaris with xpg4/sed that had gone silently
undetected since its introduction in e4bd10b2. Solaris' sed executes
the requested substitution but prints a warning about the missing
newline at the end of the file and exits with status 2.

% echo CHANGE_ME | \
tr -d \\012 | /usr/xpg4/bin/sed -e 's/CHANGE_ME/change_me/'
sed: Missing newline at end of file standard input.
change_me
% echo $?
2

To work around this, use perl to perform the substitution instead.

Signed-off-by: Ben Walton bdwal...@gmail.com
---
 t/t9500-gitweb-standalone-no-errors.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t9500-gitweb-standalone-no-errors.sh 
b/t/t9500-gitweb-standalone-no-errors.sh
index e94b2f1..a7383fa 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -290,7 +290,7 @@ test_expect_success 'setup incomplete lines' '
echo incomplete | tr -d \\012 file 
git commit -a -m Add incomplete line 
git tag incomplete_lines_add 
-   sed -e s/CHANGE_ME/change_me/ file file+ 
+   perl -pne s/CHANGE_ME/change_me/ file file+ 
mv -f file+ file 
git commit -a -m Incomplete context line 
git tag incomplete_lines_ctx 
-- 
2.1.4

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


[PATCH 1/3] Modify tr expressions so that xpg4/tr handles it on Solaris

2015-07-19 Thread Ben Walton
It seems that xpg4/tr mishandles some strings involving [ not followed
by a character class:
% echo '[::1]' | /usr/xpg4/bin/tr -d '[]'
[::1

% echo '[::1]' | /usr/xpg4/bin/tr -d '['
usr/xpg4/bin/tr: Bad string.

This was breaking two tests. To fix the issue, use the octal
representations of [ and ] instead. Reference the octal expression as
a newly exported variable so that it's shared across tests and more
easily understood when reading it.

Signed-off-by: Ben Walton bdwal...@gmail.com
---
 t/t5500-fetch-pack.sh | 2 +-
 t/t5601-clone.sh  | 8 
 t/test-lib.sh | 5 -
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 3a9b775..2db9bde 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -547,7 +547,7 @@ check_prot_host_port_path () {
*ssh*)
pp=ssh
uah=userandhost
-   ehost=$(echo $3 | tr -d [])
+   ehost=$(echo $3 | tr -d $squarebrackets)
diagport=Diag: port=$4
;;
*)
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index bfdaf75..8299d14 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -445,7 +445,7 @@ test_expect_success 'clone ssh://host.xz:22/~repo' '
 #IPv6
 for tuah in ::1 [::1] [::1]: user@::1 user@[::1] user@[::1]: [user@::1] 
[user@::1]:
 do
-   ehost=$(echo $tuah | sed -e s/1]:/1]/ | tr -d [])
+   ehost=$(echo $tuah | sed -e s/1]:/1]/  | tr -d $squarebrackets)
test_expect_success clone ssh://$tuah/home/user/repo 
  test_clone_url ssh://$tuah/home/user/repo $ehost /home/user/repo

@@ -454,7 +454,7 @@ done
 #IPv6 from home directory
 for tuah in ::1 [::1] user@::1 user@[::1] [user@::1]
 do
-   euah=$(echo $tuah | tr -d [])
+   euah=$(echo $tuah | tr -d $squarebrackets)
test_expect_success clone ssh://$tuah/~repo 
  test_clone_url ssh://$tuah/~repo $euah '~repo'

@@ -463,7 +463,7 @@ done
 #IPv6 with port number
 for tuah in [::1] user@[::1] [user@::1]
 do
-   euah=$(echo $tuah | tr -d [])
+   euah=$(echo $tuah | tr -d $squarebrackets)
test_expect_success clone ssh://$tuah:22/home/user/repo 
  test_clone_url ssh://$tuah:22/home/user/repo '-p 22' $euah 
/home/user/repo

@@ -472,7 +472,7 @@ done
 #IPv6 from home directory with port number
 for tuah in [::1] user@[::1] [user@::1]
 do
-   euah=$(echo $tuah | tr -d [])
+   euah=$(echo $tuah | tr -d $squarebrackets)
test_expect_success clone ssh://$tuah:22/~repo 
  test_clone_url ssh://$tuah:22/~repo '-p 22' $euah '~repo'

diff --git a/t/test-lib.sh b/t/test-lib.sh
index 39da9c2..6b5b6cd 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -173,7 +173,10 @@ LF='
 # when case-folding filenames
 u200c=$(printf '\342\200\214')
 
-export _x05 _x40 _z40 LF u200c
+# [ and ], for use by tr commands.
+squarebrackets=\133\135
+
+export _x05 _x40 _z40 LF u200c squarebrackets
 
 # Each test should start with something like this, after copyright notices:
 #
-- 
2.1.4

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


Re: [PATCH v2 14/16] vcbuild/readme: Improve layout and reference msvc-build script

2015-07-19 Thread Philip Oakley

From: Philip Oakley philipoak...@iee.org
Sent: Sunday, July 19, 2015 9:08 PM

This 14/16 is the wrong version accidently left over from a previous 
draft.

Please use the other version with the shorter subject line.

Sorry for the noise / mistake.


Layout the 'either/or' with more white space to clarify
which alternatives are matched up.

Reference the Msysgit build script which automates one sequence of 
options.


This part has been dropped.


Signed-off-by: Philip Oakley philipoak...@iee.org
---

[...]

Done!
+
+Or, use the Msysgit msvc-build script; available from that project.

... has gone.


--
2.4.2.windows.1.5.gd32afb6




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


How to use --cc-cmd in git-send-email?

2015-07-19 Thread Philip Oakley
I've been using git-send-email with repeated individual --cc=email 
address parameters on the command line.


I tried putting all the addresses, one per line, into a file 'cc-cmd', 
so I could use if for the --cc-cmd option.


I then tried to use --cc-cmd='cat cc-cmd' to do the send-email (as 
a --dry-run). This produced, as part of the output, a list of the output 
of the cc-cmd, which showed not only the file contents, but this was 
then followed by the full patch, as if it was part of the list of email 
addresses.


Finally, at the end of the inclusion of the patch, I got

(cc-cmd) Adding cc: -- from: 'cat cc-cmd'
(cc-cmd) Adding cc: 2.4.2.windows.1.5.gd32afb6 from: 'cat cc-cmd'
(cc-cmd) Adding cc:  from: 'cat cc-cmd'
error: unable to extract a valid address from:
What to do with this address? ([q]uit|[d]rop|[e]dit):

Could this have been caused by an extra (blank) line at the end of the 
cc-cmd file?


Also, does anyone have an example of a working --cc-cmd option?

(this is on g4w: git version 2.3.1)

Philip 


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


Re: How to use --cc-cmd in git-send-email?

2015-07-19 Thread Eric Sunshine
On Sun, Jul 19, 2015 at 6:02 PM, Philip Oakley philipoak...@iee.org wrote:
 I've been using git-send-email with repeated individual --cc=email address
 parameters on the command line.

 I tried putting all the addresses, one per line, into a file 'cc-cmd', so I
 could use if for the --cc-cmd option.

 I then tried to use --cc-cmd='cat cc-cmd' to do the send-email (as a
 --dry-run). This produced, as part of the output, a list of the output of
 the cc-cmd, which showed not only the file contents, but this was then
 followed by the full patch, as if it was part of the list of email
 addresses.

git-send-email invokes the cc-cmd like this:

$cc-cmd $patchfilename

so, when you used 'cat cc-cmd' as the value of --cc-cmd, your invocation became:

cat cc-cmd $patchfilename

and since 'cat' copies the concatenation of its input files to its
output, that explains why you first saw the names from your 'cc-cmd'
file followed by the content of the patch file.

A quick-and-dirty work-around is to use '#' to effectively comment out
the patch file name:

--cc-cmd='cat cc-cmd #'

which works, but is very, very ugly.

 Could this have been caused by an extra (blank) line at the end of the
 cc-cmd file?

Nope.

 Also, does anyone have an example of a working --cc-cmd option?

A very simple working solution is to make your 'cc-cmd' file executable:

#!/bin/sh
echo \EOF
pers...@example.com
pers...@example.com
EOF
--
To unsubscribe from this list: send the line 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/3] Modify tr expressions so that xpg4/tr handles it on Solaris

2015-07-19 Thread Eric Sunshine
On Sun, Jul 19, 2015 at 2:00 PM, Ben Walton bdwal...@gmail.com wrote:
 It seems that xpg4/tr mishandles some strings involving [ not followed
 by a character class:
 % echo '[::1]' | /usr/xpg4/bin/tr -d '[]'
 [::1

 % echo '[::1]' | /usr/xpg4/bin/tr -d '['
 usr/xpg4/bin/tr: Bad string.

 This was breaking two tests. To fix the issue, use the octal
 representations of [ and ] instead. Reference the octal expression as
 a newly exported variable so that it's shared across tests and more
 easily understood when reading it.

 Signed-off-by: Ben Walton bdwal...@gmail.com
 ---
 diff --git a/t/test-lib.sh b/t/test-lib.sh
 index 39da9c2..6b5b6cd 100644
 --- a/t/test-lib.sh
 +++ b/t/test-lib.sh
 @@ -173,7 +173,10 @@ LF='
  # when case-folding filenames
  u200c=$(printf '\342\200\214')

 -export _x05 _x40 _z40 LF u200c
 +# [ and ], for use by tr commands.
 +squarebrackets=\133\135

While it's true that the reader may be able to consult the commit
message to learn more about squarebrackets and tr, this might be
one of those cases where either a more explanatory in-code comment is
warranted or the comment should be dropped altogether, since the the
current comment is not illuminating. I'd vote for expanding the
comment a bit to mention some versions of Solaris 'tr' and a short
description of the misbehavior.

Also, Hannes wondered how Solaris 'tr' would react to '[][]'. Were you
able to test that or the alternative '[[]]'?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 4/9] ref-filter: add support to sort by version

2015-07-19 Thread Eric Sunshine
On Sat, Jul 18, 2015 at 3:12 PM, Karthik Nayak karthik@gmail.com wrote:
 Add support to sort by version using the v:refname and
 version:refname option. This is achieved by using the
 'version_cmp()' function as the comparing function for qsort.

To agree with the actual code: s/version_cmp/versioncmp/

 This option is included to support sorting by versions in `git tag -l`
 which will eventaully be ported to use ref-filter APIs.

 Add documentation and tests for the same.

 Signed-off-by: Karthik Nayak karthik@gmail.com
 ---
 diff --git a/Documentation/git-for-each-ref.txt 
 b/Documentation/git-for-each-ref.txt
 index e49d578..cc91275 100644
 --- a/Documentation/git-for-each-ref.txt
 +++ b/Documentation/git-for-each-ref.txt
 @@ -144,6 +144,8 @@ blank line.  Finally, the optional GPG signature is 
 `contents:signature`.
  For sorting purposes, fields with numeric values sort in numeric
  order (`objectsize`, `authordate`, `committerdate`, `taggerdate`).
  All other fields are used to sort in their byte-value order.
 +There is also an option to sort by versions, this is done using the
 +field names ('version:refname' or 'v:refname').

Assuming I'm a reader without prior knowledge, the first question
which pops into my mind is what's the difference between
'version:refname' and 'v:refname'? Is one just shorthand for the
other, or is there some subtle difference in behavior, or what? The
documentation should explain this better.

Also, why are there parentheses around 'version:refname' or
'v:refname'? And, you should use backticks rather than apostrophes, as
is done with the other field names.

  In any case, a field name that refers to a field inapplicable to
  the object referred by the ref does not cause an error.  It
 diff --git a/ref-filter.c b/ref-filter.c
 index 82731ac..85c561e 100644
 --- a/ref-filter.c
 +++ b/ref-filter.c
 @@ -1169,18 +1170,22 @@ static int cmp_ref_sorting(struct ref_sorting *s, 
 struct ref_array_item *a, stru

 get_ref_atom_value(a, s-atom, va);
 get_ref_atom_value(b, s-atom, vb);
 -   switch (cmp_type) {
 -   case FIELD_STR:
 -   cmp = strcmp(va-s, vb-s);
 -   break;
 -   default:
 -   if (va-ul  vb-ul)
 -   cmp = -1;
 -   else if (va-ul == vb-ul)
 -   cmp = 0;
 -   else
 -   cmp = 1;
 -   break;
 +   if (s-version)
 +   cmp = versioncmp(va-s, vb-s);
 +   else {
 +   switch (cmp_type) {
 +   case FIELD_STR:
 +   cmp = strcmp(va-s, vb-s);
 +   break;
 +   default:
 +   if (va-ul  vb-ul)
 +   cmp = -1;
 +   else if (va-ul == vb-ul)
 +   cmp = 0;
 +   else
 +   cmp = 1;
 +   break;
 +   }

The logic might be slightly easier to follow, and give a much less
noisy diff if you rewrite it like this instead:

if (s-version)
cmp = versioncmp(va-s, vb-s);
else if (cmp_type == FIELD_STR)
cmp = strcmp(va-s, vb-s);
else {
if (va-ul  vb-ul)
cmp = -1;
else if (va-ul == vb-ul)
cmp = 0;
else
cmp = 1;
}

Or, if you don't mind a noisy diff, you can outdent the other branches, as well:

if (s-version)
   cmp = versioncmp(va-s, vb-s);
else if (cmp_type == FIELD_STR)
   cmp = strcmp(va-s, vb-s);
else if (va-ul  vb-ul)
   cmp = -1;
else if (va-ul == vb-ul)
   cmp = 0;
else
   cmp = 1;

(I rather prefer the latter, despite the noisy diff.)

 }
 return (s-reverse) ? -cmp : cmp;
  }
 diff --git a/ref-filter.h b/ref-filter.h
 index 7dfdea0..6f1646b 100644
 --- a/ref-filter.h
 +++ b/ref-filter.h
 @@ -25,7 +25,7 @@ struct atom_value {
  struct ref_sorting {
 struct ref_sorting *next;
 int atom; /* index into used_atom array (internal) */
 -   unsigned reverse : 1;
 +   unsigned reverse : 1, version : 1;

This is difficult to read. Style elsewhere (if I'm not mistaken) is to
place the declaration on a line by itself.

  };

  struct ref_array_item {
 diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
 index 505a360..c31fd2f 100755
 --- a/t/t6302-for-each-ref-filter.sh
 +++ b/t/t6302-for-each-ref-filter.sh
 @@ -81,4 +81,30 @@ test_expect_success 'filtering with --contains' '
 test_cmp expect actual
  '

 +test_expect_success 'version sort' '
 +   git tag -l --sort=version:refname | grep foo actual 
 +   cat expect -\EOF 
 +   foo1.3
 +   foo1.6
 +   foo1.10
 +   EOF
 +   test_cmp expect actual
 +'
 +
 +test_expect_success 'reverse version sort' '
 +   git tag -l --sort=-version:refname | grep foo actual 

Maybe use 'v:refname' in one of these 

Re: [PATCH v3 1/9] ref-filter: add option to align atoms to the left

2015-07-19 Thread Eric Sunshine
On Sat, Jul 18, 2015 at 3:12 PM, Karthik Nayak karthik@gmail.com wrote:
 Add a new atom align and support %(align:X) where X is a number.
 This will align the preceeding atom value to the left followed by
 spaces for a total length of X characters. If X is less than the item
 size, the entire atom value is printed.

 Signed-off-by: Karthik Nayak karthik@gmail.com
 ---
 diff --git a/ref-filter.c b/ref-filter.c
 index 7561727..b81a08d 100644
 --- a/ref-filter.c
 +++ b/ref-filter.c
 @@ -53,6 +55,7 @@ static struct {
 { flag },
 { HEAD },
 { color },
 +   { align },

Not a new issue, but some compilers (Solaris?) complain about the
trailing comma.

  };

  /*
 @@ -687,6 +690,17 @@ static void populate_value(struct ref_array_item *ref)
 else
 v-s =  ;
 continue;
 +   } else if (starts_with(name, align:)) {
 +   const char *valp = NULL;
 +
 +   skip_prefix(name, align:, valp);
 +   if (!valp[0])
 +   die(_(No value given with 'align='));

The parser expects align:, but the error message talks about
align=. Also, current trend is to drop capitalization from the error
message.

 +   strtoul_ui(valp, 10, ref-align_value);
 +   if (ref-align_value  1)
 +   die(_(Value should be greater than zero));

Drop capitalization. Also, the user seeing this message won't
necessarily know to which value this refers. Better would be to
provide context ('align:' value should be...), and even better would
be to show the actual value at fault:

die(_(value should be greater than zero: align:%u\n,
ref_align_value);

or something.

 +   v-s = ;
 +   continue;
 } else
 continue;

 @@ -1254,17 +1268,38 @@ static void emit(const char *cp, const char *ep)
 }
  }

 +static void assign_formating(struct ref_array_item *ref, int parsed_atom, 
 struct atom_value *v)
 +{
 +   if (v-s[0]  ref-align_value) {

Mental note: v-s[0] is not NUL ('\0').

Also, in this code base, this is typically written *v-s rather than v-s[0].

 +   unsigned int len = 0;
 +   len = utf8_strwidth(v-s);

You initialize 'len' to 0 but then immediately re-assign it.

 +   if (ref-align_value  len) {
 +   struct strbuf buf = STRBUF_INIT;
 +   strbuf_addstr(buf, v-s);
 +   if (!v-s[0])
 +   free((char *)v-s);

We know from the mental note above that v-s[0] is not NUL ('\0'),
so this 'if' statement can never be true, thus is dead code.

 +   strbuf_addchars(buf, ' ', ref-align_value - len);
 +   v-s = strbuf_detach(buf, NULL);
 +   }
 +   ref-align_value = 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 v3 3/9] ref-filter: support printing N lines from tag annotation

2015-07-19 Thread Eric Sunshine
On Sat, Jul 18, 2015 at 3:12 PM, Karthik Nayak karthik@gmail.com wrote:
 In 'tag.c' we can print N lines from the annotation of the tag using
 the '-nnum' option. Copy code from 'tag.c' to 'ref-filter' and
 modify 'ref-filter' to support printing of N lines from the annotation
 of tags.

 Signed-off-by: Karthik Nayak karthik@gmail.com
 ---
 diff --git a/ref-filter.c b/ref-filter.c
 index 771c48d..82731ac 100644
 --- a/ref-filter.c
 +++ b/ref-filter.c
 @@ -1288,7 +1288,48 @@ static void assign_formating(struct ref_array_item 
 *ref, int parsed_atom, struct
 }
  }

 -void show_ref_array_item(struct ref_array_item *info, const char *format, 
 int quote_style)
 +/* Print 'lines' no of lines of a given oid */

This is difficult to read and understand. I presume you meant no. as
shorthand for number but dropped the period. Even with the period,
it's still hard to read. Perhaps rewrite it as:

If 'lines' is greater than 0, print that may lines of...

or something.

 diff --git a/ref-filter.h b/ref-filter.h
 index c18781b..7dfdea0 100644
 --- a/ref-filter.h
 +++ b/ref-filter.h
 @@ -87,8 +88,11 @@ int parse_ref_filter_atom(const char *atom, const char 
 *ep);
  int verify_ref_format(const char *format);
  /*  Sort the given ref_array as per the ref_sorting provided */
  void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);
 -/*  Print the ref using the given format and quote_style */
 -void show_ref_array_item(struct ref_array_item *info, const char *format, 
 int quote_style);
 +/*
 + * Print the ref using the given format and quote_style. If lines  0,
 + * prints the lines no of lines of the objected pointed to.
 + */

Same problem. This literal no is quite confusing. Perhaps rewrite as above:

If lines  0, print that many lines of...

 +void show_ref_array_item(struct ref_array_item *info, const char *format, 
 int quote_style, unsigned int lines);

ref-filter.h seems to be setting a precedent for overlong lines.
Wrapping this manually could improve readability.

  /*  Callback function for parsing the sort option */
  int parse_opt_ref_sorting(const struct option *opt, const char *arg, int 
 unset);
  /*  Default sort option based on refname */
 --
 2.4.6
--
To unsubscribe from this list: send the line 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: [msysGit] [PATCH v2 08/16] engine.pl: ignore invalidcontinue.obj which is known to MSVC

2015-07-19 Thread Eric Sunshine
On Sun, Jul 19, 2015 at 4:08 PM, Philip Oakley philipoak...@iee.org wrote:
 Commit 4b623d8 (MSVC: link in invalidcontinue.obj for better
 POSIX compatibility, 2014-03-29) is not processed correctly
 by the buildsystem. Ignore it.

What does not processed correctly mean? For a person reading the
commit message, but lacking your experience with this, not processed
correctly seems akin to it doesn't work[1]. Can the commit message
provide a bit more detail?

[1]: http://www.chiark.greenend.org.uk/~sgtatham/bugs.html

 Also split the .o and .obj processing; 'make' does not produce .obj
 files. Only substitute filenames ending with .o when generating the
 source .c filename.

 Signed-off-by: Philip Oakley philipoak...@iee.org
 ---
  contrib/buildsystems/engine.pl | 10 +++---
  1 file changed, 7 insertions(+), 3 deletions(-)

 diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
 index 60c7a7d..9db3d43 100755
 --- a/contrib/buildsystems/engine.pl
 +++ b/contrib/buildsystems/engine.pl
 @@ -289,7 +289,7 @@ sub handleLibLine
  #exit(1);
  foreach (@objfiles) {
  my $sourcefile = $_;
 -$sourcefile =~ s/\.o/.c/;
 +$sourcefile =~ s/\.o$/.c/;
  push(@sources, $sourcefile);
  push(@cflags, @{$compile_options{${sourcefile}_CFLAGS}});
  push(@defines, @{$compile_options{${sourcefile}_DEFINES}});
 @@ -333,8 +333,12 @@ sub handleLinkLine
  } elsif ($part =~ /\.(a|lib)$/) {
  $part =~ s/\.a$/.lib/;
  push(@libs, $part);
 -} elsif ($part =~ /\.(o|obj)$/) {
 +} elsif ($part eq 'invalidcontinue.obj') {
 +# ignore - known to MSVC
 +} elsif ($part =~ /\.o$/) {
  push(@objfiles, $part);
 +} elsif ($part =~ /\.obj$/) {
 +# do nothing, 'make' should not be producing .obj, only .o files
  } else {
  die Unhandled link option @ line $lineno: $part;
  }
 @@ -343,7 +347,7 @@ sub handleLinkLine
  #exit(1);
  foreach (@objfiles) {
  my $sourcefile = $_;
 -$sourcefile =~ s/\.o/.c/;
 +$sourcefile =~ s/\.o$/.c/;
  push(@sources, $sourcefile);
  push(@cflags, @{$compile_options{${sourcefile}_CFLAGS}});
  push(@defines, @{$compile_options{${sourcefile}_DEFINES}});
 --
 2.4.2.windows.1.5.gd32afb6
--
To unsubscribe from this list: send the line 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: pre-receive hook issue

2015-07-19 Thread Jacob Keller
To check whether the ref being updated is a tag, you need to check the
3rd parameter. pre-receive receives in the format

old-value new-value ref-name

so you need to check each line's 3rd value which is the ref-name being
updated. If it's in refs/tags then it's a tag update. If it's not, you
can check it as a branch update.

Then you should check all new commits for each branch, as Julio mentioned above.

Checking whether each commit has an associated tag is probably not
what you meant.

Regards,
Jake

On Sun, Jul 19, 2015 at 3:13 AM, Gaurav Chhabra
varuag.chha...@gmail.com wrote:
 The only thing we wanted to check was whether a ref is a tag. :) Rest
 other things are working fine (except for the commits=$new_sha1
 thing which Junio already pointed out and corrected). I will correct
 the pre-receive hook.

 The only mystery that remains is about the current nonsensical code
 working fine in the past for few annotated tag pushes. It shouldn't
 have worked just by providing:

 RW+ refs/tags=developer_name

 Ref: http://gitolite.com/gitolite/g2/aac.html (Section: deny rules
 for refs in a repo)


 On Sun, Jul 19, 2015 at 2:09 PM, Jacob Keller [via git]
 ml-node+s661346n7635875...@n2.nabble.com wrote:
 On Sun, Jul 19, 2015 at 12:55 AM, Gaurav Chhabra
 [hidden email] wrote:
 @Junio: So from your detailed explanation (and Jake's comment), i
 understand that since my ref wasn't updated on remote so querying the
 same using git describe resulted in failure, and hence, code was not
 entering the IF block. Correct?


 I assume so.

 Also, while i was reading your replies, i was just thinking that the
 following question that i asked Jake doesn't really make sense because
 a commit object _is_ being passed (on local machine) to git
 describe, which is what it expects so it should work for sure:


 It works yes. Git describe finds the nearest tag. --exact-match fails
 unless it can find a tag at the commit specified.

 If i got the above right, then shouldn't Git throw an error even on
 my local machine when i'm running git describe --exact-match
 ac28ca721e67a?


 only if ac28ca721e67a does not have an annotated tag associated to it



 @Junio: You wrote: The part that I find questionable is that by
 checking with is this commit a tagged one? and doing different
 things. What makes the initial and the third special to deserve
 checking (because they are not annotated with a tag) while skipping
 the validation for the second (merely because it has an annotated tag
 added to it)?
 Isn't the code that i shared doing just the opposite of what you've
 written? It's checking for annotated tags only and skipping the lightweight
 ones (although it shouldn't be doing all such things in the first place).
 Was it a typo on your part?



 I'm not sure what the code you have is trying to do. See below.

 @Jake: For the question you asked: It would help a lot if we
 understood exactly what you are trying to accomplish.
 I'm not sure how my colleague zeroed in on this git describe command
 but i at least know what we observed (and 'seemed' to work).  We saw that 
 if
 we use git-describe and pass a commit object, it throws fatal error 
 message.
 On the other hand, if we pass a tag object, it doesn't throw any fatal
 error. That's the reason he added that tag check portion.


 Hmmm


 @Junio/Jake: After going through all the responses that i've received
 so far on this forum, i'm thinking how this nonsense code worked for
 few cases in the past? When this check was put in place, devs were
 getting error while pushing annotated tags. Since we use Gitolite, we
 added the following to gitolite.conf and the tag push worked for them:

 RW+ refs/tags=developer_name


 Sounds like you needed to add RW permissions to the refs/tags namespace.

 I'm wondering why.


 Ok, so normally, pre-receive hook is used to implement policy. Ie:
 prevent acceptance of pushes that have bad content as defined by the
 repository owner. For example, preventing push of tags that don't
 match some format, or preventing pushes which contain bad stuff.

 I could provide some examples or suggestions if you would describe
 what sort of policy you're trying to enforce..

 git describe will tell you if the commit you're passing it is
 associated with an annotated tag. I do not understand who this
 information can help you implement any policy, so understanding what
 the policy you want is would be the most helpful.

 I can't really help more or understand exactly what you were doing
 without understanding what policy you were/are trying to implement.

 The thing your code is doing today is something like:

 for each reference update, locate every commit

 for each commit in this reference update, check to see if it already
 has an associated tag connected to it.

 If it doesn't have a tag, then do some more checks which are not
 described here.

 This doesn't make sense to me at all. I think what you *meant* was this:

 for each reference update, if the 

Re: [msysGit] [PATCH v2 10/16] engine.pl: delete the captured stderr file if empty

2015-07-19 Thread Eric Sunshine
On Sun, Jul 19, 2015 at 4:08 PM, Philip Oakley philipoak...@iee.org wrote:
 Keep the build clean of extraneous files if it is indeed clean.
 Otherwise leave the msvc-build-makedryerrors.txt file both as
 a flag for any CI system or for manual debugging.

 Note that the file will contain the new values of the GIT_VERSION
 and GITGUI_VERSION if they were generated by the make file. They
 are omitted if the release is tagged and indentically defined in
 their respective GIT_VERSION_GEN file DEF_VER variables.

 Signed-off-by: Philip Oakley philipoak...@iee.org
 ---
 diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
 index a6999b6..020776e 100755
 --- a/contrib/buildsystems/engine.pl
 +++ b/contrib/buildsystems/engine.pl
 @@ -77,6 +77,8 @@ EOM

  my $ErrsFile = msvc-build-makedryerrors.txt;
  @makedry = `cd $git_dir  make -n MSVC=1 V=1 2$ErrsFile` if !@makedry;
 +# test for an empty Errors file and remove it
 +for ($ErrsFile) {unlink $_ if (-f $_)  (!-s $_);}

Why the 'for' loop?

Also, if you're using the 'for' loop for the $_ side-effect, then why
not the simpler:

for ($ErrsFile) { unlink if -f  !-s; }

?


  # Parse the make output into usable info
  parseMakeOutput();
 --
 2.4.2.windows.1.5.gd32afb6
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 36/45] builtin-am: invoke pre-applypatch hook

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sg will invoke the pre-applypatch hook after applying the patch
to the index, but before a commit is made. Should the hook exit with a
non-zero status, git am will exit.

Re-implement this in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 764e955..fdba3b0 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1336,6 +1336,9 @@ static void do_commit(const struct am_state *state)
const char *reflog_msg, *author;
struct strbuf sb = STRBUF_INIT;
 
+   if (run_hook_le(NULL, pre-applypatch, NULL))
+   exit(1);
+
if (write_cache_as_tree(tree, 0, NULL))
die(_(git write-tree failed to write a tree));
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 42/45] builtin-am: implement -i/--interactive

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sh supported the --interactive mode. After parsing the patch mail
and extracting the patch, commit message and authorship info, an
interactive session will begin that allows the user to choose between:

* applying the patch

* applying the patch and all subsequent patches (by disabling
  interactive mode in subsequent patches)

* skipping the patch

* editing the commit message

Since f89ad67 (Add [v]iew patch in git-am interactive., 2005-10-25),
git-am.sh --interactive also supported viewing the patch to be applied.

When --resolved-ing in --interactive mode, we need to take care to
update the patch with the contents of the index, such that the correct
patch will be displayed when the patch is viewed in interactive mode.

Re-implement the above in builtin/am.c

Signed-off-by: Paul Tan pyoka...@gmail.com
---

Notes:
Can't be tested because even with test_terminal isatty(0) still returns
false.

 builtin/am.c | 105 ++-
 1 file changed, 104 insertions(+), 1 deletion(-)

diff --git a/builtin/am.c b/builtin/am.c
index 8fe616e..39ea3c7 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -25,6 +25,7 @@
 #include log-tree.h
 #include notes-utils.h
 #include rerere.h
+#include prompt.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -119,6 +120,7 @@ struct am_state {
int prec;
 
/* various operating modes and command line options */
+   int interactive;
int threeway;
int quiet;
int append_signoff;
@@ -1173,7 +1175,7 @@ static void NORETURN die_user_resolve(const struct 
am_state *state)
if (state-resolvemsg) {
printf_ln(%s, state-resolvemsg);
} else {
-   const char *cmdline = git am;
+   const char *cmdline = state-interactive ? git am -i : git 
am;
 
printf_ln(_(When you have resolved this problem, run \%s 
--continue\.), cmdline);
printf_ln(_(If you prefer to skip this patch, run \%s 
--skip\ instead.), cmdline);
@@ -1406,6 +1408,36 @@ static void write_commit_patch(const struct am_state 
*state, struct commit *comm
 }
 
 /**
+ * Writes the diff of the index against HEAD as a patch to the state
+ * directory's patch file.
+ */
+static void write_index_patch(const struct am_state *state)
+{
+   struct tree *tree;
+   unsigned char head[GIT_SHA1_RAWSZ];
+   struct rev_info rev_info;
+   FILE *fp;
+
+   if (!get_sha1_tree(HEAD, head))
+   tree = lookup_tree(head);
+   else
+   tree = lookup_tree(EMPTY_TREE_SHA1_BIN);
+
+   fp = xfopen(am_path(state, patch), w);
+   init_revisions(rev_info, NULL);
+   rev_info.diff = 1;
+   rev_info.disable_stdin = 1;
+   rev_info.no_commit_id = 1;
+   rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
+   rev_info.diffopt.use_color = 0;
+   rev_info.diffopt.file = fp;
+   rev_info.diffopt.close_file = 1;
+   add_pending_object(rev_info, tree-object, );
+   diff_setup_done(rev_info.diffopt);
+   run_diff_index(rev_info, 1);
+}
+
+/**
  * Like parse_mail(), but parses the mail by looking up its commit ID
  * directly. This is used in --rebasing mode to bypass git-mailinfo's munging
  * of patches.
@@ -1657,6 +1689,65 @@ static void validate_resume_state(const struct am_state 
*state)
 }
 
 /**
+ * Interactively prompt the user on whether the current patch should be
+ * applied.
+ *
+ * Returns 0 if the user chooses to apply the patch, 1 if the user chooses to
+ * skip it.
+ */
+static int do_interactive(struct am_state *state)
+{
+   assert(state-msg);
+
+   if (!isatty(0))
+   die(_(cannot be interactive without stdin connected to a 
terminal.));
+
+   for (;;) {
+   const char *reply;
+
+   puts(_(Commit Body is:));
+   puts(--);
+   printf(%s, state-msg);
+   puts(--);
+
+   /*
+* TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
+* in your translation. The program will only accept English
+* input at this point.
+*/
+   reply = git_prompt(_(Apply? [y]es/[n]o/[e]dit/[v]iew 
patch/[a]ccept all: ), PROMPT_ECHO);
+
+   if (!reply) {
+   continue;
+   } else if (*reply == 'y' || *reply == 'Y') {
+   return 0;
+   } else if (*reply == 'a' || *reply == 'A') {
+   state-interactive = 0;
+   return 0;
+   } else if (*reply == 'n' || *reply == 'N') {
+   return 1;
+   } else if (*reply == 'e' || *reply == 'E') {
+   struct strbuf msg = STRBUF_INIT;
+
+   if 

[PATCH v6 37/45] builtin-am: invoke post-applypatch hook

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sh will invoke the post-applypatch hook after the patch is
applied and a commit is made. The exit code of the hook is ignored.

Re-implement this in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index fdba3b0..638b6d3 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1380,6 +1380,8 @@ static void do_commit(const struct am_state *state)
fclose(fp);
}
 
+   run_hook_le(NULL, post-applypatch, NULL);
+
strbuf_release(sb);
 }
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 31/45] builtin-am: implement --committer-date-is-author-date

2015-07-19 Thread Paul Tan
Since 3f01ad6 (am: Add --committer-date-is-author-date option,
2009-01-22), git-am.sh implemented the --committer-date-is-author-date
option, which tells git-am to use the timestamp recorded in the email
message as both author and committer date.

Re-implement this option in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 7f068e2..1080df6 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -108,6 +108,7 @@ struct am_state {
int scissors; /* enum scissors_type */
struct argv_array git_apply_opts;
const char *resolvemsg;
+   int committer_date_is_author_date;
int ignore_date;
int rebasing;
 };
@@ -1223,6 +1224,10 @@ static void do_commit(const struct am_state *state)
state-ignore_date ? NULL : state-author_date,
IDENT_STRICT);
 
+   if (state-committer_date_is_author_date)
+   setenv(GIT_COMMITTER_DATE,
+   state-ignore_date ?  : state-author_date, 1);
+
if (commit_tree(state-msg, state-msg_len, tree, parents, commit,
author, NULL))
die(_(failed to write commit object));
@@ -1664,6 +1669,9 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
OPT_CMDMODE(0, abort, resume,
N_(restore the original branch and abort the patching 
operation.),
RESUME_ABORT),
+   OPT_BOOL(0, committer-date-is-author-date,
+   state.committer_date_is_author_date,
+   N_(lie about committer date)),
OPT_BOOL(0, ignore-date, state.ignore_date,
N_(use current timestamp for author date)),
OPT_HIDDEN_BOOL(0, rebasing, state.rebasing,
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 35/45] builtin-am: invoke applypatch-msg hook

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sh will invoke the applypatch-msg hooks just after extracting the
patch message. If the applypatch-msg hook exits with a non-zero status,
git-am.sh abort before even applying the patch to the index.

Re-implement this in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 64b467f..764e955 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -458,6 +458,27 @@ static void am_destroy(const struct am_state *state)
 }
 
 /**
+ * Runs applypatch-msg hook. Returns its exit code.
+ */
+static int run_applypatch_msg_hook(struct am_state *state)
+{
+   int ret;
+
+   assert(state-msg);
+   ret = run_hook_le(NULL, applypatch-msg, am_path(state, 
final-commit), NULL);
+
+   if (!ret) {
+   free(state-msg);
+   state-msg = NULL;
+   if (read_commit_msg(state)  0)
+   die(_('%s' was deleted by the applypatch-msg hook),
+   am_path(state, final-commit));
+   }
+
+   return ret;
+}
+
+/**
  * Runs post-rewrite hook. Returns it exit code.
  */
 static int run_post_rewrite_hook(const struct am_state *state)
@@ -1422,6 +1443,9 @@ static void am_run(struct am_state *state, int resume)
write_commit_msg(state);
}
 
+   if (run_applypatch_msg_hook(state))
+   exit(1);
+
say(state, stdout, _(Applying: %.*s), linelen(state-msg), 
state-msg);
 
apply_status = run_apply(state, NULL);
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 23/45] builtin-am: handle stray state directory

2015-07-19 Thread Paul Tan
Should git-am terminate unexpectedly between the point where the state
directory is created, but the next and last files are not written
yet, a stray state directory will be left behind.

As such, since b141f3c (am: handle stray $dotest directory, 2013-06-15),
git-am.sh explicitly recognizes such a stray directory, and allows the
user to remove it with am --abort.

Re-implement this feature in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 01f01bf..398debf 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1531,6 +1531,23 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
struct argv_array paths = ARGV_ARRAY_INIT;
int i;
 
+   /*
+* Handle stray state directory in the independent-run case. In
+* the --rebasing case, it is up to the caller to take care of
+* stray directories.
+*/
+   if (file_exists(state.dir)  !state.rebasing) {
+   if (resume == RESUME_ABORT) {
+   am_destroy(state);
+   am_state_release(state);
+   return 0;
+   }
+
+   die(_(Stray %s directory found.\n
+   Use \git am --abort\ to remove it.),
+   state.dir);
+   }
+
if (resume)
die(_(Resolve operation not in progress, we are not 
resuming.));
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 43/45] builtin-am: implement legacy -b/--binary option

2015-07-19 Thread Paul Tan
The -b/--binary option was initially implemented in 087b674 (git-am:
--binary; document --resume and --binary., 2005-11-16). The option will
pass the --binary flag to git-apply to allow it to apply binary patches.

However, in 2b6eef9 (Make apply --binary a no-op., 2006-09-06), --binary
was been made a no-op in git-apply. Following that, since cb3a160
(git-am: ignore --binary option, 2008-08-09), the --binary option in
git-am is ignored as well.

In 6c15a1c (am: officially deprecate -b/--binary option, 2012-03-13),
the --binary option was tweaked to its present behavior: when set, the
message:

The -b/--binary option has been a no-op for long time, and it
will be removed. Please do not use it anymore.

will be printed.

Re-implement this in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 39ea3c7..6a2b887 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -2127,6 +2127,7 @@ enum resume_mode {
 int cmd_am(int argc, const char **argv, const char *prefix)
 {
struct am_state state;
+   int binary = -1;
int keep_cr = -1;
int patch_format = PATCH_FORMAT_UNKNOWN;
enum resume_mode resume = RESUME_FALSE;
@@ -2140,6 +2141,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
struct option options[] = {
OPT_BOOL('i', interactive, state.interactive,
N_(run interactively)),
+   OPT_HIDDEN_BOOL('b', binary, binary,
+   N_((historical option -- no-op)),
OPT_BOOL('3', 3way, state.threeway,
N_(allow fall back on 3way merging if needed)),
OPT__QUIET(state.quiet, N_(be quiet)),
@@ -2240,6 +2243,10 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
 
argc = parse_options(argc, argv, prefix, options, usage, 0);
 
+   if (binary = 0)
+   fprintf_ln(stderr, _(The -b/--binary option has been a no-op 
for long time, and\n
+   it will be removed. Please do not use it 
anymore.));
+
if (read_index_preload(the_index, NULL)  0)
die(_(failed to read the index));
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 41/45] builtin-am: support and auto-detect mercurial patches

2015-07-19 Thread Paul Tan
Since 0cfd112 (am: preliminary support for hg patches, 2011-08-29),
git-am.sh could convert mercurial patches to an RFC2822 mail patch
suitable for parsing with git-mailinfo, and queue them in the state
directory for application.

Since 15ced75 (git-am foreign patch support: autodetect some patch
formats, 2009-05-27), git-am.sh was able to auto-detect mercurial
patches by checking if the file begins with the line:

# HG changeset patch

Re-implement the above in builtin/am.c.

Helped-by: Stefan Beller sbel...@google.com
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 74 +++-
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/builtin/am.c b/builtin/am.c
index 01f8a53..8fe616e 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -81,7 +81,8 @@ enum patch_format {
PATCH_FORMAT_UNKNOWN = 0,
PATCH_FORMAT_MBOX,
PATCH_FORMAT_STGIT,
-   PATCH_FORMAT_STGIT_SERIES
+   PATCH_FORMAT_STGIT_SERIES,
+   PATCH_FORMAT_HG
 };
 
 enum keep_type {
@@ -658,6 +659,11 @@ static int detect_patch_format(const char **paths)
goto done;
}
 
+   if (!strcmp(l1.buf, # HG changeset patch)) {
+   ret = PATCH_FORMAT_HG;
+   goto done;
+   }
+
strbuf_reset(l2);
strbuf_getline_crlf(l2, fp);
strbuf_reset(l3);
@@ -856,6 +862,68 @@ static int split_mail_stgit_series(struct am_state *state, 
const char **paths,
 }
 
 /**
+ * A split_patches_conv() callback that converts a mercurial patch to a RFC2822
+ * message suitable for parsing with git-mailinfo.
+ */
+static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
+{
+   struct strbuf sb = STRBUF_INIT;
+
+   while (!strbuf_getline(sb, in, '\n')) {
+   const char *str;
+
+   if (skip_prefix(sb.buf, # User , str))
+   fprintf(out, From: %s\n, str);
+   else if (skip_prefix(sb.buf, # Date , str)) {
+   unsigned long timestamp;
+   long tz, tz2;
+   char *end;
+
+   errno = 0;
+   timestamp = strtoul(str, end, 10);
+   if (errno)
+   return error(_(invalid timestamp));
+
+   if (!skip_prefix(end,  , str))
+   return error(_(invalid Date line));
+
+   errno = 0;
+   tz = strtol(str, end, 10);
+   if (errno)
+   return error(_(invalid timezone offset));
+
+   if (*end)
+   return error(_(invalid Date line));
+
+   /*
+* mercurial's timezone is in seconds west of UTC,
+* however git's timezone is in hours + minutes east of
+* UTC. Convert it.
+*/
+   tz2 = labs(tz) / 3600 * 100 + labs(tz) % 3600 / 60;
+   if (tz  0)
+   tz2 = -tz2;
+
+   fprintf(out, Date: %s\n, show_date(timestamp, tz2, 
DATE_RFC2822));
+   } else if (starts_with(sb.buf, # )) {
+   continue;
+   } else {
+   fprintf(out, \n%s\n, sb.buf);
+   break;
+   }
+   }
+
+   strbuf_reset(sb);
+   while (strbuf_fread(sb, 8192, in)  0) {
+   fwrite(sb.buf, 1, sb.len, out);
+   strbuf_reset(sb);
+   }
+
+   strbuf_release(sb);
+   return 0;
+}
+
+/**
  * Splits a list of files/directories into individual email patches. Each path
  * in `paths` must be a file/directory that is formatted according to
  * `patch_format`.
@@ -887,6 +955,8 @@ static int split_mail(struct am_state *state, enum 
patch_format patch_format,
return split_mail_conv(stgit_patch_to_mail, state, paths, 
keep_cr);
case PATCH_FORMAT_STGIT_SERIES:
return split_mail_stgit_series(state, paths, keep_cr);
+   case PATCH_FORMAT_HG:
+   return split_mail_conv(hg_patch_to_mail, state, paths, keep_cr);
default:
die(BUG: invalid patch_format);
}
@@ -1938,6 +2008,8 @@ static int parse_opt_patchformat(const struct option 
*opt, const char *arg, int
*opt_value = PATCH_FORMAT_STGIT;
else if (!strcmp(arg, stgit-series))
*opt_value = PATCH_FORMAT_STGIT_SERIES;
+   else if (!strcmp(arg, hg))
+   *opt_value = PATCH_FORMAT_HG;
else
return error(_(Invalid value for --patch-format: %s), arg);
return 0;
-- 
2.5.0.rc2.110.gb39b692

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

[PATCH v6 38/45] builtin-am: rerere support

2015-07-19 Thread Paul Tan
git-am.sh will call git-rerere at the following events:

* git rerere when a three-way merge fails to record the conflicted
  automerge results. Since 8389b52 (git-rerere: reuse recorded resolve.,
  2006-01-28)

  * Since cb6020b (Teach --[no-]rerere-autoupdate option to merge,
revert and friends, 2009-12-04), git-am.sh supports the
--[no-]rerere-autoupdate option as well, and would pass it to
git-rerere.

* git rerere when --resolved, to record the hand resolution. Since
  f131dd4 (rerere: record (or avoid misrecording) resolved, skipped or
  aborted rebase/am, 2006-12-08)

* git rerere clear when --skip-ing. Since f131dd4 (rerere: record (or
  avoid misrecording) resolved, skipped or aborted rebase/am,
  2006-12-08)

* git rerere clear when --abort-ing. Since 3e5057a (git am --abort,
  2008-07-16)

Re-implement the above in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 638b6d3..89613e0 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -24,6 +24,7 @@
 #include revision.h
 #include log-tree.h
 #include notes-utils.h
+#include rerere.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -114,6 +115,7 @@ struct am_state {
const char *resolvemsg;
int committer_date_is_author_date;
int ignore_date;
+   int allow_rerere_autoupdate;
const char *sign_commit;
int rebasing;
 };
@@ -1314,6 +1316,7 @@ static int fall_back_threeway(const struct am_state 
*state, const char *index_pa
o.verbosity = 0;
 
if (merge_recursive_generic(o, our_tree, his_tree, 1, bases, result)) 
{
+   rerere(state-allow_rerere_autoupdate);
free(his_tree_name);
return error(_(Failed to merge in the changes.));
}
@@ -1533,6 +1536,8 @@ static void am_resolve(struct am_state *state)
die_user_resolve(state);
}
 
+   rerere(0);
+
do_commit(state);
 
am_next(state);
@@ -1633,12 +1638,29 @@ static int clean_index(const unsigned char *head, const 
unsigned char *remote)
 }
 
 /**
+ * Resets rerere's merge resolution metadata.
+ */
+static void am_rerere_clear(void)
+{
+   struct string_list merge_rr = STRING_LIST_INIT_DUP;
+   int fd = setup_rerere(merge_rr, 0);
+
+   if (fd  0)
+   return;
+
+   rerere_clear(merge_rr);
+   string_list_clear(merge_rr, 1);
+}
+
+/**
  * Resume the current am session by skipping the current patch.
  */
 static void am_skip(struct am_state *state)
 {
unsigned char head[GIT_SHA1_RAWSZ];
 
+   am_rerere_clear();
+
if (get_sha1(HEAD, head))
hashcpy(head, EMPTY_TREE_SHA1_BIN);
 
@@ -1696,6 +1718,8 @@ static void am_abort(struct am_state *state)
return;
}
 
+   am_rerere_clear();
+
curr_branch = resolve_refdup(HEAD, 0, curr_head, NULL);
has_curr_head = !is_null_sha1(curr_head);
if (!has_curr_head)
@@ -1824,6 +1848,7 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
N_(lie about committer date)),
OPT_BOOL(0, ignore-date, state.ignore_date,
N_(use current timestamp for author date)),
+   OPT_RERERE_AUTOUPDATE(state.allow_rerere_autoupdate),
{ OPTION_STRING, 'S', gpg-sign, state.sign_commit, 
N_(key-id),
  N_(GPG-sign commits),
  PARSE_OPT_OPTARG, NULL, (intptr_t)  },
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 34/45] builtin-am: support automatic notes copying

2015-07-19 Thread Paul Tan
Since eb2151b (rebase: support automatic notes copying, 2010-03-12),
git-am.sh supported automatic notes copying in --rebasing mode by
invoking git notes copy once it has finished applying all the patches.

Re-implement this feature in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 60 
 1 file changed, 60 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index e99e1ec..64b467f 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -23,6 +23,7 @@
 #include merge-recursive.h
 #include revision.h
 #include log-tree.h
+#include notes-utils.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -481,6 +482,64 @@ static int run_post_rewrite_hook(const struct am_state 
*state)
 }
 
 /**
+ * Reads the state directory's rewritten file, and copies notes from the old
+ * commits listed in the file to their rewritten commits.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int copy_notes_for_rebase(const struct am_state *state)
+{
+   struct notes_rewrite_cfg *c;
+   struct strbuf sb = STRBUF_INIT;
+   const char *invalid_line = _(Malformed input line: '%s'.);
+   const char *msg = Notes added by 'git rebase';
+   FILE *fp;
+   int ret = 0;
+
+   assert(state-rebasing);
+
+   c = init_copy_notes_for_rewrite(rebase);
+   if (!c)
+   return 0;
+
+   fp = xfopen(am_path(state, rewritten), r);
+
+   while (!strbuf_getline(sb, fp, '\n')) {
+   unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ];
+
+   if (sb.len != GIT_SHA1_HEXSZ * 2 + 1) {
+   ret = error(invalid_line, sb.buf);
+   goto finish;
+   }
+
+   if (get_sha1_hex(sb.buf, from_obj)) {
+   ret = error(invalid_line, sb.buf);
+   goto finish;
+   }
+
+   if (sb.buf[GIT_SHA1_HEXSZ] != ' ') {
+   ret = error(invalid_line, sb.buf);
+   goto finish;
+   }
+
+   if (get_sha1_hex(sb.buf + GIT_SHA1_HEXSZ + 1, to_obj)) {
+   ret = error(invalid_line, sb.buf);
+   goto finish;
+   }
+
+   if (copy_note_for_rewrite(c, from_obj, to_obj))
+   ret = error(_(Failed to copy notes from '%s' to '%s'),
+   sha1_to_hex(from_obj), 
sha1_to_hex(to_obj));
+   }
+
+finish:
+   finish_copy_notes_for_rewrite(c, msg);
+   fclose(fp);
+   strbuf_release(sb);
+   return ret;
+}
+
+/**
  * Determines if the file looks like a piece of RFC2822 mail by grabbing all
  * non-indented lines and checking if they look like they begin with valid
  * header field names.
@@ -1407,6 +1466,7 @@ next:
 
if (!is_empty_file(am_path(state, rewritten))) {
assert(state-rebasing);
+   copy_notes_for_rebase(state);
run_post_rewrite_hook(state);
}
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 19/45] cache-tree: introduce write_index_as_tree()

2015-07-19 Thread Paul Tan
A caller may wish to write a temporary index as a tree. However,
write_cache_as_tree() assumes that the index was read from, and will
write to, the default index file path. Introduce write_index_as_tree()
which removes this limitation by allowing the caller to specify its own
index_state and index file path.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 cache-tree.c | 29 +
 cache-tree.h |  1 +
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/cache-tree.c b/cache-tree.c
index 32772b9..feace8b 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -592,7 +592,7 @@ static struct cache_tree *cache_tree_find(struct cache_tree 
*it, const char *pat
return it;
 }
 
-int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
+int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, 
const char *index_path, int flags, const char *prefix)
 {
int entries, was_valid, newfd;
struct lock_file *lock_file;
@@ -603,23 +603,23 @@ int write_cache_as_tree(unsigned char *sha1, int flags, 
const char *prefix)
 */
lock_file = xcalloc(1, sizeof(struct lock_file));
 
-   newfd = hold_locked_index(lock_file, 1);
+   newfd = hold_lock_file_for_update(lock_file, index_path, 
LOCK_DIE_ON_ERROR);
 
-   entries = read_cache();
+   entries = read_index_from(index_state, index_path);
if (entries  0)
return WRITE_TREE_UNREADABLE_INDEX;
if (flags  WRITE_TREE_IGNORE_CACHE_TREE)
-   cache_tree_free((active_cache_tree));
+   cache_tree_free(index_state-cache_tree);
 
-   if (!active_cache_tree)
-   active_cache_tree = cache_tree();
+   if (!index_state-cache_tree)
+   index_state-cache_tree = cache_tree();
 
-   was_valid = cache_tree_fully_valid(active_cache_tree);
+   was_valid = cache_tree_fully_valid(index_state-cache_tree);
if (!was_valid) {
-   if (cache_tree_update(the_index, flags)  0)
+   if (cache_tree_update(index_state, flags)  0)
return WRITE_TREE_UNMERGED_INDEX;
if (0 = newfd) {
-   if (!write_locked_index(the_index, lock_file, 
COMMIT_LOCK))
+   if (!write_locked_index(index_state, lock_file, 
COMMIT_LOCK))
newfd = -1;
}
/* Not being able to write is fine -- we are only interested
@@ -631,14 +631,14 @@ int write_cache_as_tree(unsigned char *sha1, int flags, 
const char *prefix)
}
 
if (prefix) {
-   struct cache_tree *subtree =
-   cache_tree_find(active_cache_tree, prefix);
+   struct cache_tree *subtree;
+   subtree = cache_tree_find(index_state-cache_tree, prefix);
if (!subtree)
return WRITE_TREE_PREFIX_ERROR;
hashcpy(sha1, subtree-sha1);
}
else
-   hashcpy(sha1, active_cache_tree-sha1);
+   hashcpy(sha1, index_state-cache_tree-sha1);
 
if (0 = newfd)
rollback_lock_file(lock_file);
@@ -646,6 +646,11 @@ int write_cache_as_tree(unsigned char *sha1, int flags, 
const char *prefix)
return 0;
 }
 
+int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
+{
+   return write_index_as_tree(sha1, the_index, get_index_file(), flags, 
prefix);
+}
+
 static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
 {
struct tree_desc desc;
diff --git a/cache-tree.h b/cache-tree.h
index aa7b3e4..41c5746 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -46,6 +46,7 @@ int update_main_cache_tree(int);
 #define WRITE_TREE_UNMERGED_INDEX (-2)
 #define WRITE_TREE_PREFIX_ERROR (-3)
 
+int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, 
const char *index_path, int flags, const char *prefix);
 int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix);
 void prime_cache_tree(struct index_state *, struct tree *);
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 33/45] builtin-am: invoke post-rewrite hook

2015-07-19 Thread Paul Tan
Since 96e1948 (rebase: invoke post-rewrite hook, 2010-03-12), git-am.sh
will invoke the post-rewrite hook after it successfully finishes
applying all the queued patches.

To do this, when parsing a mail to extract its patch and metadata, in
--rebasing mode git-am.sh will also store the original commit ID in the
$state_dir/original-commit file. Once it applies and commits the patch,
the original commit ID, and the new commit ID, will be appended to the
$state_dir/rewritten file.

Once all of the queued mail have been processed, git-am.sh will then
invoke the post-rewrite hook with the contents of the
$state_dir/rewritten file.

Re-implement this in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 55 +++
 1 file changed, 55 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 3612bb3..e99e1ec 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -95,6 +95,9 @@ struct am_state {
char *msg;
size_t msg_len;
 
+   /* when --rebasing, records the original commit the patch came from */
+   unsigned char orig_commit[GIT_SHA1_RAWSZ];
+
/* number of digits in patch filename */
int prec;
 
@@ -394,6 +397,11 @@ static void am_load(struct am_state *state)
 
read_commit_msg(state);
 
+   if (read_state_file(sb, state, original-commit, 1)  0)
+   hashclr(state-orig_commit);
+   else if (get_sha1_hex(sb.buf, state-orig_commit)  0)
+   die(_(could not parse %s), am_path(state, original-commit));
+
read_state_file(sb, state, threeway, 1);
state-threeway = !strcmp(sb.buf, t);
 
@@ -449,6 +457,30 @@ static void am_destroy(const struct am_state *state)
 }
 
 /**
+ * Runs post-rewrite hook. Returns it exit code.
+ */
+static int run_post_rewrite_hook(const struct am_state *state)
+{
+   struct child_process cp = CHILD_PROCESS_INIT;
+   const char *hook = find_hook(post-rewrite);
+   int ret;
+
+   if (!hook)
+   return 0;
+
+   argv_array_push(cp.args, hook);
+   argv_array_push(cp.args, rebase);
+
+   cp.in = xopen(am_path(state, rewritten), O_RDONLY);
+   cp.stdout_to_stderr = 1;
+
+   ret = run_command(cp);
+
+   close(cp.in);
+   return ret;
+}
+
+/**
  * Determines if the file looks like a piece of RFC2822 mail by grabbing all
  * non-indented lines and checking if they look like they begin with valid
  * header field names.
@@ -722,6 +754,9 @@ static void am_next(struct am_state *state)
unlink(am_path(state, author-script));
unlink(am_path(state, final-commit));
 
+   hashclr(state-orig_commit);
+   unlink(am_path(state, original-commit));
+
if (!get_sha1(HEAD, head))
write_file(am_path(state, abort-safety), 1, %s, 
sha1_to_hex(head));
else
@@ -1040,6 +1075,8 @@ static void write_commit_patch(const struct am_state 
*state, struct commit *comm
  * directly. This is used in --rebasing mode to bypass git-mailinfo's munging
  * of patches.
  *
+ * state-orig_commit will be set to the original commit ID.
+ *
  * Will always return 0 as the patch should never be skipped.
  */
 static int parse_mail_rebase(struct am_state *state, const char *mail)
@@ -1056,6 +1093,10 @@ static int parse_mail_rebase(struct am_state *state, 
const char *mail)
 
write_commit_patch(state, commit);
 
+   hashcpy(state-orig_commit, commit_sha1);
+   write_file(am_path(state, original-commit), 1, %s,
+   sha1_to_hex(commit_sha1));
+
return 0;
 }
 
@@ -1247,6 +1288,15 @@ static void do_commit(const struct am_state *state)
 
update_ref(sb.buf, HEAD, commit, ptr, 0, UPDATE_REFS_DIE_ON_ERR);
 
+   if (state-rebasing) {
+   FILE *fp = xfopen(am_path(state, rewritten), a);
+
+   assert(!is_null_sha1(state-orig_commit));
+   fprintf(fp, %s , sha1_to_hex(state-orig_commit));
+   fprintf(fp, %s\n, sha1_to_hex(commit));
+   fclose(fp);
+   }
+
strbuf_release(sb);
 }
 
@@ -1355,6 +1405,11 @@ next:
am_next(state);
}
 
+   if (!is_empty_file(am_path(state, rewritten))) {
+   assert(state-rebasing);
+   run_post_rewrite_hook(state);
+   }
+
/*
 * In rebasing mode, it's up to the caller to take care of
 * housekeeping.
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 40/45] builtin-am: support and auto-detect StGit series files

2015-07-19 Thread Paul Tan
Since c574e68 (git-am foreign patch support: StGIT support, 2009-05-27),
git-am.sh is able to read a single StGit series file and, for each StGit
patch listed in the file, convert the StGit patch into a RFC2822 mail
patch suitable for parsing with git-mailinfo, and queue them in the
state directory for applying.

Since 15ced75 (git-am foreign patch support: autodetect some patch
formats, 2009-05-27), git-am.sh is able to auto-detect StGit series
files by checking to see if the file starts with the string:

# This series applies on GIT commit

Re-implement the above in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 59 ++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/builtin/am.c b/builtin/am.c
index 101bca3..01f8a53 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -80,7 +80,8 @@ static int str_isspace(const char *str)
 enum patch_format {
PATCH_FORMAT_UNKNOWN = 0,
PATCH_FORMAT_MBOX,
-   PATCH_FORMAT_STGIT
+   PATCH_FORMAT_STGIT,
+   PATCH_FORMAT_STGIT_SERIES
 };
 
 enum keep_type {
@@ -652,6 +653,11 @@ static int detect_patch_format(const char **paths)
goto done;
}
 
+   if (starts_with(l1.buf, # This series applies on GIT commit)) {
+   ret = PATCH_FORMAT_STGIT_SERIES;
+   goto done;
+   }
+
strbuf_reset(l2);
strbuf_getline_crlf(l2, fp);
strbuf_reset(l3);
@@ -803,6 +809,53 @@ static int stgit_patch_to_mail(FILE *out, FILE *in, int 
keep_cr)
 }
 
 /**
+ * This function only supports a single StGit series file in `paths`.
+ *
+ * Given an StGit series file, converts the StGit patches in the series into
+ * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in
+ * the state directory.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int split_mail_stgit_series(struct am_state *state, const char **paths,
+   int keep_cr)
+{
+   const char *series_dir;
+   char *series_dir_buf;
+   FILE *fp;
+   struct argv_array patches = ARGV_ARRAY_INIT;
+   struct strbuf sb = STRBUF_INIT;
+   int ret;
+
+   if (!paths[0] || paths[1])
+   return error(_(Only one StGIT patch series can be applied at 
once));
+
+   series_dir_buf = xstrdup(*paths);
+   series_dir = dirname(series_dir_buf);
+
+   fp = fopen(*paths, r);
+   if (!fp)
+   return error(_(could not open '%s' for reading: %s), *paths,
+   strerror(errno));
+
+   while (!strbuf_getline(sb, fp, '\n')) {
+   if (*sb.buf == '#')
+   continue; /* skip comment lines */
+
+   argv_array_push(patches, mkpath(%s/%s, series_dir, sb.buf));
+   }
+
+   fclose(fp);
+   strbuf_release(sb);
+   free(series_dir_buf);
+
+   ret = split_mail_conv(stgit_patch_to_mail, state, patches.argv, 
keep_cr);
+
+   argv_array_clear(patches);
+   return ret;
+}
+
+/**
  * Splits a list of files/directories into individual email patches. Each path
  * in `paths` must be a file/directory that is formatted according to
  * `patch_format`.
@@ -832,6 +885,8 @@ static int split_mail(struct am_state *state, enum 
patch_format patch_format,
return split_mail_mbox(state, paths, keep_cr);
case PATCH_FORMAT_STGIT:
return split_mail_conv(stgit_patch_to_mail, state, paths, 
keep_cr);
+   case PATCH_FORMAT_STGIT_SERIES:
+   return split_mail_stgit_series(state, paths, keep_cr);
default:
die(BUG: invalid patch_format);
}
@@ -1881,6 +1936,8 @@ static int parse_opt_patchformat(const struct option 
*opt, const char *arg, int
*opt_value = PATCH_FORMAT_MBOX;
else if (!strcmp(arg, stgit))
*opt_value = PATCH_FORMAT_STGIT;
+   else if (!strcmp(arg, stgit-series))
+   *opt_value = PATCH_FORMAT_STGIT_SERIES;
else
return error(_(Invalid value for --patch-format: %s), arg);
return 0;
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 09/45] builtin-am: implement committing applied patch

2015-07-19 Thread Paul Tan
Implement do_commit(), which commits the index which contains the
results of applying the patch, along with the extracted commit message
and authorship information.

Since 29b6754 (am: remove rebase-apply directory before gc, 2010-02-22),
git gc --auto is also invoked to pack the loose objects that are created
from making the commits.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 55 +++
 1 file changed, 51 insertions(+), 4 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index 1f198e4..a2811b6 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -11,6 +11,9 @@
 #include run-command.h
 #include quote.h
 #include lockfile.h
+#include cache-tree.h
+#include refs.h
+#include commit.h
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -674,10 +677,56 @@ static int run_apply(const struct am_state *state)
 }
 
 /**
+ * Commits the current index with state-msg as the commit message and
+ * state-author_name, state-author_email and state-author_date as the author
+ * information.
+ */
+static void do_commit(const struct am_state *state)
+{
+   unsigned char tree[GIT_SHA1_RAWSZ], parent[GIT_SHA1_RAWSZ],
+ commit[GIT_SHA1_RAWSZ];
+   unsigned char *ptr;
+   struct commit_list *parents = NULL;
+   const char *reflog_msg, *author;
+   struct strbuf sb = STRBUF_INIT;
+
+   if (write_cache_as_tree(tree, 0, NULL))
+   die(_(git write-tree failed to write a tree));
+
+   if (!get_sha1_commit(HEAD, parent)) {
+   ptr = parent;
+   commit_list_insert(lookup_commit(parent), parents);
+   } else {
+   ptr = NULL;
+   fprintf_ln(stderr, _(applying to an empty history));
+   }
+
+   author = fmt_ident(state-author_name, state-author_email,
+   state-author_date, IDENT_STRICT);
+
+   if (commit_tree(state-msg, state-msg_len, tree, parents, commit,
+   author, NULL))
+   die(_(failed to write commit object));
+
+   reflog_msg = getenv(GIT_REFLOG_ACTION);
+   if (!reflog_msg)
+   reflog_msg = am;
+
+   strbuf_addf(sb, %s: %.*s, reflog_msg, linelen(state-msg),
+   state-msg);
+
+   update_ref(sb.buf, HEAD, commit, ptr, 0, UPDATE_REFS_DIE_ON_ERR);
+
+   strbuf_release(sb);
+}
+
+/**
  * Applies all queued mail.
  */
 static void am_run(struct am_state *state)
 {
+   const char *argv_gc_auto[] = {gc, --auto, NULL};
+
refresh_and_write_cache();
 
while (state-cur = state-last) {
@@ -709,16 +758,14 @@ static void am_run(struct am_state *state)
exit(128);
}
 
-   /*
-* NEEDSWORK: After the patch has been applied to the index
-* with git-apply, we need to make commit as well.
-*/
+   do_commit(state);
 
 next:
am_next(state);
}
 
am_destroy(state);
+   run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
 }
 
 /**
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 27/45] builtin-am: support --keep-cr, am.keepcr

2015-07-19 Thread Paul Tan
Since ad2c928 (git-am: Add command line parameter `--keep-cr` passing it
to git-mailsplit, 2010-02-27), git-am.sh supported the --keep-cr option
and would pass it to git-mailsplit.

Since e80d4cb (git-am: Add am.keepcr and --no-keep-cr to override it,
2010-02-27), git-am.sh supported the am.keepcr config setting, which
controls whether --keep-cr is on by default.

Re-implement the above in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 29 +++--
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index e41a104..80f091e 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -504,7 +504,7 @@ done:
  * Splits out individual email patches from `paths`, where each path is either
  * a mbox file or a Maildir. Returns 0 on success, -1 on failure.
  */
-static int split_mail_mbox(struct am_state *state, const char **paths)
+static int split_mail_mbox(struct am_state *state, const char **paths, int 
keep_cr)
 {
struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf last = STRBUF_INIT;
@@ -514,6 +514,8 @@ static int split_mail_mbox(struct am_state *state, const 
char **paths)
argv_array_pushf(cp.args, -d%d, state-prec);
argv_array_pushf(cp.args, -o%s, state-dir);
argv_array_push(cp.args, -b);
+   if (keep_cr)
+   argv_array_push(cp.args, --keep-cr);
argv_array_push(cp.args, --);
argv_array_pushv(cp.args, paths);
 
@@ -538,14 +540,22 @@ static int split_mail_mbox(struct am_state *state, const 
char **paths)
  * state-cur will be set to the index of the first mail, and state-last will
  * be set to the index of the last mail.
  *
+ * Set keep_cr to 0 to convert all lines ending with \r\n to end with \n, 1
+ * to disable this behavior, -1 to use the default configured setting.
+ *
  * Returns 0 on success, -1 on failure.
  */
 static int split_mail(struct am_state *state, enum patch_format patch_format,
-   const char **paths)
+   const char **paths, int keep_cr)
 {
+   if (keep_cr  0) {
+   keep_cr = 0;
+   git_config_get_bool(am.keepcr, keep_cr);
+   }
+
switch (patch_format) {
case PATCH_FORMAT_MBOX:
-   return split_mail_mbox(state, paths);
+   return split_mail_mbox(state, paths, keep_cr);
default:
die(BUG: invalid patch_format);
}
@@ -556,7 +566,7 @@ static int split_mail(struct am_state *state, enum 
patch_format patch_format,
  * Setup a new am session for applying patches
  */
 static void am_setup(struct am_state *state, enum patch_format patch_format,
-   const char **paths)
+   const char **paths, int keep_cr)
 {
unsigned char curr_head[GIT_SHA1_RAWSZ];
const char *str;
@@ -572,7 +582,7 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
if (mkdir(state-dir, 0777)  0  errno != EEXIST)
die_errno(_(failed to create directory '%s'), state-dir);
 
-   if (split_mail(state, patch_format, paths)  0) {
+   if (split_mail(state, patch_format, paths, keep_cr)  0) {
am_destroy(state);
die(_(Failed to split patches.));
}
@@ -1512,6 +1522,7 @@ enum resume_mode {
 int cmd_am(int argc, const char **argv, const char *prefix)
 {
struct am_state state;
+   int keep_cr = -1;
int patch_format = PATCH_FORMAT_UNKNOWN;
enum resume_mode resume = RESUME_FALSE;
 
@@ -1535,6 +1546,12 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
N_(pass -b flag to git-mailinfo), KEEP_NON_PATCH),
OPT_BOOL('m', message-id, state.message_id,
N_(pass -m flag to git-mailinfo)),
+   { OPTION_SET_INT, 0, keep-cr, keep_cr, NULL,
+ N_(pass --keep-cr flag to git-mailsplit for mbox format),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1},
+   { OPTION_SET_INT, 0, no-keep-cr, keep_cr, NULL,
+ N_(do not pass --keep-cr flag to git-mailsplit independent 
of am.keepcr),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 0},
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
@@ -1632,7 +1649,7 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
argv_array_push(paths, mkpath(%s/%s, prefix, 
argv[i]));
}
 
-   am_setup(state, patch_format, paths.argv);
+   am_setup(state, patch_format, paths.argv, keep_cr);
 
argv_array_clear(paths);
}
-- 
2.5.0.rc2.110.gb39b692

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

[PATCH v6 44/45] builtin-am: check for valid committer ident

2015-07-19 Thread Paul Tan
When commit_tree() is called, if the user does not have an explicit
committer ident configured, it will attempt to construct a default
committer ident based on the user's and system's info (e.g. gecos field,
hostname etc.) However, if a default committer ident is unable to be
constructed, commit_tree() will die(), but at this point of git-am's
execution, there will already be changes made to the index and work
tree.

This can be confusing to new users, and as such since d64e6b0 (Keep
Porcelainish from failing by broken ident after making changes.,
2006-02-18) git-am.sh will check to see if the committer ident has been
configured, or a default one can be constructed, before even starting to
apply patches.

Re-implement this in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 6a2b887..1fe2c65 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -2247,6 +2247,9 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
fprintf_ln(stderr, _(The -b/--binary option has been a no-op 
for long time, and\n
it will be removed. Please do not use it 
anymore.));
 
+   /* Ensure a valid committer ident can be constructed */
+   git_committer_info(IDENT_STRICT);
+
if (read_index_preload(the_index, NULL)  0)
die(_(failed to read the index));
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 45/45] builtin-am: remove redirection to git-am.sh

2015-07-19 Thread Paul Tan
At the beginning of the rewrite of git-am.sh to C, in order to not break
existing test scripts that depended on a functional git-am, a
redirection to git-am.sh was introduced that would activate if the
environment variable _GIT_USE_BUILTIN_AM was not defined.

Now that all of git-am.sh's functionality has been re-implemented in
builtin/am.c, remove this redirection, and retire git-am.sh into
contrib/examples/.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 Makefile|  1 -
 builtin/am.c| 15 ---
 git-am.sh = contrib/examples/git-am.sh |  0
 git.c   |  7 +--
 4 files changed, 1 insertion(+), 22 deletions(-)
 rename git-am.sh = contrib/examples/git-am.sh (100%)

diff --git a/Makefile b/Makefile
index f88642a..ec51f03 100644
--- a/Makefile
+++ b/Makefile
@@ -467,7 +467,6 @@ TEST_PROGRAMS_NEED_X =
 # interactive shell sessions without exporting it.
 unexport CDPATH
 
-SCRIPT_SH += git-am.sh
 SCRIPT_SH += git-bisect.sh
 SCRIPT_SH += git-difftool--helper.sh
 SCRIPT_SH += git-filter-branch.sh
diff --git a/builtin/am.c b/builtin/am.c
index 1fe2c65..1116304 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -,21 +,6 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
OPT_END()
};
 
-   /*
-* NEEDSWORK: Once all the features of git-am.sh have been
-* re-implemented in builtin/am.c, this preamble can be removed.
-*/
-   if (!getenv(_GIT_USE_BUILTIN_AM)) {
-   const char *path = mkpath(%s/git-am, git_exec_path());
-
-   if (sane_execvp(path, (char **)argv)  0)
-   die_errno(could not exec %s, path);
-   } else {
-   prefix = setup_git_directory();
-   trace_repo_setup(prefix);
-   setup_work_tree();
-   }
-
git_config(git_default_config, NULL);
 
am_state_init(state, git_path(rebase-apply));
diff --git a/git-am.sh b/contrib/examples/git-am.sh
similarity index 100%
rename from git-am.sh
rename to contrib/examples/git-am.sh
diff --git a/git.c b/git.c
index 38d9ad5..5feba41 100644
--- a/git.c
+++ b/git.c
@@ -370,12 +370,7 @@ static int run_builtin(struct cmd_struct *p, int argc, 
const char **argv)
 
 static struct cmd_struct commands[] = {
{ add, cmd_add, RUN_SETUP | NEED_WORK_TREE },
-   /*
-* NEEDSWORK: Once the redirection to git-am.sh in builtin/am.c has
-* been removed, this entry should be changed to
-* RUN_SETUP | NEED_WORK_TREE
-*/
-   { am, cmd_am },
+   { am, cmd_am, RUN_SETUP | NEED_WORK_TREE },
{ annotate, cmd_annotate, RUN_SETUP },
{ apply, cmd_apply, RUN_SETUP_GENTLY },
{ archive, cmd_archive },
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 25/45] builtin-am: implement -k/--keep, --keep-non-patch

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sh supported the -k/--keep option to pass the -k option to
git-mailsplit.

Since f7e5ea1 (am: learn passing -b to mailinfo, 2012-01-16), git-am.sh
supported the --keep-non-patch option to pass the -b option to
git-mailsplit.

Re-implement these two options in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 50 ++
 1 file changed, 50 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index a64a859..af08a22 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -68,6 +68,12 @@ enum patch_format {
PATCH_FORMAT_MBOX
 };
 
+enum keep_type {
+   KEEP_FALSE = 0,
+   KEEP_TRUE,  /* pass -k flag to git-mailinfo */
+   KEEP_NON_PATCH  /* pass -b flag to git-mailinfo */
+};
+
 struct am_state {
/* state directory path */
char *dir;
@@ -91,6 +97,7 @@ struct am_state {
int quiet;
int append_signoff;
int utf8;
+   int keep; /* enum keep_type */
const char *resolvemsg;
int rebasing;
 };
@@ -375,6 +382,14 @@ static void am_load(struct am_state *state)
read_state_file(sb, state, utf8, 1);
state-utf8 = !strcmp(sb.buf, t);
 
+   read_state_file(sb, state, keep, 1);
+   if (!strcmp(sb.buf, t))
+   state-keep = KEEP_TRUE;
+   else if (!strcmp(sb.buf, b))
+   state-keep = KEEP_NON_PATCH;
+   else
+   state-keep = KEEP_FALSE;
+
state-rebasing = !!file_exists(am_path(state, rebasing));
 
strbuf_release(sb);
@@ -538,6 +553,7 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
const char **paths)
 {
unsigned char curr_head[GIT_SHA1_RAWSZ];
+   const char *str;
 
if (!patch_format)
patch_format = detect_patch_format(paths);
@@ -566,6 +582,22 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
 
write_file(am_path(state, utf8), 1, state-utf8 ? t : f);
 
+   switch (state-keep) {
+   case KEEP_FALSE:
+   str = f;
+   break;
+   case KEEP_TRUE:
+   str = t;
+   break;
+   case KEEP_NON_PATCH:
+   str = b;
+   break;
+   default:
+   die(BUG: invalid value for state-keep);
+   }
+
+   write_file(am_path(state, keep), 1, %s, str);
+
if (state-rebasing)
write_file(am_path(state, rebasing), 1, %s, );
else
@@ -733,6 +765,20 @@ static int parse_mail(struct am_state *state, const char 
*mail)
 
argv_array_push(cp.args, mailinfo);
argv_array_push(cp.args, state-utf8 ? -u : -n);
+
+   switch (state-keep) {
+   case KEEP_FALSE:
+   break;
+   case KEEP_TRUE:
+   argv_array_push(cp.args, -k);
+   break;
+   case KEEP_NON_PATCH:
+   argv_array_push(cp.args, -b);
+   break;
+   default:
+   die(BUG: invalid value for state-keep);
+   }
+
argv_array_push(cp.args, am_path(state, msg));
argv_array_push(cp.args, am_path(state, patch));
 
@@ -1472,6 +1518,10 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
N_(add a Signed-off-by line to the commit message)),
OPT_BOOL('u', utf8, state.utf8,
N_(recode into utf8 (default))),
+   OPT_SET_INT('k', keep, state.keep,
+   N_(pass -k flag to git-mailinfo), KEEP_TRUE),
+   OPT_SET_INT(0, keep-non-patch, state.keep,
+   N_(pass -b flag to git-mailinfo), KEEP_NON_PATCH),
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 26/45] builtin-am: implement --[no-]message-id, am.messageid

2015-07-19 Thread Paul Tan
Since a078f73 (git-am: add --message-id/--no-message-id, 2014-11-25),
git-am.sh supported the --[no-]message-id options, and the
am.messageid setting which specifies the default option.

--[no-]message-id tells git-am whether or not the -m option should be
passed to git-mailinfo.

Re-implement this option in builtin/am.c.

Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index af08a22..e41a104 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -98,6 +98,7 @@ struct am_state {
int append_signoff;
int utf8;
int keep; /* enum keep_type */
+   int message_id;
const char *resolvemsg;
int rebasing;
 };
@@ -118,6 +119,8 @@ static void am_state_init(struct am_state *state, const 
char *dir)
git_config_get_bool(am.threeway, state-threeway);
 
state-utf8 = 1;
+
+   git_config_get_bool(am.messageid, state-message_id);
 }
 
 /**
@@ -390,6 +393,9 @@ static void am_load(struct am_state *state)
else
state-keep = KEEP_FALSE;
 
+   read_state_file(sb, state, messageid, 1);
+   state-message_id = !strcmp(sb.buf, t);
+
state-rebasing = !!file_exists(am_path(state, rebasing));
 
strbuf_release(sb);
@@ -598,6 +604,8 @@ static void am_setup(struct am_state *state, enum 
patch_format patch_format,
 
write_file(am_path(state, keep), 1, %s, str);
 
+   write_file(am_path(state, messageid), 1, state-message_id ? t : 
f);
+
if (state-rebasing)
write_file(am_path(state, rebasing), 1, %s, );
else
@@ -779,6 +787,9 @@ static int parse_mail(struct am_state *state, const char 
*mail)
die(BUG: invalid value for state-keep);
}
 
+   if (state-message_id)
+   argv_array_push(cp.args, -m);
+
argv_array_push(cp.args, am_path(state, msg));
argv_array_push(cp.args, am_path(state, patch));
 
@@ -1522,6 +1533,8 @@ int cmd_am(int argc, const char **argv, const char 
*prefix)
N_(pass -k flag to git-mailinfo), KEEP_TRUE),
OPT_SET_INT(0, keep-non-patch, state.keep,
N_(pass -b flag to git-mailinfo), KEEP_NON_PATCH),
+   OPT_BOOL('m', message-id, state.message_id,
+   N_(pass -m flag to git-mailinfo)),
OPT_CALLBACK(0, patch-format, patch_format, N_(format),
N_(format the patch(es) are in),
parse_opt_patchformat),
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 39/45] builtin-am: support and auto-detect StGit patches

2015-07-19 Thread Paul Tan
Since c574e68 (git-am foreign patch support: StGIT support, 2009-05-27),
git-am.sh supported converting StGit patches into RFC2822 mail patches
that can be parsed with git-mailinfo.

Implement this by introducing two functions in builtin/am.c:
stgit_patch_to_mail() and split_mail_conv().

stgit_patch_to_mail() is a callback function for split_mail_conv(), and
contains the logic for converting an StGit patch into an RFC2822 mail
patch.

split_mail_conv() implements the logic to go through each file in the
`paths` list, reading from stdin where specified, and calls the callback
function to write the converted patch to the corresponding output file
in the state directory. This interface should be generic enough to
support other foreign patch formats in the future.

Since 15ced75 (git-am foreign patch support: autodetect some patch
formats, 2009-05-27), git-am.sh is able to auto-detect StGit patches.
Re-implement this in builtin/am.c.

Helped-by: Eric Sunshine sunsh...@sunshineco.com
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 132 ++-
 1 file changed, 131 insertions(+), 1 deletion(-)

diff --git a/builtin/am.c b/builtin/am.c
index 89613e0..101bca3 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -65,9 +65,22 @@ static int linelen(const char *msg)
return strchrnul(msg, '\n') - msg;
 }
 
+/**
+ * Returns true if `str` consists of only whitespace, false otherwise.
+ */
+static int str_isspace(const char *str)
+{
+   for (; *str; str++)
+   if (!isspace(*str))
+   return 0;
+
+   return 1;
+}
+
 enum patch_format {
PATCH_FORMAT_UNKNOWN = 0,
-   PATCH_FORMAT_MBOX
+   PATCH_FORMAT_MBOX,
+   PATCH_FORMAT_STGIT
 };
 
 enum keep_type {
@@ -612,6 +625,8 @@ static int detect_patch_format(const char **paths)
 {
enum patch_format ret = PATCH_FORMAT_UNKNOWN;
struct strbuf l1 = STRBUF_INIT;
+   struct strbuf l2 = STRBUF_INIT;
+   struct strbuf l3 = STRBUF_INIT;
FILE *fp;
 
/*
@@ -637,6 +652,23 @@ static int detect_patch_format(const char **paths)
goto done;
}
 
+   strbuf_reset(l2);
+   strbuf_getline_crlf(l2, fp);
+   strbuf_reset(l3);
+   strbuf_getline_crlf(l3, fp);
+
+   /*
+* If the second line is empty and the third is a From, Author or Date
+* entry, this is likely an StGit patch.
+*/
+   if (l1.len  !l2.len 
+   (starts_with(l3.buf, From:) ||
+starts_with(l3.buf, Author:) ||
+starts_with(l3.buf, Date:))) {
+   ret = PATCH_FORMAT_STGIT;
+   goto done;
+   }
+
if (l1.len  is_mail(fp)) {
ret = PATCH_FORMAT_MBOX;
goto done;
@@ -677,6 +709,100 @@ static int split_mail_mbox(struct am_state *state, const 
char **paths, int keep_
 }
 
 /**
+ * Callback signature for split_mail_conv(). The foreign patch should be
+ * read from `in`, and the converted patch (in RFC2822 mail format) should be
+ * written to `out`. Return 0 on success, or -1 on failure.
+ */
+typedef int (*mail_conv_fn)(FILE *out, FILE *in, int keep_cr);
+
+/**
+ * Calls `fn` for each file in `paths` to convert the foreign patch to the
+ * RFC2822 mail format suitable for parsing with git-mailinfo.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
+   const char **paths, int keep_cr)
+{
+   static const char *stdin_only[] = {-, NULL};
+   int i;
+
+   if (!*paths)
+   paths = stdin_only;
+
+   for (i = 0; *paths; paths++, i++) {
+   FILE *in, *out;
+   const char *mail;
+   int ret;
+
+   if (!strcmp(*paths, -))
+   in = stdin;
+   else
+   in = fopen(*paths, r);
+
+   if (!in)
+   return error(_(could not open '%s' for reading: %s),
+   *paths, strerror(errno));
+
+   mail = mkpath(%s/%0*d, state-dir, state-prec, i + 1);
+
+   out = fopen(mail, w);
+   if (!out)
+   return error(_(could not open '%s' for writing: %s),
+   mail, strerror(errno));
+
+   ret = fn(out, in, keep_cr);
+
+   fclose(out);
+   fclose(in);
+
+   if (ret)
+   return error(_(could not parse patch '%s'), *paths);
+   }
+
+   state-cur = 1;
+   state-last = i;
+   return 0;
+}
+
+/**
+ * A split_mail_conv() callback that converts an StGit patch to an RFC2822
+ * message suitable for parsing with git-mailinfo.
+ */
+static int stgit_patch_to_mail(FILE *out, FILE *in, int keep_cr)
+{
+   struct strbuf sb = STRBUF_INIT;
+   int subject_printed = 0;
+
+   while 

Re: [PATCH v3 9/9] tag.c: implement '--merged' and '--no-merged' options

2015-07-19 Thread Christian Couder
On Sun, Jul 19, 2015 at 12:00 AM, Karthik Nayak karthik@gmail.com wrote:
 From: Karthik Nayak karthik@gmail.com

 Using 'ref-filter' APIs implement the '--merged' and '--no-merged'
 options into 'tag.c'. The '--merged' option lets the user to only
 list tags merged into the named commit. The '--no-merged' option
 lets the user to only list tags not merged into the named commit.
 If no object is provided it assumes HEAD as the object.

 Add documentation and tests for the same.

 Mentored-by: Christian Couder christian.cou...@gmail.com
 Mentored-by: Matthieu Moy matthieu@grenoble-inp.fr
 Signed-off-by: Karthik Nayak karthik@gmail.com
 ---
  Documentation/git-tag.txt | 10 +-
  builtin/tag.c |  6 +-
  t/t7004-tag.sh| 27 +++
  3 files changed, 41 insertions(+), 2 deletions(-)

 diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
 index 16e396c..74ed157 100644
 --- a/Documentation/git-tag.txt
 +++ b/Documentation/git-tag.txt
 @@ -14,7 +14,7 @@ SYNOPSIS
  'git tag' -d tagname...
  'git tag' [-n[num]] -l [--contains commit] [--points-at object]
 [--column[=options] | --no-column] [--sort=key] 
 [--format=format]
 -   [pattern...]
 +   [(--merged | --no-merged) [commit]] [pattern...]

Maybe [--[no-]merged [commit]] instead of [(--merged | --no-merged)
[commit]].

  'git tag' -v tagname...

  DESCRIPTION
 @@ -169,6 +169,14 @@ This option is only applicable when listing tags without 
 annotation lines.
 `%09` to `\t` (TAB) and `%0a` to `\n` (LF).
 The fields are same as those in `git for-each-ref`.

 +--merged [commit]::
 +   Only list tags whose tips are reachable from the
 +   specified commit (HEAD if not specified).
 +
 +--no-merged [commit]::
 +   Only list tags whose tips are not reachable from the
 +   specified commit (HEAD if not specified).

Here also you could write something like:

+--[no-]merged [commit]::
+   Only list tags whose tips are reachable, or not reachable
+   if --no-merged is used, from the specified commit
+   (HEAD if not specified).


  CONFIGURATION
  -
 diff --git a/builtin/tag.c b/builtin/tag.c
 index cae113b..0fa1d31 100644
 --- a/builtin/tag.c
 +++ b/builtin/tag.c
 @@ -23,7 +23,7 @@ static const char * const git_tag_usage[] = {
 N_(git tag [-a | -s | -u key-id] [-f] [-m msg | -F file] 
 tagname [head]),
 N_(git tag -d tagname...),
 N_(git tag -l [-n[num]] [--contains commit] [--points-at 
 object]
 -   \n\t\t[pattern...]),
 +   \n\t\t[--merged [commit]] [--no-merged [commit]] 
 [pattern...]),

[--[no-]merged [commit]] here too.

Thanks,
Christian.
--
To unsubscribe from this list: send the line 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 07/16] engine.pl: Fix i18n -o option in msvc buildsystem generator

2015-07-19 Thread Philip Oakley
The i18n 5e9637c (i18n: add infrastructure for translating
Git with gettext, 2011-11-18) introduced an extra '-o' option
into the make file.

If the msvc buildsystem is run without NO_GETTEXT being set
then this broke the engine.pl code for extracting the git.sln
for msvc gui-IDE. The setting of NO_GETTEXT was not fixed until
later, relative to the Msysgit project where this issue was being
investigated.

The presence of these options in the Makefile output should not
compromise the derived build structure. They should be ignored.

Add tests to remove these non linker options, in same vein as
74cf9bd (engine.pl: Fix a recent breakage of the buildsystem
generator, 2010-01-22).

Signed-off-by: Philip Oakley philipoak...@iee.org
---
 contrib/buildsystems/engine.pl | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index 24b8992..60c7a7d 100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -141,6 +141,12 @@ sub parseMakeOutput
 next;
 }
 
+if ($text =~ /^(mkdir|msgfmt) /) {
+# options to the Portable Object translations
+# the line mkdir ...  msgfmt ... contains no linker options
+next;
+}
+
 if($text =~ / -c /) {
 # compilation
 handleCompileLine($text, $line);
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 12/16] engine.pl: provide more debug print statements

2015-07-19 Thread Philip Oakley
Assist developers transitioning between the two cultures
by including appropriate, but commented out, debug statements.

The exception is when an unhandled compiler option is detected,
where printing of the full line will supplement the line number and
option part. Otherwise the OP has no immediate mechanism for
inspecting the relevant part of the makedry output.

The commented out code is deactivated code, not dead code, as per
DO178B safety critical software development guideline [1].

These debug print statements act as a guide for a poor man's --verbose
option. The test suite doesn't cover the contrib/buildsystems (or
Msysgit's msvc-build) contributions so fails to notice breakages there-in.

It is doubly hard to get developers to ride both horses so, contrary to
normal convention, retain selected debug statements as a safety net for
those willing to try.

[1] Dead code : Dead code is source code (and it is a part of binary code)
that is not executed in the final system and it will be not having
traceability to any requirements (one can say unintentional code).

Deactivated code: code which is commented out or removed via #ifdef's
(it is not a part of final binary code) and it will be having
traceability to its low level requirements (its a intentional code and
it can be activated in some configurations through hardware traps for
debugging or other purposes.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
My response to Sebastian Schuberth's comment on dead code
http://marc.info/?l=gitm=143630748919942w=2 (2015-07-07)
---
 contrib/buildsystems/engine.pl | 4 
 1 file changed, 4 insertions(+)

diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index 4a843f3..3238d16 100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -41,6 +41,7 @@ EOM
 # Parse command-line options
 while (@ARGV) {
 my $arg = shift @ARGV;
+   #print Arg: $arg \n;
 if ($arg eq -h || $arg eq --help || $arg eq -?) {
showUsage();
exit(0);
@@ -129,6 +130,7 @@ sub parseMakeOutput
 print Parsing GNU Make output to figure out build structure...\n;
 my $line = 0;
 while (my $text = shift @makedry) {
+   #print Make: $text\n; # show the makedry line
 my $ate_next;
 do {
 $ate_next = 0;
@@ -263,6 +265,7 @@ sub handleCompileLine
 } elsif ($part =~ /\.(c|cc|cpp)$/) {
 $sourcefile = $part;
 } else {
+print full line: $line\n;
 die Unhandled compiler option @ line $lineno: $part;
 }
 }
@@ -288,6 +291,7 @@ sub handleLibLine
 $libout = $part;
 $libout =~ s/\.a$//;
 } else {
+print full line: $line\n;
 die Unhandled lib option @ line $lineno: $part;
 }
 }
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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/16] engine.pl: Properly accept quoted spaces in filenames

2015-07-19 Thread Philip Oakley
The engine.pl script barfs on the properly quoted spaces in
filename options prevalent on Windows. Use shellwords() rather
than split() to separate such options.

Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Philip Oakley philipoak...@iee.org
---
Junio's help at gmane.comp.version-control.msysgit/21145 (2014-11-21)
 gmane.comp.version-control.msysgit/21147 (2014-11-21)
---
 contrib/buildsystems/engine.pl | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index c8a5258..24b8992 100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -12,6 +12,7 @@ use File::Basename;
 use File::Spec;
 use Cwd;
 use Generators;
+use Text::ParseWords;
 
 my (%build_structure, %compile_options, @makedry);
 my $out_dir = getcwd();
@@ -231,7 +232,7 @@ sub removeDuplicates
 sub handleCompileLine
 {
 my ($line, $lineno) = @_;
-my @parts = split(' ', $line);
+my @parts = shellwords($line);
 my $sourcefile;
 shift(@parts); # ignore cmd
 while (my $part = shift @parts) {
@@ -265,7 +266,7 @@ sub handleLibLine
 my (@objfiles, @lflags, $libout, $part);
 # kill cmd and rm 'prefix'
 $line =~ s/^rm -f .*  .* rcs //;
-my @parts = split(' ', $line);
+my @parts = shellwords($line);
 while ($part = shift @parts) {
 if ($part =~ /^-/) {
 push(@lflags, $part);
@@ -306,7 +307,7 @@ sub handleLinkLine
 {
 my ($line, $lineno) = @_;
 my (@objfiles, @lflags, @libs, $appout, $part);
-my @parts = split(' ', $line);
+my @parts = shellwords($line);
 shift(@parts); # ignore cmd
 while ($part = shift @parts) {
 if ($part =~ /^-IGNORE/) {
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 02/16] .gitignore: improve MSVC ignore patterns

2015-07-19 Thread Philip Oakley
Add the Microsoft .manifest pattern, and correct the generic 'Debug'
and 'Release' directory patterns which were mechanically adjusted way
back in c591d5f (gitignore: root most patterns at the top-level directory,
2009-10-26) to allow multi-level projects within the Git suite.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
Junio's correction http://marc.info/?l=gitm=143524522500906w=2
(2015-06-25)
---
 .gitignore | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index a685ec1..91e75ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -247,5 +247,6 @@
 *.user
 *.idb
 *.pdb
-/Debug/
-/Release/
+*.manifest
+Debug/
+Release/
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 15/16] msvc-build: add complete Microsoft Visual C compilation script

2015-07-19 Thread Philip Oakley
Implement the README to facilitate cross community development.
Include comments for those Windows folks not yet fully familiar
with bash commands.

This is identical to the msysgit script, except for the 'cd toplevel'
step, and comments for the edification of converts from Windows.

Original author: Johannes Schindelin (2011-11-01 3142da4 : Add a script
to make the MSVC build more convenient) on Msysgit
https://github.com/msysgit/msysgit/commit/3142da4038 and subsequent
development.

The --gui clean now also removes the VS2010 .sdf file, and the
vcs-svn_lib  xdiff_lib directories.

The script is made executable in line with $msysgit/cb9836b8a
(Mark scripts and binaries in /bin/ as executable, 2012-06-26)

Signed-off-by: Philip Oakley philipoak...@iee.org
---

TODO:
resolve any further cleaning of newer VS2010... build products.
---
 compat/vcbuild/README |  2 +
 compat/vcbuild/scripts/msvc-build | 86 +++
 2 files changed, 88 insertions(+)
 create mode 100755 compat/vcbuild/scripts/msvc-build

diff --git a/compat/vcbuild/README b/compat/vcbuild/README
index ad8633e..faaea69 100644
--- a/compat/vcbuild/README
+++ b/compat/vcbuild/README
@@ -57,3 +57,5 @@ The Steps of Build Git with VS2008
Git, which you set up in step 1.
 
 Done!
+
+Or, use the msvc-build script; available from /compat/vcbuild/scripts/.
diff --git a/compat/vcbuild/scripts/msvc-build 
b/compat/vcbuild/scripts/msvc-build
new file mode 100755
index 000..d67203b
--- /dev/null
+++ b/compat/vcbuild/scripts/msvc-build
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+# This msvc-build command should be executed from the msysgit directory level
+# This is so that the 'cd/git' step works and the subequent operations have 
the right msysgit super directory.
+set -e # Exit immediately if a command exits with a nonzero exit status.
+
+gui=
+clean=
+while test $# -gt 0
+do
+   case $1 in
+   --gui|--dev|--devenv|--vs|--visual-studio)
+   gui=t
+   ;;
+   clean)
+   clean=t
+   ;;
+   *)
+   echo Usage: $0 [--vs] [clean] 2
+   exit 1
+   ;;
+   esac
+   shift
+done
+
+cd $(git rev-parse --show-toplevel)
+
+case $clean in
+t)
+   case $gui in
+   t)
+   rm -rf git.sln git.sdf libgit vcs-svn_lib xdiff_lib
+   # remove any other new VS2010... stuff as well: rm -rf  ?
+   ;;
+   '')
+   make clean
+   ;;
+   esac
+   exit
+   ;;
+esac
+
+to_ignore=$(git ls-files --other --exclude-standard msvcgit msvc-build.cmd)
+test -z $to_ignore || {
+   mkdir -p .git/info 
+   echo $to_ignore |
+   sed 's/^/\//'  .git/info/exclude
+} || exit
+
+test -d msvcgit || git clone git://repo.or.cz/msvcgit.git
+
+vsvars=
+# assume cl.exe will populate its relevant environment variables
+# if cl.exe does not exist, populate vsvars with the most recent Visual Studio 
path
+type cl.exe 2 /dev/null ||
+vsvars=$(ls -t \
+   $PROGRAMFILES/Microsoft Visual Studio*/Common7/Tools/vsvars32.bat |
+   head -n 1)
+
+
+config_mak=
+# if a config.mak file (dot, not underscore) exists, back it up,
+# remember the backup file name in config_mak.
+test -f config.mak 
+config_mak=config.mak.bup.$$ 
+mv config.mak $config_mak
+
+cat  config.mak  EOF
+CFLAGS += -Imsvcgit/32bits/include
+LDFLAGS += -Lmsvcgit/32bits/lib
+EOF
+
+echo call \$vsvars\  msvc-build.cmd
+if test -z $gui
+then
+   echo 'make MSVC=1'  msvc-build.cmd
+else
+   echo 'perl contrib/buildsystems/generate -g Vcproj'  msvc-build.cmd
+   echo 'start git.sln'  msvc-build.cmd
+fi
+
+cmd /c msvc-build.cmd
+
+# if we made a backup file (name in config_mak), then restore it.
+test -z $config_mak ||
+mv $config_mak config.mak
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 14/16] vcbuild/readme: Improve layout and reference msvc-build script

2015-07-19 Thread Philip Oakley
Layout the 'either/or' with more white space to clarify
which alternatives are matched up.

Reference the Msysgit build script which automates one sequence of options.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
 compat/vcbuild/README | 27 +++
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/compat/vcbuild/README b/compat/vcbuild/README
index df8a657..7548dc4 100644
--- a/compat/vcbuild/README
+++ b/compat/vcbuild/README
@@ -3,20 +3,24 @@ The Steps of Build Git with VS2008
 1. You need the build environment, which contains the Git dependencies
to be able to compile, link and run Git with MSVC.
 
-   You can either use the binary repository:
+   You can either:
+  use the binary repository:
 
WWW: http://repo.or.cz/w/msvcgit.git
Git: git clone git://repo.or.cz/msvcgit.git
Zip: http://repo.or.cz/w/msvcgit.git?a=snapshot;h=master;sf=zip
 
-   and call the setup_32bit_env.cmd batch script before compiling Git,
-   (see repo/package README for details), or the source repository:
+  and call the setup_32bit_env.cmd batch script before compiling Git,
+ (see repo/package README for details),
+
+   or:
+  use the source repository:
 
WWW: http://repo.or.cz/w/gitbuild.git
Git: git clone git://repo.or.cz/gitbuild.git
Zip: (None, as it's a project with submodules)
 
-   and build the support libs as instructed in that repo/package.
+ and build the support libs as instructed in that repo/package.
 
 2. Ensure you have the msysgit environment in your path, so you have
GNU Make, bash and perl available.
@@ -33,18 +37,25 @@ The Steps of Build Git with VS2008
make common-cmds.h
to generate the common-cmds.h file needed to compile git.
 
-4. Then either build Git with the GNU Make Makefile in the Git projects
-   root
+4. Then either
+
+ build Git with the GNU Make Makefile in the Git projects root
make MSVC=1
-   or generate Visual Studio solution/projects (.sln/.vcproj) with the
+   or
+
+   generate Visual Studio solution/projects (.sln/.vcproj) with the
command
perl contrib/buildsystems/generate -g Vcproj
and open and build the solution with the IDE
devenv git.sln /useenv
-   or build with the IDE build engine directly from the command line
+ or
+
+   build with the IDE build engine directly from the command line
devenv git.sln /useenv /build Release|Win32
The /useenv option is required, so Visual Studio picks up the
environment variables for the support libraries required to build
Git, which you set up in step 1.
 
 Done!
+
+Or, use the Msysgit msvc-build script; available from that project.
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 16/16] config.mak.uname: add MSVC No_SafeExeceptionHandler option

2015-07-19 Thread Philip Oakley
Microsoft flipped the Windows Safe Exception Handling default
in VS2013 so that zlib became unacceptable to certain OS versions
(Vista and subsequent 32-bit OS's) without the addition of
the option -SAFESEH:NO.

Provide a switch to disable the Safe Exeption Handler when required.

The option ImageHasSafeExceptionHandlers for VS2013 is not available in
earlier versions, so use the SAFESEH:NO linker flag. See
https://msdn.microsoft.com/en-us/library/9a89h429.aspx for
further details.

This has only had limited testing due to the lack of a suitable system.

Helped-by: Yue Lin Ho b8732...@student.nsysu.edu.tw
Signed-off-by: Philip Oakley philipoak...@iee.org
---
Junio/my discussion on reviews: http://marc.info/?l=gitm=143526063906215w=2 
(2015-06-25)
Patch series v1: https://github.com/msysgit/git/pull/318
Yue Lin Ho: https://github.com/msysgit/git/pull/318#issuecomment-81292918
---
 config.mak.uname | 9 +
 1 file changed, 9 insertions(+)

diff --git a/config.mak.uname b/config.mak.uname
index 943c439..1c27828 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -1,5 +1,9 @@
 # Platform specific Makefile tweaks based on uname detection
 
+# Define NO_SAFESEH if you need MSVC/Visual Studio to ignore the lack of
+# Microsoft's Safe Exception Handling in libraries (such as zlib).
+# Typically required for VS2013+/32-bit compilation on Vista+ versions.
+
 uname_S := $(shell sh -c 'uname -s 2/dev/null || echo not')
 uname_M := $(shell sh -c 'uname -m 2/dev/null || echo not')
 uname_O := $(shell sh -c 'uname -o 2/dev/null || echo not')
@@ -385,6 +389,11 @@ ifeq ($(uname_S),Windows)
PTHREAD_LIBS =
lib =
BASIC_CFLAGS += -DPROTECT_NTFS_DEFAULT=1
+
+ifdef NO_SAFESEH
+   LDFLAGS += -SAFESEH:NO
+endif
+
 ifndef DEBUG
BASIC_CFLAGS += -GL -Os -MD
BASIC_LDFLAGS += -LTCG
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 08/16] engine.pl: ignore invalidcontinue.obj which is known to MSVC

2015-07-19 Thread Philip Oakley
Commit 4b623d8 (MSVC: link in invalidcontinue.obj for better
POSIX compatibility, 2014-03-29) is not processed correctly
by the buildsystem. Ignore it.

Also split the .o and .obj processing; 'make' does not produce .obj
files. Only substitute filenames ending with .o when generating the
source .c filename.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
 contrib/buildsystems/engine.pl | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index 60c7a7d..9db3d43 100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -289,7 +289,7 @@ sub handleLibLine
 #exit(1);
 foreach (@objfiles) {
 my $sourcefile = $_;
-$sourcefile =~ s/\.o/.c/;
+$sourcefile =~ s/\.o$/.c/;
 push(@sources, $sourcefile);
 push(@cflags, @{$compile_options{${sourcefile}_CFLAGS}});
 push(@defines, @{$compile_options{${sourcefile}_DEFINES}});
@@ -333,8 +333,12 @@ sub handleLinkLine
 } elsif ($part =~ /\.(a|lib)$/) {
 $part =~ s/\.a$/.lib/;
 push(@libs, $part);
-} elsif ($part =~ /\.(o|obj)$/) {
+} elsif ($part eq 'invalidcontinue.obj') {
+# ignore - known to MSVC
+} elsif ($part =~ /\.o$/) {
 push(@objfiles, $part);
+} elsif ($part =~ /\.obj$/) {
+# do nothing, 'make' should not be producing .obj, only .o files
 } else {
 die Unhandled link option @ line $lineno: $part;
 }
@@ -343,7 +347,7 @@ sub handleLinkLine
 #exit(1);
 foreach (@objfiles) {
 my $sourcefile = $_;
-$sourcefile =~ s/\.o/.c/;
+$sourcefile =~ s/\.o$/.c/;
 push(@sources, $sourcefile);
 push(@cflags, @{$compile_options{${sourcefile}_CFLAGS}});
 push(@defines, @{$compile_options{${sourcefile}_DEFINES}});
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 09/16] engine.pl: name the msvc buildsystem's makedry error file

2015-07-19 Thread Philip Oakley
Save the stderr from the dry MSVC make to a well named file for
later review. Use 'msvc-build-makedryerrors.txt' which should be
obvious as to its source, and is not ignored by 'git status'.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
fixed false mode change:- Junio's report (last line of)
http://marc.info/?l=gitm=143524504500824 (2015-06-25),

The cause was probably an early 'commit --amend' during a
rebase, and using the git gui to unstage the whole commit, then
pick up and commit hunks one at a time. Unfortunately, on Msysgit/g4w
core.filemode is false, so the execute bit was lost during the
unstage, never noticed, and there's no simple way of adding it back.

Discussion on correcting file mode on msysgit/git4Windows is at
https://groups.google.com/forum/#!topic/msysgit/zwH-qj0xR48
---
 contrib/buildsystems/engine.pl | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index 9db3d43..a6999b6 100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -73,7 +73,10 @@ Running GNU Make to figure out build structure...
 EOM
 
 # Pipe a make --dry-run into a variable, if not already loaded from file
-@makedry = `cd $git_dir  make -n MSVC=1 V=1 2/dev/null` if !@makedry;
+# Capture the make dry stderr to file for review (will be empty for a release 
build).
+
+my $ErrsFile = msvc-build-makedryerrors.txt;
+@makedry = `cd $git_dir  make -n MSVC=1 V=1 2$ErrsFile` if !@makedry;
 
 # Parse the make output into usable info
 parseMakeOutput();
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 10/16] engine.pl: delete the captured stderr file if empty

2015-07-19 Thread Philip Oakley
Keep the build clean of extraneous files if it is indeed clean.
Otherwise leave the msvc-build-makedryerrors.txt file both as
a flag for any CI system or for manual debugging.

Note that the file will contain the new values of the GIT_VERSION
and GITGUI_VERSION if they were generated by the make file. They
are omitted if the release is tagged and indentically defined in
their respective GIT_VERSION_GEN file DEF_VER variables.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
 contrib/buildsystems/engine.pl | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index a6999b6..020776e 100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -77,6 +77,8 @@ EOM
 
 my $ErrsFile = msvc-build-makedryerrors.txt;
 @makedry = `cd $git_dir  make -n MSVC=1 V=1 2$ErrsFile` if !@makedry;
+# test for an empty Errors file and remove it
+for ($ErrsFile) {unlink $_ if (-f $_)  (!-s $_);}
 
 # Parse the make output into usable info
 parseMakeOutput();
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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/16] perl/Makefile: treat a missing PM.stamp as if empty

2015-07-19 Thread Philip Oakley
'make clean', or a 'git clean -dfx' will delete the PM stamp file,
so it cannot be a direct target in such clean conditions, resulting
in an error.

Normally the PM.stamp is recreated by the git/Makefile, except when
a dry-run is requested, for example, as used in the msysgit msvc-build
script which implements the compat/vcbuild/README using
contrib/buildsystems. The script msvc-build is introduced later in this
series.

Protect the PM.stamp target when the PM.stamp file does not exist,
allowing a Git 'Makefile -n' to succeed on a clean repo.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
This is development of the original [PATCH 4/17] Makefile: a dry-run
can error out if no perl. Document the issue 2015-06-25,
(http://marc.info/?l=gitm=143519054716960w=2), which simply documented
the issue and then used NO_PERL to avoid the problem. See follow on
email thread for some discussion.
---
 perl/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/perl/Makefile b/perl/Makefile
index 15d96fc..5b86aac 100644
--- a/perl/Makefile
+++ b/perl/Makefile
@@ -22,7 +22,9 @@ clean:
$(RM) $(makfile).old
$(RM) PM.stamp
 
+ifneq (,$(wildcard PM.stamp))
 $(makfile): PM.stamp
+endif
 
 ifdef NO_PERL_MAKEMAKER
 instdir_SQ = $(subst ','\'',$(prefix)/lib)
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 05/16] engine.pl: fix error message (lib-link)

2015-07-19 Thread Philip Oakley
Signed-off-by: Philip Oakley philipoak...@iee.org
---
 contrib/buildsystems/engine.pl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index 23da787..c8a5258 100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -329,7 +329,7 @@ sub handleLinkLine
 } elsif ($part =~ /\.(o|obj)$/) {
 push(@objfiles, $part);
 } else {
-die Unhandled lib option @ line $lineno: $part;
+die Unhandled link option @ line $lineno: $part;
 }
 }
 #print AppOut: '$appout'\nLFlags: @lflags\nLibs  : @libs\nOfiles: 
@objfiles\n;
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 11/16] engine.pl: add debug line to capture the dry-run

2015-07-19 Thread Philip Oakley
Add a debug suggestion for capturing to file the stdout from the dry-run
of the make file used in determining the msvc-build structure for easy
debugging.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
 contrib/buildsystems/engine.pl | 1 +
 1 file changed, 1 insertion(+)

diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index 020776e..4a843f3 100755
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -76,6 +76,7 @@ EOM
 # Capture the make dry stderr to file for review (will be empty for a release 
build).
 
 my $ErrsFile = msvc-build-makedryerrors.txt;
+#@makedry = `cd $git_dir  make -n MSVC=1 V=1 1makedry.txt 2$ErrsFile`; # 
capture the dry run as a text file
 @makedry = `cd $git_dir  make -n MSVC=1 V=1 2$ErrsFile` if !@makedry;
 # test for an empty Errors file and remove it
 for ($ErrsFile) {unlink $_ if (-f $_)  (!-s $_);}
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 03/16] .gitignore: ignore library directories created by MSVC VS2008 buildsystem

2015-07-19 Thread Philip Oakley
Signed-off-by: Philip Oakley philipoak...@iee.org
---
 .gitignore | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.gitignore b/.gitignore
index 91e75ee..e35c492 100644
--- a/.gitignore
+++ b/.gitignore
@@ -178,6 +178,7 @@
 /gitweb/gitweb.cgi
 /gitweb/static/gitweb.js
 /gitweb/static/gitweb.min.*
+/libgit
 /test-chmtime
 /test-ctype
 /test-config
@@ -210,6 +211,8 @@
 /test-urlmatch-normalization
 /test-wildmatch
 /common-cmds.h
+/vcs-svn_lib
+/xdiff_lib
 *.tar.gz
 *.dsc
 *.deb
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 04/16] (msvc-build) Vcproj.pm: remove duplicate GUID

2015-07-19 Thread Philip Oakley
Delete the duplicated GUID from the generation code for the Visual Studio
.sln project file.

The duplicate GUID tended to be allocated to test-svn-fe, which was then
ignored by Visual Studio / MSVC, and its omission from the build never
noticed.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
Eric Sunshine correction http://marc.info/?l=gitm=143546075320855w=2
---
 contrib/buildsystems/Generators/Vcproj.pm | 1 -
 1 file changed, 1 deletion(-)

diff --git a/contrib/buildsystems/Generators/Vcproj.pm 
b/contrib/buildsystems/Generators/Vcproj.pm
index cfa74ad..1b01d58 100644
--- a/contrib/buildsystems/Generators/Vcproj.pm
+++ b/contrib/buildsystems/Generators/Vcproj.pm
@@ -52,7 +52,6 @@ my @GUIDS = (
 {00785268-A9CC-4E40-AC29-BAC0019159CE},
 {4C06F56A-DCDB-46A6-B67C-02339935CF12},
 {3A62D3FD-519E-4EC9-8171-D2C1BFEA022F},
-{3A62D3FD-519E-4EC9-8171-D2C1BFEA022F},
 {9392EB58-D7BA-410B-B1F0-B2FAA6BC89A7},
 {2ACAB2D5-E0CE-4027-BCA0-D78B2D7A6C66},
 {86E216C3-43CE-481A-BCB2-BE5E62850635},
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 00/16] Make the msvc-build scripts work again

2015-07-19 Thread Philip Oakley
This updated series fixes the scripts which generated Visual Studio project
files. The scripts had bit rotted over the years as other commits
changed the git makefile which it post-processes.

The series doesn't attempt (yet) to install the Visual Studio compiled product
but allows Windows developers familiar with VS to support the Windows SDK
port of Git.

The fixes are presented in a fine grained manner.

The key change in this series is that the failure of using the git/Makefile
for a clean dry-run has been identified in perl/Makefile. The new fix replaces
two previous hack patches.

Grammatical corrections and other comments have all been included. In
particular the use of deactivated code is now better explained. The false
mode change has also been fixed (from using 'git gui', who's unstage/re-stage
action on Windows with its core.filemode=false loses the 'x' bit).

The previous patch series was not picked up on $gmane, but is available
at http://marc.info/?t=14351906523r=1w=2 (2015-06-25)

Older patch series were at:
 $gmane/21132 (2014-11-20),
 $gmane/21207 (2014-12-26),
 and on Msysgit list (2015-02-23) at
 https://groups.google.com/forum/?hl=en_US?hl%3Den#!topic/msysgit/aiEVBKjRshY
 and as a PR https://github.com/msysgit/git/pull/318/files


Philip Oakley (16):
  perl/Makefile: treat a missing PM.stamp as if empty
  .gitignore: improve MSVC ignore patterns
  .gitignore: ignore library directories created by MSVC VS2008
buildsystem
  (msvc-build) Vcproj.pm: remove duplicate GUID
  engine.pl: fix error message (lib-link)
  engine.pl: Properly accept quoted spaces in filenames
  engine.pl: Fix i18n -o option in msvc buildsystem generator
  engine.pl: ignore invalidcontinue.obj which is known to MSVC
  engine.pl: name the msvc buildsystem's makedry error file
  engine.pl: delete the captured stderr file if empty
  engine.pl: add debug line to capture the dry-run
  engine.pl: provide more debug print statements
  Vcproj.pm: list git.exe first to be startup project
  vcbuild/readme: Improve layout
  msvc-build: add complete Microsoft Visual C compilation script
  config.mak.uname: add MSVC No_SafeExeceptionHandler option

 .gitignore|  8 ++-
 compat/vcbuild/README | 27 +++---
 compat/vcbuild/scripts/msvc-build | 86 +++
 config.mak.uname  |  9 
 contrib/buildsystems/Generators/Vcproj.pm | 34 ++--
 contrib/buildsystems/engine.pl| 37 ++---
 perl/Makefile |  2 +
 7 files changed, 170 insertions(+), 33 deletions(-)
 create mode 100755 compat/vcbuild/scripts/msvc-build

-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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 13/16] Vcproj.pm: list git.exe first to be startup project

2015-07-19 Thread Philip Oakley
Visual Studio takes the first listed application/library as the default
startup project [1].

Detect the 'git' project and place it the head of the apps list, rather
than the tail.

Export the apps list before libs list for both the projects and global
structures of the .sln file.

[1] http://stackoverflow.com/questions/1238553/
vs2008-where-is-the-startup-project-setting-stored-for-a-solution
In the solution file, there are a list of pseudo-XML Project
entries. It turns out that whatever is the first one ends up as
the Startup Project, unless it’s overridden in the suo file. Argh.
I just rearranged the order in the file and it’s good.

just moving the pseudo-xml isn't enough. You also have to move the
group of entries in the GlobalSection(ProjectConfigurationPlatforms)
= postSolution group that has the GUID of the project you moved to
the top. So there are two places to move lines.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
 contrib/buildsystems/Generators/Vcproj.pm | 33 ++-
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/contrib/buildsystems/Generators/Vcproj.pm 
b/contrib/buildsystems/Generators/Vcproj.pm
index 1b01d58..cc2fa21 100644
--- a/contrib/buildsystems/Generators/Vcproj.pm
+++ b/contrib/buildsystems/Generators/Vcproj.pm
@@ -560,20 +560,18 @@ sub createGlueProject {
 foreach (@apps) {
 $_ =~ s/\//_/g;
 $_ =~ s/\.exe//;
-push(@tmp, $_);
+if ($_ eq git ) {
+unshift(@tmp, $_);
+} else {
+push(@tmp, $_);
+}
 }
 @apps = @tmp;
 
 open F, git.sln || die Could not open git.sln for writing!\n;
 binmode F, :crlf;
 print F $SLN_HEAD;
-foreach (@libs) {
-my $libname = $_;
-my $uuid = $build_structure{LIBS_${libname}_GUID};
-print F $SLN_PRE;
-print F \${libname}\, \${libname}\\${libname}.vcproj\, 
\${uuid}\;
-print F $SLN_POST;
-}
+
 my $uuid_libgit = $build_structure{LIBS_libgit_GUID};
 my $uuid_xdiff_lib = $build_structure{LIBS_xdiff_lib_GUID};
 foreach (@apps) {
@@ -587,6 +585,13 @@ sub createGlueProject {
 print F   EndProjectSection;
 print F $SLN_POST;
 }
+foreach (@libs) {
+my $libname = $_;
+my $uuid = $build_structure{LIBS_${libname}_GUID};
+print F $SLN_PRE;
+print F \${libname}\, \${libname}\\${libname}.vcproj\, 
\${uuid}\;
+print F $SLN_POST;
+}
 
 print F  EOM;
 Global
@@ -598,17 +603,17 @@ EOM
 print F  EOM;
GlobalSection(ProjectConfigurationPlatforms) = postSolution
 EOM
-foreach (@libs) {
-my $libname = $_;
-my $uuid = $build_structure{LIBS_${libname}_GUID};
+foreach (@apps) {
+my $appname = $_;
+my $uuid = $build_structure{APPS_${appname}_GUID};
 print F \t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n;
 print F \t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n;
 print F \t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n;
 print F \t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n;
 }
-foreach (@apps) {
-my $appname = $_;
-my $uuid = $build_structure{APPS_${appname}_GUID};
+foreach (@libs) {
+my $libname = $_;
+my $uuid = $build_structure{LIBS_${libname}_GUID};
 print F \t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n;
 print F \t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n;
 print F \t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n;
-- 
2.4.2.windows.1.5.gd32afb6

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


[PATCH v3 11/12] t3418: non-interactive rebase --continue with rerere enabled

2015-07-19 Thread Paul Tan
Since 8389b52 (git-rerere: reuse recorded resolve., 2006-01-28), git-am
will call git-rerere to re-use recorded merge conflict resolutions if
any occur in a threeway merge.

Add a test to ensure that git-rerere is called by git-am (which handles
the non-interactive rebase).

Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t3418-rebase-continue.sh | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index 2680375..4428b90 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -40,6 +40,25 @@ test_expect_success 'non-interactive rebase --continue works 
with touched file'
git rebase --continue
 '
 
+test_expect_success 'non-interactive rebase --continue with rerere enabled' '
+   test_config rerere.enabled true 
+   test_when_finished test_might_fail git rebase --abort 
+   git reset --hard commit-new-file-F2-on-topic-branch 
+   git checkout master 
+   rm -fr .git/rebase-* 
+
+   test_must_fail git rebase --onto master master topic 
+   echo Resolved F2 
+   git add F2 
+   cp F2 F2.expected 
+   git rebase --continue 
+
+   git reset --hard commit-new-file-F2-on-topic-branch 
+   git checkout master 
+   test_must_fail git rebase --onto master master topic 
+   test_cmp F2.expected F2
+'
+
 test_expect_success 'rebase --continue can not be used with other options' '
test_must_fail git rebase -v --continue 
test_must_fail git rebase --continue -v
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 10/12] t4150: tests for am --[no-]scissors

2015-07-19 Thread Paul Tan
Since 017678b (am/mailinfo: Disable scissors processing by default,
2009-08-26), git-am supported the --[no-]scissors option, passing it to
git-mailinfo.

Add tests to ensure that git-am will pass the --scissors option to
git-mailinfo, and that --no-scissors will override the configuration
setting of mailinfo.scissors.

Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t4150-am.sh | 48 
 1 file changed, 48 insertions(+)

diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 7494240..67fbf0e 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -67,6 +67,19 @@ test_expect_success 'setup: messages' '
 
EOF
 
+   cat scissors-msg -\EOF 
+   Test git-am with scissors line
+
+   This line should be included in the commit message.
+   EOF
+
+   cat - scissors-msg no-scissors-msg -\EOF 
+   This line should not be included in the commit message with --scissors 
enabled.
+
+- - 8 - - remove everything above this line - - 8 - -
+
+   EOF
+
signoff=Signed-off-by: $GIT_COMMITTER_NAME $GIT_COMMITTER_EMAIL
 '
 
@@ -105,6 +118,20 @@ test_expect_success setup '
git format-patch --stdout first | sed -e 1d
}  patch1-ws.eml 
 
+   echo scissors-file scissors-file 
+   git add scissors-file 
+   git commit -F scissors-msg 
+   git tag scissors 
+   git format-patch --stdout scissors^ scissors-patch.eml 
+   git reset --hard HEAD^ 
+
+   echo no-scissors-file no-scissors-file 
+   git add no-scissors-file 
+   git commit -F no-scissors-msg 
+   git tag no-scissors 
+   git format-patch --stdout no-scissors^ no-scissors-patch.eml 
+   git reset --hard HEAD^ 
+
sed -n -e 3,\$p msg file 
git add file 
test_tick 
@@ -305,6 +332,27 @@ test_expect_success 'am with failing post-applypatch hook' 
'
test_cmp head.expected head.actual
 '
 
+test_expect_success 'am --scissors cuts the message at the scissors line' '
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout second 
+   git am --scissors scissors-patch.eml 
+   test_path_is_missing .git/rebase-apply 
+   git diff --exit-code scissors 
+   test_cmp_rev scissors HEAD
+'
+
+test_expect_success 'am --no-scissors overrides mailinfo.scissors' '
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout second 
+   test_config mailinfo.scissors true 
+   git am --no-scissors no-scissors-patch.eml 
+   test_path_is_missing .git/rebase-apply 
+   git diff --exit-code no-scissors 
+   test_cmp_rev no-scissors HEAD
+'
+
 test_expect_success 'setup: new author and committer' '
GIT_AUTHOR_NAME=Another Thor 
GIT_AUTHOR_EMAIL=a.t...@example.com 
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 12/12] t3901: test git-am encoding conversion

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07), git-am
supported the --utf8 and --no-utf8 options, and if set, would pass the
-u flag and the -k flag respectively.

git mailinfo -u will re-code the commit log message and authorship info
in the charset specified by i18n.commitencoding setting, while
git mailinfo -n will disable the re-coding.

Since d84029b (--utf8 is now default for 'git-am', 2007-01-08), --utf8
is set by default in git-am.

Add various encoding conversion tests to t3901 to test git-mailinfo's
encoding conversion. In addition, add a test for --no-utf8 to check that
no encoding conversion will occur if that option is set.

Helped-by: Johannes Sixt j...@kdbg.org
Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---

Notes:
v3

* Added !MINGW prereq for the other test case that uses ISO-8859-1
  encoded environment vars

 t/t3901-i18n-patch.sh | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh
index 75cf3ff..509084e 100755
--- a/t/t3901-i18n-patch.sh
+++ b/t/t3901-i18n-patch.sh
@@ -251,4 +251,66 @@ test_expect_success 'rebase --merge (L/U)' '
check_encoding 2 8859
 '
 
+test_expect_success 'am (U/U)' '
+   # Apply UTF-8 patches with UTF-8 commitencoding
+   git config i18n.commitencoding UTF-8 
+   . $TEST_DIRECTORY/t3901-utf8.txt 
+
+   git reset --hard master 
+   git am out-u1 out-u2 
+
+   check_encoding 2
+'
+
+test_expect_success !MINGW 'am (L/L)' '
+   # Apply ISO-8859-1 patches with ISO-8859-1 commitencoding
+   git config i18n.commitencoding ISO8859-1 
+   . $TEST_DIRECTORY/t3901-8859-1.txt 
+
+   git reset --hard master 
+   git am out-l1 out-l2 
+
+   check_encoding 2 8859
+'
+
+test_expect_success 'am (U/L)' '
+   # Apply ISO-8859-1 patches with UTF-8 commitencoding
+   git config i18n.commitencoding UTF-8 
+   . $TEST_DIRECTORY/t3901-utf8.txt 
+   git reset --hard master 
+
+   # am specifies --utf8 by default.
+   git am out-l1 out-l2 
+
+   check_encoding 2
+'
+
+test_expect_success 'am --no-utf8 (U/L)' '
+   # Apply ISO-8859-1 patches with UTF-8 commitencoding
+   git config i18n.commitencoding UTF-8 
+   . $TEST_DIRECTORY/t3901-utf8.txt 
+
+   git reset --hard master 
+   git am --no-utf8 out-l1 out-l2 2err 
+
+   # commit-tree will warn that the commit message does not contain valid 
UTF-8
+   # as mailinfo did not convert it
+   grep did not conform err 
+
+   check_encoding 2
+'
+
+test_expect_success !MINGW 'am (L/U)' '
+   # Apply UTF-8 patches with ISO-8859-1 commitencoding
+   git config i18n.commitencoding ISO8859-1 
+   . $TEST_DIRECTORY/t3901-8859-1.txt 
+
+   git reset --hard master 
+   # mailinfo will re-code the commit message to the charset specified by
+   # i18n.commitencoding
+   git am out-u1 out-u2 
+
+   check_encoding 2 8859
+'
+
 test_done
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 09/12] t4150: am with post-applypatch hook

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sh will invoke the post-applypatch hook after the patch is
applied and a commit is made. The exit code of the hook is ignored.

Add tests for this hook.

Helped-by: Junio C Hamano gits...@pobox.com
Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t4150-am.sh | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 957c63c..7494240 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -267,6 +267,44 @@ test_expect_success 'am with failing pre-applypatch hook' '
test_cmp_rev first HEAD
 '
 
+test_expect_success 'am with post-applypatch hook' '
+   test_when_finished rm -f .git/hooks/post-applypatch 
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout first 
+   mkdir -p .git/hooks 
+   write_script .git/hooks/post-applypatch -\EOF 
+   git rev-parse HEAD head.actual
+   git diff second diff.actual
+   exit 0
+   EOF
+   git am patch1 
+   test_path_is_missing .git/rebase-apply 
+   test_cmp_rev second HEAD 
+   git rev-parse second head.expected 
+   test_cmp head.expected head.actual 
+   git diff second diff.expected 
+   test_cmp diff.expected diff.actual
+'
+
+test_expect_success 'am with failing post-applypatch hook' '
+   test_when_finished rm -f .git/hooks/post-applypatch 
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout first 
+   mkdir -p .git/hooks 
+   write_script .git/hooks/post-applypatch -\EOF 
+   git rev-parse HEAD head.actual
+   exit 1
+   EOF
+   git am patch1 
+   test_path_is_missing .git/rebase-apply 
+   git diff --exit-code second 
+   test_cmp_rev second HEAD 
+   git rev-parse second head.expected 
+   test_cmp head.expected head.actual
+'
+
 test_expect_success 'setup: new author and committer' '
GIT_AUTHOR_NAME=Another Thor 
GIT_AUTHOR_EMAIL=a.t...@example.com 
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v6 01/45] wrapper: implement xopen()

2015-07-19 Thread Paul Tan
A common usage pattern of open() is to check if it was successful, and
die() if it was not:

int fd = open(path, O_WRONLY | O_CREAT, 0777);
if (fd  0)
die_errno(_(Could not open '%s' for writing.), path);

Implement a wrapper function xopen() that does the above so that we can
save a few lines of code, and make the die() messages consistent.

Helped-by: Torsten Bögershausen tbo...@web.de
Helped-by: Jeff King p...@peff.net
Helped-by: Johannes Schindelin johannes.schinde...@gmx.de
Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 git-compat-util.h |  1 +
 wrapper.c | 35 +++
 2 files changed, 36 insertions(+)

diff --git a/git-compat-util.h b/git-compat-util.h
index c6d391f..e168dfd 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -717,6 +717,7 @@ extern void *xrealloc(void *ptr, size_t size);
 extern void *xcalloc(size_t nmemb, size_t size);
 extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, 
off_t offset);
 extern void *xmmap_gently(void *start, size_t length, int prot, int flags, int 
fd, off_t offset);
+extern int xopen(const char *path, int flags, ...);
 extern ssize_t xread(int fd, void *buf, size_t len);
 extern ssize_t xwrite(int fd, const void *buf, size_t len);
 extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset);
diff --git a/wrapper.c b/wrapper.c
index ff49807..0a4502d 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -189,6 +189,41 @@ void *xcalloc(size_t nmemb, size_t size)
 # endif
 #endif
 
+/**
+ * xopen() is the same as open(), but it die()s if the open() fails.
+ */
+int xopen(const char *path, int oflag, ...)
+{
+   mode_t mode = 0;
+   va_list ap;
+
+   /*
+* va_arg() will have undefined behavior if the specified type is not
+* compatible with the argument type. Since integers are promoted to
+* ints, we fetch the next argument as an int, and then cast it to a
+* mode_t to avoid undefined behavior.
+*/
+   va_start(ap, oflag);
+   if (oflag  O_CREAT)
+   mode = va_arg(ap, int);
+   va_end(ap);
+
+   for (;;) {
+   int fd = open(path, oflag, mode);
+   if (fd = 0)
+   return fd;
+   if (errno == EINTR)
+   continue;
+
+   if ((oflag  O_RDWR) == O_RDWR)
+   die_errno(_(could not open '%s' for reading and 
writing), path);
+   else if ((oflag  O_WRONLY) == O_WRONLY)
+   die_errno(_(could not open '%s' for writing), path);
+   else
+   die_errno(_(could not open '%s' for reading), path);
+   }
+}
+
 /*
  * xread() is the same a read(), but it automatically restarts read()
  * operations with a recoverable error (EAGAIN and EINTR). xread()
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 04/45] builtin-am: implement patch queue mechanism

2015-07-19 Thread Paul Tan
git-am applies a series of patches. If the process terminates
abnormally, we want to be able to resume applying the series of patches.
This requires the session state to be saved in a persistent location.

Implement the mechanism of a patch queue, represented by 2 integers --
the index of the current patch we are applying and the index of the last
patch, as well as its lifecycle through the following functions:

* am_setup(), which will set up the state directory
  $GIT_DIR/rebase-apply. As such, even if the process exits abnormally,
  the last-known state will still persist.

* am_load(), which is called if there is an am session in
  progress, to load the last known state from the state directory so we
  can resume applying patches.

* am_run(), which will do the actual patch application. After applying a
  patch, it calls am_next() to increment the current patch index. The
  logic for applying and committing a patch is not implemented yet.

* am_destroy(), which is finally called when we successfully applied all
  the patches in the queue, to clean up by removing the state directory
  and its contents.

Helped-by: Junio C Hamano gits...@pobox.com
Helped-by: Stefan Beller sbel...@google.com
Helped-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 177 +++
 1 file changed, 177 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index fd32caf..ac172c4 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -6,9 +6,171 @@
 #include cache.h
 #include builtin.h
 #include exec_cmd.h
+#include parse-options.h
+#include dir.h
+
+struct am_state {
+   /* state directory path */
+   char *dir;
+
+   /* current and last patch numbers, 1-indexed */
+   int cur;
+   int last;
+};
+
+/**
+ * Initializes am_state with the default values. The state directory is set to
+ * dir.
+ */
+static void am_state_init(struct am_state *state, const char *dir)
+{
+   memset(state, 0, sizeof(*state));
+
+   assert(dir);
+   state-dir = xstrdup(dir);
+}
+
+/**
+ * Releases memory allocated by an am_state.
+ */
+static void am_state_release(struct am_state *state)
+{
+   free(state-dir);
+}
+
+/**
+ * Returns path relative to the am_state directory.
+ */
+static inline const char *am_path(const struct am_state *state, const char 
*path)
+{
+   return mkpath(%s/%s, state-dir, path);
+}
+
+/**
+ * Returns 1 if there is an am session in progress, 0 otherwise.
+ */
+static int am_in_progress(const struct am_state *state)
+{
+   struct stat st;
+
+   if (lstat(state-dir, st)  0 || !S_ISDIR(st.st_mode))
+   return 0;
+   if (lstat(am_path(state, last), st) || !S_ISREG(st.st_mode))
+   return 0;
+   if (lstat(am_path(state, next), st) || !S_ISREG(st.st_mode))
+   return 0;
+   return 1;
+}
+
+/**
+ * Reads the contents of `file` in the `state` directory into `sb`. Returns the
+ * number of bytes read on success, -1 if the file does not exist. If `trim` is
+ * set, trailing whitespace will be removed.
+ */
+static int read_state_file(struct strbuf *sb, const struct am_state *state,
+   const char *file, int trim)
+{
+   strbuf_reset(sb);
+
+   if (strbuf_read_file(sb, am_path(state, file), 0) = 0) {
+   if (trim)
+   strbuf_trim(sb);
+
+   return sb-len;
+   }
+
+   if (errno == ENOENT)
+   return -1;
+
+   die_errno(_(could not read '%s'), am_path(state, file));
+}
+
+/**
+ * Loads state from disk.
+ */
+static void am_load(struct am_state *state)
+{
+   struct strbuf sb = STRBUF_INIT;
+
+   if (read_state_file(sb, state, next, 1)  0)
+   die(BUG: state file 'next' does not exist);
+   state-cur = strtol(sb.buf, NULL, 10);
+
+   if (read_state_file(sb, state, last, 1)  0)
+   die(BUG: state file 'last' does not exist);
+   state-last = strtol(sb.buf, NULL, 10);
+
+   strbuf_release(sb);
+}
+
+/**
+ * Removes the am_state directory, forcefully terminating the current am
+ * session.
+ */
+static void am_destroy(const struct am_state *state)
+{
+   struct strbuf sb = STRBUF_INIT;
+
+   strbuf_addstr(sb, state-dir);
+   remove_dir_recursively(sb, 0);
+   strbuf_release(sb);
+}
+
+/**
+ * Setup a new am session for applying patches
+ */
+static void am_setup(struct am_state *state)
+{
+   if (mkdir(state-dir, 0777)  0  errno != EEXIST)
+   die_errno(_(failed to create directory '%s'), state-dir);
+
+   /*
+* NOTE: Since the next and last files determine if an am_state
+* session is in progress, they should be written last.
+*/
+
+   write_file(am_path(state, next), 1, %d, state-cur);
+
+   write_file(am_path(state, last), 1, %d, state-last);
+}
+
+/**
+ * Increments the patch pointer, and cleans am_state for the application of 

[PATCH v6 03/45] builtin-am: implement skeletal builtin am

2015-07-19 Thread Paul Tan
For the purpose of rewriting git-am.sh into a C builtin, implement a
skeletal builtin/am.c that redirects to $GIT_EXEC_PATH/git-am if the
environment variable _GIT_USE_BUILTIN_AM is not defined. Since in the
Makefile git-am.sh takes precedence over builtin/am.c,
$GIT_EXEC_PATH/git-am will contain the shell script git-am.sh, and thus
this allows us to fall back on the functional git-am.sh when running the
test suite for tests that depend on a working git-am implementation.

Since git-am.sh cannot handle any environment modifications by
setup_git_directory(), am is declared with no setup flags in git.c. On
the other hand, to re-implement git-am.sh in builtin/am.c, we need to
run all the git dir and work tree setup logic that git.c typically does
for us. As such, we work around this temporarily by copying the logic in
git.c's run_builtin(), which is roughly:

prefix = setup_git_directory();
trace_repo_setup(prefix);
setup_work_tree();

This redirection should be removed when all the features of git-am.sh
have been re-implemented in builtin/am.c.

Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 Makefile |  1 +
 builtin.h|  1 +
 builtin/am.c | 29 +
 git.c|  6 ++
 4 files changed, 37 insertions(+)
 create mode 100644 builtin/am.c

diff --git a/Makefile b/Makefile
index c6c28bc..f88642a 100644
--- a/Makefile
+++ b/Makefile
@@ -812,6 +812,7 @@ LIB_OBJS += xdiff-interface.o
 LIB_OBJS += zlib.o
 
 BUILTIN_OBJS += builtin/add.o
+BUILTIN_OBJS += builtin/am.o
 BUILTIN_OBJS += builtin/annotate.o
 BUILTIN_OBJS += builtin/apply.o
 BUILTIN_OBJS += builtin/archive.o
diff --git a/builtin.h b/builtin.h
index 839483d..79aaf0a 100644
--- a/builtin.h
+++ b/builtin.h
@@ -30,6 +30,7 @@ extern int textconv_object(const char *path, unsigned mode, 
const unsigned char
 extern int is_builtin(const char *s);
 
 extern int cmd_add(int argc, const char **argv, const char *prefix);
+extern int cmd_am(int argc, const char **argv, const char *prefix);
 extern int cmd_annotate(int argc, const char **argv, const char *prefix);
 extern int cmd_apply(int argc, const char **argv, const char *prefix);
 extern int cmd_archive(int argc, const char **argv, const char *prefix);
diff --git a/builtin/am.c b/builtin/am.c
new file mode 100644
index 000..fd32caf
--- /dev/null
+++ b/builtin/am.c
@@ -0,0 +1,29 @@
+/*
+ * Builtin git am
+ *
+ * Based on git-am.sh by Junio C Hamano.
+ */
+#include cache.h
+#include builtin.h
+#include exec_cmd.h
+
+int cmd_am(int argc, const char **argv, const char *prefix)
+{
+
+   /*
+* NEEDSWORK: Once all the features of git-am.sh have been
+* re-implemented in builtin/am.c, this preamble can be removed.
+*/
+   if (!getenv(_GIT_USE_BUILTIN_AM)) {
+   const char *path = mkpath(%s/git-am, git_exec_path());
+
+   if (sane_execvp(path, (char **)argv)  0)
+   die_errno(could not exec %s, path);
+   } else {
+   prefix = setup_git_directory();
+   trace_repo_setup(prefix);
+   setup_work_tree();
+   }
+
+   return 0;
+}
diff --git a/git.c b/git.c
index 55c327c..38d9ad5 100644
--- a/git.c
+++ b/git.c
@@ -370,6 +370,12 @@ static int run_builtin(struct cmd_struct *p, int argc, 
const char **argv)
 
 static struct cmd_struct commands[] = {
{ add, cmd_add, RUN_SETUP | NEED_WORK_TREE },
+   /*
+* NEEDSWORK: Once the redirection to git-am.sh in builtin/am.c has
+* been removed, this entry should be changed to
+* RUN_SETUP | NEED_WORK_TREE
+*/
+   { am, cmd_am },
{ annotate, cmd_annotate, RUN_SETUP },
{ apply, cmd_apply, RUN_SETUP_GENTLY },
{ archive, cmd_archive },
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 05/45] builtin-am: split out mbox/maildir patches with git-mailsplit

2015-07-19 Thread Paul Tan
git-am.sh supports mbox, stgit and mercurial patches. Re-implement
support for splitting out mbox/maildirs using git-mailsplit, while also
implementing the framework required to support other patch formats in
the future.

Re-implement support for the --patch-format option (since a5a6755
(git-am foreign patch support: introduce patch_format, 2009-05-27)) to
allow the user to choose between the different patch formats.

Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 107 +--
 1 file changed, 104 insertions(+), 3 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index ac172c4..5f3c131 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -8,6 +8,12 @@
 #include exec_cmd.h
 #include parse-options.h
 #include dir.h
+#include run-command.h
+
+enum patch_format {
+   PATCH_FORMAT_UNKNOWN = 0,
+   PATCH_FORMAT_MBOX
+};
 
 struct am_state {
/* state directory path */
@@ -16,6 +22,9 @@ struct am_state {
/* current and last patch numbers, 1-indexed */
int cur;
int last;
+
+   /* number of digits in patch filename */
+   int prec;
 };
 
 /**
@@ -28,6 +37,8 @@ static void am_state_init(struct am_state *state, const char 
*dir)
 
assert(dir);
state-dir = xstrdup(dir);
+
+   state-prec = 4;
 }
 
 /**
@@ -117,13 +128,71 @@ static void am_destroy(const struct am_state *state)
 }
 
 /**
+ * Splits out individual email patches from `paths`, where each path is either
+ * a mbox file or a Maildir. Returns 0 on success, -1 on failure.
+ */
+static int split_mail_mbox(struct am_state *state, const char **paths)
+{
+   struct child_process cp = CHILD_PROCESS_INIT;
+   struct strbuf last = STRBUF_INIT;
+
+   cp.git_cmd = 1;
+   argv_array_push(cp.args, mailsplit);
+   argv_array_pushf(cp.args, -d%d, state-prec);
+   argv_array_pushf(cp.args, -o%s, state-dir);
+   argv_array_push(cp.args, -b);
+   argv_array_push(cp.args, --);
+   argv_array_pushv(cp.args, paths);
+
+   if (capture_command(cp, last, 8))
+   return -1;
+
+   state-cur = 1;
+   state-last = strtol(last.buf, NULL, 10);
+
+   return 0;
+}
+
+/**
+ * Splits a list of files/directories into individual email patches. Each path
+ * in `paths` must be a file/directory that is formatted according to
+ * `patch_format`.
+ *
+ * Once split out, the individual email patches will be stored in the state
+ * directory, with each patch's filename being its index, padded to state-prec
+ * digits.
+ *
+ * state-cur will be set to the index of the first mail, and state-last will
+ * be set to the index of the last mail.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int split_mail(struct am_state *state, enum patch_format patch_format,
+   const char **paths)
+{
+   switch (patch_format) {
+   case PATCH_FORMAT_MBOX:
+   return split_mail_mbox(state, paths);
+   default:
+   die(BUG: invalid patch_format);
+   }
+   return -1;
+}
+
+/**
  * Setup a new am session for applying patches
  */
-static void am_setup(struct am_state *state)
+static void am_setup(struct am_state *state, enum patch_format patch_format,
+   const char **paths)
 {
if (mkdir(state-dir, 0777)  0  errno != EEXIST)
die_errno(_(failed to create directory '%s'), state-dir);
 
+   if (split_mail(state, patch_format, paths)  0) {
+   am_destroy(state);
+   die(_(Failed to split patches.));
+   }
+
/*
 * NOTE: Since the next and last files determine if an am_state
 * session is in progress, they should be written last.
@@ -159,9 +228,25 @@ static void am_run(struct am_state *state)
am_destroy(state);
 }
 
+/**
+ * parse_options() callback that validates and sets opt-value to the
+ * PATCH_FORMAT_* enum value corresponding to `arg`.
+ */
+static int parse_opt_patchformat(const struct option *opt, const char *arg, 
int unset)
+{
+   int *opt_value = opt-value;
+
+   if (!strcmp(arg, mbox))
+   *opt_value = PATCH_FORMAT_MBOX;
+   else
+   return error(_(Invalid value for --patch-format: %s), arg);
+   return 0;
+}
+
 int cmd_am(int argc, const char **argv, const char *prefix)
 {
struct am_state state;
+   int patch_format = PATCH_FORMAT_UNKNOWN;
 
const char * const usage[] = {
N_(git am [options] [(mbox|Maildir)...]),
@@ -169,6 +254,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
};
 
struct option options[] = {
+   OPT_CALLBACK(0, patch-format, patch_format, N_(format),
+   N_(format the patch(es) are in),
+   parse_opt_patchformat),
OPT_END()
};
 
@@ -195,8 +283,21 @@ int cmd_am(int argc, const char **argv, const char 

[PATCH v6 06/45] builtin-am: auto-detect mbox patches

2015-07-19 Thread Paul Tan
Since 15ced75 (git-am foreign patch support: autodetect some patch
formats, 2009-05-27), git-am.sh is able to autodetect mbox, stgit and
mercurial patches through heuristics.

Re-implement support for autodetecting mbox/maildir files in
builtin/am.c.

RFC 2822 requires that lines are terminated by \r\n. To support this,
implement strbuf_getline_crlf(), which will remove both '\n' and \r\n
from the end of the line.

Helped-by: Junio C Hamano gits...@pobox.com
Helped-by: Eric Sunshine sunsh...@sunshineco.com
Helped-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 109 +++
 1 file changed, 109 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index 5f3c131..c12566a 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -10,6 +10,21 @@
 #include dir.h
 #include run-command.h
 
+/**
+ * Like strbuf_getline(), but treats both '\n' and \r\n as line terminators.
+ */
+static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
+{
+   if (strbuf_getwholeline(sb, fp, '\n'))
+   return EOF;
+   if (sb-buf[sb-len - 1] == '\n') {
+   strbuf_setlen(sb, sb-len - 1);
+   if (sb-len  0  sb-buf[sb-len - 1] == '\r')
+   strbuf_setlen(sb, sb-len - 1);
+   }
+   return 0;
+}
+
 enum patch_format {
PATCH_FORMAT_UNKNOWN = 0,
PATCH_FORMAT_MBOX
@@ -128,6 +143,92 @@ static void am_destroy(const struct am_state *state)
 }
 
 /**
+ * Determines if the file looks like a piece of RFC2822 mail by grabbing all
+ * non-indented lines and checking if they look like they begin with valid
+ * header field names.
+ *
+ * Returns 1 if the file looks like a piece of mail, 0 otherwise.
+ */
+static int is_mail(FILE *fp)
+{
+   const char *header_regex = ^[!-9;-~]+:;
+   struct strbuf sb = STRBUF_INIT;
+   regex_t regex;
+   int ret = 1;
+
+   if (fseek(fp, 0L, SEEK_SET))
+   die_errno(_(fseek failed));
+
+   if (regcomp(regex, header_regex, REG_NOSUB | REG_EXTENDED))
+   die(invalid pattern: %s, header_regex);
+
+   while (!strbuf_getline_crlf(sb, fp)) {
+   if (!sb.len)
+   break; /* End of header */
+
+   /* Ignore indented folded lines */
+   if (*sb.buf == '\t' || *sb.buf == ' ')
+   continue;
+
+   /* It's a header if it matches header_regex */
+   if (regexec(regex, sb.buf, 0, NULL, 0)) {
+   ret = 0;
+   goto done;
+   }
+   }
+
+done:
+   regfree(regex);
+   strbuf_release(sb);
+   return ret;
+}
+
+/**
+ * Attempts to detect the patch_format of the patches contained in `paths`,
+ * returning the PATCH_FORMAT_* enum value. Returns PATCH_FORMAT_UNKNOWN if
+ * detection fails.
+ */
+static int detect_patch_format(const char **paths)
+{
+   enum patch_format ret = PATCH_FORMAT_UNKNOWN;
+   struct strbuf l1 = STRBUF_INIT;
+   FILE *fp;
+
+   /*
+* We default to mbox format if input is from stdin and for directories
+*/
+   if (!*paths || !strcmp(*paths, -) || is_directory(*paths))
+   return PATCH_FORMAT_MBOX;
+
+   /*
+* Otherwise, check the first few lines of the first patch, starting
+* from the first non-blank line, to try to detect its format.
+*/
+
+   fp = xfopen(*paths, r);
+
+   while (!strbuf_getline_crlf(l1, fp)) {
+   if (l1.len)
+   break;
+   }
+
+   if (starts_with(l1.buf, From ) || starts_with(l1.buf, From: )) {
+   ret = PATCH_FORMAT_MBOX;
+   goto done;
+   }
+
+   if (l1.len  is_mail(fp)) {
+   ret = PATCH_FORMAT_MBOX;
+   goto done;
+   }
+
+done:
+   fclose(fp);
+   strbuf_release(l1);
+   return ret;
+}
+
+/**
  * Splits out individual email patches from `paths`, where each path is either
  * a mbox file or a Maildir. Returns 0 on success, -1 on failure.
  */
@@ -185,6 +286,14 @@ static int split_mail(struct am_state *state, enum 
patch_format patch_format,
 static void am_setup(struct am_state *state, enum patch_format patch_format,
const char **paths)
 {
+   if (!patch_format)
+   patch_format = detect_patch_format(paths);
+
+   if (!patch_format) {
+   fprintf_ln(stderr, _(Patch format detection failed.));
+   exit(128);
+   }
+
if (mkdir(state-dir, 0777)  0  errno != EEXIST)
die_errno(_(failed to create directory '%s'), state-dir);
 
-- 
2.5.0.rc2.110.gb39b692

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


[PATCH v6 07/45] builtin-am: extract patch and commit info with git-mailinfo

2015-07-19 Thread Paul Tan
For the purpose of applying the patch and committing the results,
implement extracting the patch data, commit message and authorship from
an e-mail message using git-mailinfo.

git-mailinfo is run as a separate process, but ideally in the future,
we should be be able to access its functionality directly without
spawning a new process.

Helped-by: Junio C Hamano gits...@pobox.com
Helped-by: Jeff King p...@peff.net
Helped-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 builtin/am.c | 317 +++
 1 file changed, 317 insertions(+)

diff --git a/builtin/am.c b/builtin/am.c
index c12566a..63f0fa4 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -9,6 +9,23 @@
 #include parse-options.h
 #include dir.h
 #include run-command.h
+#include quote.h
+
+/**
+ * Returns 1 if the file is empty or does not exist, 0 otherwise.
+ */
+static int is_empty_file(const char *filename)
+{
+   struct stat st;
+
+   if (stat(filename, st)  0) {
+   if (errno == ENOENT)
+   return 1;
+   die_errno(_(could not stat %s), filename);
+   }
+
+   return !st.st_size;
+}
 
 /**
  * Like strbuf_getline(), but treats both '\n' and \r\n as line terminators.
@@ -38,6 +55,13 @@ struct am_state {
int cur;
int last;
 
+   /* commit metadata and message */
+   char *author_name;
+   char *author_email;
+   char *author_date;
+   char *msg;
+   size_t msg_len;
+
/* number of digits in patch filename */
int prec;
 };
@@ -62,6 +86,10 @@ static void am_state_init(struct am_state *state, const char 
*dir)
 static void am_state_release(struct am_state *state)
 {
free(state-dir);
+   free(state-author_name);
+   free(state-author_email);
+   free(state-author_date);
+   free(state-msg);
 }
 
 /**
@@ -112,6 +140,161 @@ static int read_state_file(struct strbuf *sb, const 
struct am_state *state,
 }
 
 /**
+ * Reads a KEY=VALUE shell variable assignment from `fp`, returning the VALUE
+ * as a newly-allocated string. VALUE must be a quoted string, and the KEY must
+ * match `key`. Returns NULL on failure.
+ *
+ * This is used by read_author_script() to read the GIT_AUTHOR_* variables from
+ * the author-script.
+ */
+static char *read_shell_var(FILE *fp, const char *key)
+{
+   struct strbuf sb = STRBUF_INIT;
+   const char *str;
+
+   if (strbuf_getline(sb, fp, '\n'))
+   goto fail;
+
+   if (!skip_prefix(sb.buf, key, str))
+   goto fail;
+
+   if (!skip_prefix(str, =, str))
+   goto fail;
+
+   strbuf_remove(sb, 0, str - sb.buf);
+
+   str = sq_dequote(sb.buf);
+   if (!str)
+   goto fail;
+
+   return strbuf_detach(sb, NULL);
+
+fail:
+   strbuf_release(sb);
+   return NULL;
+}
+
+/**
+ * Reads and parses the state directory's author-script file, and sets
+ * state-author_name, state-author_email and state-author_date accordingly.
+ * Returns 0 on success, -1 if the file could not be parsed.
+ *
+ * The author script is of the format:
+ *
+ * GIT_AUTHOR_NAME='$author_name'
+ * GIT_AUTHOR_EMAIL='$author_email'
+ * GIT_AUTHOR_DATE='$author_date'
+ *
+ * where $author_name, $author_email and $author_date are quoted. We are strict
+ * with our parsing, as the file was meant to be eval'd in the old git-am.sh
+ * script, and thus if the file differs from what this function expects, it is
+ * better to bail out than to do something that the user does not expect.
+ */
+static int read_author_script(struct am_state *state)
+{
+   const char *filename = am_path(state, author-script);
+   FILE *fp;
+
+   assert(!state-author_name);
+   assert(!state-author_email);
+   assert(!state-author_date);
+
+   fp = fopen(filename, r);
+   if (!fp) {
+   if (errno == ENOENT)
+   return 0;
+   die_errno(_(could not open '%s' for reading), filename);
+   }
+
+   state-author_name = read_shell_var(fp, GIT_AUTHOR_NAME);
+   if (!state-author_name) {
+   fclose(fp);
+   return -1;
+   }
+
+   state-author_email = read_shell_var(fp, GIT_AUTHOR_EMAIL);
+   if (!state-author_email) {
+   fclose(fp);
+   return -1;
+   }
+
+   state-author_date = read_shell_var(fp, GIT_AUTHOR_DATE);
+   if (!state-author_date) {
+   fclose(fp);
+   return -1;
+   }
+
+   if (fgetc(fp) != EOF) {
+   fclose(fp);
+   return -1;
+   }
+
+   fclose(fp);
+   return 0;
+}
+
+/**
+ * Saves state-author_name, state-author_email and state-author_date in the
+ * state directory's author-script file.
+ */
+static void write_author_script(const struct am_state *state)
+{
+   struct strbuf sb = STRBUF_INIT;
+
+   strbuf_addstr(sb, GIT_AUTHOR_NAME=);

[PATCH v6 00/45] Make git-am a builtin

2015-07-19 Thread Paul Tan
This patch series depends on pt/pull-builtin.

This is a re-roll of [v5]. The changes are as follows:

* Compacted the struct am_state declaration, so there are no ugly newlines
  between every field.

* Removed unnecessary assert()s.

* Simplified if (x) free(x) to just free(x)

* Only alloc memory for lock_file just before calling hold_locked_index() to
  prevent memory leaks.

* Added a patch to re-implement 271440e (git-am: make it easier after fixing up
  an unapplicable patch., 2005-10-25).

Thanks Junio and Stefan for the reviews last round. Interdiff below.

Previous versions:

[WIP v1] http://thread.gmane.org/gmane.comp.version-control.git/270048
[WIP v2] http://thread.gmane.org/gmane.comp.version-control.git/271381
[WIP v3] http://thread.gmane.org/gmane.comp.version-control.git/271967
[v4] http://thread.gmane.org/gmane.comp.version-control.git/272876
[v5] http://thread.gmane.org/gmane.comp.version-control.git/273520

git-am is a commonly used command for applying a series of patches from a
mailbox to the current branch. Currently, it is implemented by the shell script
git-am.sh. However, compared to C, shell scripts have certain deficiencies:
they need to spawn a lot of processes, introduce a lot of dependencies and
cannot take advantage of git's internal caches.

This patch series rewrites git-am.sh into C builtin/am.c, and is part of my
GSoC project to rewrite git-pull and git-am into C builtins[1].

[1] https://gist.github.com/pyokagan/1b7b0d1f4dab6ba3cef1


Paul Tan (45):
  wrapper: implement xopen()
  wrapper: implement xfopen()
  builtin-am: implement skeletal builtin am
  builtin-am: implement patch queue mechanism
  builtin-am: split out mbox/maildir patches with git-mailsplit
  builtin-am: auto-detect mbox patches
  builtin-am: extract patch and commit info with git-mailinfo
  builtin-am: apply patch with git-apply
  builtin-am: implement committing applied patch
  builtin-am: refuse to apply patches if index is dirty
  builtin-am: implement --resolved/--continue
  builtin-am: don't parse mail when resuming
  builtin-am: implement --skip
  builtin-am: implement --abort
  builtin-am: reject patches when there's a session in progress
  builtin-am: implement -q/--quiet
  builtin-am: exit with user friendly message on failure
  builtin-am: implement -s/--signoff
  cache-tree: introduce write_index_as_tree()
  builtin-am: implement --3way, am.threeWay
  builtin-am: implement --rebasing mode
  builtin-am: bypass git-mailinfo when --rebasing
  builtin-am: handle stray state directory
  builtin-am: implement -u/--utf8
  builtin-am: implement -k/--keep, --keep-non-patch
  builtin-am: implement --[no-]message-id, am.messageid
  builtin-am: support --keep-cr, am.keepcr
  builtin-am: implement --[no-]scissors
  builtin-am: pass git-apply's options to git-apply
  builtin-am: implement --ignore-date
  builtin-am: implement --committer-date-is-author-date
  builtin-am: implement -S/--gpg-sign, commit.gpgsign
  builtin-am: invoke post-rewrite hook
  builtin-am: support automatic notes copying
  builtin-am: invoke applypatch-msg hook
  builtin-am: invoke pre-applypatch hook
  builtin-am: invoke post-applypatch hook
  builtin-am: rerere support
  builtin-am: support and auto-detect StGit patches
  builtin-am: support and auto-detect StGit series files
  builtin-am: support and auto-detect mercurial patches
  builtin-am: implement -i/--interactive
  builtin-am: implement legacy -b/--binary option
  builtin-am: check for valid committer ident
  builtin-am: remove redirection to git-am.sh

 Makefile|2 +-
 builtin.h   |1 +
 builtin/am.c| 2320 +++
 cache-tree.c|   29 +-
 cache-tree.h|1 +
 git-am.sh = contrib/examples/git-am.sh |0
 git-compat-util.h   |2 +
 git.c   |1 +
 wrapper.c   |   56 +
 9 files changed, 2399 insertions(+), 13 deletions(-)
 create mode 100644 builtin/am.c
 rename git-am.sh = contrib/examples/git-am.sh (100%)

diff --git a/builtin/am.c b/builtin/am.c
index c548129..1116304 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -119,38 +119,21 @@ struct am_state {
/* number of digits in patch filename */
int prec;
 
+   /* various operating modes and command line options */
int interactive;
-
int threeway;
-
int quiet;
-
int append_signoff;
-
int utf8;
-
-   /* one of the enum keep_type values */
-   int keep;
-
-   /* pass -m flag to git-mailinfo */
+   int keep; /* enum keep_type */
int message_id;
-
-   /* one of the enum scissors_type values */
-   int scissors;
-
+   int scissors; /* enum scissors_type */
struct argv_array git_apply_opts;
-
-   /* override error message when patch failure occurs */
const 

[PATCH v2 14/16] vcbuild/readme: Improve layout

2015-07-19 Thread Philip Oakley
Layout the 'either/or' with more white space to clarify
which alternatives are matched up.

A revised copy of the Msysgit msvc-build script which automates this
README is introduced in the next commit.

Signed-off-by: Philip Oakley philipoak...@iee.org
---
 compat/vcbuild/README | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/compat/vcbuild/README b/compat/vcbuild/README
index df8a657..ad8633e 100644
--- a/compat/vcbuild/README
+++ b/compat/vcbuild/README
@@ -3,20 +3,24 @@ The Steps of Build Git with VS2008
 1. You need the build environment, which contains the Git dependencies
to be able to compile, link and run Git with MSVC.
 
-   You can either use the binary repository:
+   You can either:
+  use the binary repository:
 
WWW: http://repo.or.cz/w/msvcgit.git
Git: git clone git://repo.or.cz/msvcgit.git
Zip: http://repo.or.cz/w/msvcgit.git?a=snapshot;h=master;sf=zip
 
-   and call the setup_32bit_env.cmd batch script before compiling Git,
-   (see repo/package README for details), or the source repository:
+  and call the setup_32bit_env.cmd batch script before compiling Git,
+ (see repo/package README for details),
+
+   or:
+  use the source repository:
 
WWW: http://repo.or.cz/w/gitbuild.git
Git: git clone git://repo.or.cz/gitbuild.git
Zip: (None, as it's a project with submodules)
 
-   and build the support libs as instructed in that repo/package.
+ and build the support libs as instructed in that repo/package.
 
 2. Ensure you have the msysgit environment in your path, so you have
GNU Make, bash and perl available.
@@ -33,15 +37,20 @@ The Steps of Build Git with VS2008
make common-cmds.h
to generate the common-cmds.h file needed to compile git.
 
-4. Then either build Git with the GNU Make Makefile in the Git projects
-   root
+4. Then either
+
+ build Git with the GNU Make Makefile in the Git projects root
make MSVC=1
-   or generate Visual Studio solution/projects (.sln/.vcproj) with the
+   or
+
+   generate Visual Studio solution/projects (.sln/.vcproj) with the
command
perl contrib/buildsystems/generate -g Vcproj
and open and build the solution with the IDE
devenv git.sln /useenv
-   or build with the IDE build engine directly from the command line
+ or
+
+   build with the IDE build engine directly from the command line
devenv git.sln /useenv /build Release|Win32
The /useenv option is required, so Visual Studio picks up the
environment variables for the support libraries required to build
-- 
2.4.2.windows.1.5.gd32afb6

--
To unsubscribe from this list: send the line 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/3] Fix sed usage in tests to work around broken xpg4/sed on Solaris

2015-07-19 Thread Johannes Sixt

Am 19.07.2015 um 20:00 schrieb Ben Walton:

-   sed -e s/CHANGE_ME/change_me/ file file+ 
+   perl -pne s/CHANGE_ME/change_me/ file file+ 


Did you mean '-lpe' or better '-pe' here?

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


[PATCH v3 02/12] t4150: am fails if index is dirty

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07), git-am
will ensure that the index is clean before applying the patch. This is
to prevent changes unrelated to the patch from being committed.

Add a test for this check.

Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t4150-am.sh | 12 
 1 file changed, 12 insertions(+)

diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 264f53f..a85e06a 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -154,6 +154,18 @@ test_expect_success 'am applies patch correctly' '
test $(git rev-parse second^) = $(git rev-parse HEAD^)
 '
 
+test_expect_success 'am fails if index is dirty' '
+   test_when_finished rm -f dirtyfile 
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout first 
+   echo dirtyfile dirtyfile 
+   git add dirtyfile 
+   test_must_fail git am patch1 
+   test_path_is_dir .git/rebase-apply 
+   test_cmp_rev first HEAD
+'
+
 test_expect_success 'am applies patch e-mail not in a mbox' '
rm -fr .git/rebase-apply 
git reset --hard 
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 07/12] t4150: am with applypatch-msg hook

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07), git-am
will invoke the applypatch-msg hooks just after extracting the patch
message. If the applypatch-msg hook exits with a non-zero status, git-am
abort before even applying the patch to the index.

Add tests for this hook.

Helped-by: Junio C Hamano gits...@pobox.com
Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t4150-am.sh | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index c1ec4d5..7878e32 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -199,6 +199,41 @@ test_expect_success 'am applies patch e-mail with 
preceding whitespace' '
test $(git rev-parse second^) = $(git rev-parse HEAD^)
 '
 
+test_expect_success 'am with applypatch-msg hook' '
+   test_when_finished rm -f .git/hooks/applypatch-msg 
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout first 
+   mkdir -p .git/hooks 
+   write_script .git/hooks/applypatch-msg -\EOF 
+   cat $1 actual-msg 
+   echo hook-message $1
+   EOF
+   git am patch1 
+   test_path_is_missing .git/rebase-apply 
+   git diff --exit-code second 
+   echo hook-message expected 
+   git log -1 --format=format:%B actual 
+   test_cmp expected actual 
+   git log -1 --format=format:%B second expected 
+   test_cmp expected actual-msg
+'
+
+test_expect_success 'am with failing applypatch-msg hook' '
+   test_when_finished rm -f .git/hooks/applypatch-msg 
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout first 
+   mkdir -p .git/hooks 
+   write_script .git/hooks/applypatch-msg -\EOF 
+   exit 1
+   EOF
+   test_must_fail git am patch1 
+   test_path_is_dir .git/rebase-apply 
+   git diff --exit-code first 
+   test_cmp_rev first HEAD
+'
+
 test_expect_success 'setup: new author and committer' '
GIT_AUTHOR_NAME=Another Thor 
GIT_AUTHOR_EMAIL=a.t...@example.com 
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 05/12] t4150: am --resolved fails if index has no changes

2015-07-19 Thread Paul Tan
Since 6d28644 (git-am: do not allow empty commits by mistake.,
2006-02-23), git-am --resolved will check to see if the index has any
changes to prevent the user from creating an empty commit by mistake.

Add a test for this.

Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t4150-am.sh | 12 
 1 file changed, 12 insertions(+)

diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index c350967..430ae71 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -425,6 +425,18 @@ test_expect_success 'am --resolved works' '
test_cmp expected another
 '
 
+test_expect_success 'am --resolved fails if index has no changes' '
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout lorem2^^ 
+   test_must_fail git am lorem-move.patch 
+   test_path_is_dir .git/rebase-apply 
+   test_cmp_rev lorem2^^ HEAD 
+   test_must_fail git am --resolved 
+   test_path_is_dir .git/rebase-apply 
+   test_cmp_rev lorem2^^ HEAD
+'
+
 test_expect_success 'am takes patches from a Pine mailbox' '
rm -fr .git/rebase-apply 
git reset --hard 
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 00/12] Improve git-am test coverage

2015-07-19 Thread Paul Tan
This is a very minor re-roll of [v2] that adds in the missing !MINGW prereq in
t3901.  Thanks Johannes Schindelin and Johannes Sixt for the reviews last
round. Interdiff below.

Previous versions:

[v1] http://thread.gmane.org/gmane.comp.version-control.git/273254
[v2] http://thread.gmane.org/gmane.comp.version-control.git/273507

Increase test coverage of git-am.sh to help prevent regressions that could
arise from the rewrite of git-am.sh to C. This patch series, along with
pt/am-foreign, improved test coverage as measured by kcov from 56.5%[1] to
67.3%[2].

No tests for git-am's interactive mode, though, as test_terminal does not seem
to attach a pseudo-tty to stdin(?), thus making git-am's test -t 0 check
fail.

This is part of my GSoC project to rewrite git-am.sh to a C builtin[3].

[1] 
http://pyokagan.github.io/git/20150430132408-a75942b//kcov-merged/git-am.eb79278e.html
[2] 
http://pyokagan.github.io/git/20150702173751-2fdae08//kcov-merged/git-am.eb79278e.html
[3] https://gist.github.com/pyokagan/1b7b0d1f4dab6ba3cef1


Paul Tan (12):
  t4150: am.messageid really adds the message id
  t4150: am fails if index is dirty
  t4151: am --abort will keep dirty index intact
  t4150: am refuses patches when paused
  t4150: am --resolved fails if index has no changes
  t4150: am --resolved fails if index has unmerged entries
  t4150: am with applypatch-msg hook
  t4150: am with pre-applypatch hook
  t4150: am with post-applypatch hook
  t4150: tests for am --[no-]scissors
  t3418: non-interactive rebase --continue with rerere enabled
  t3901: test git-am encoding conversion

 t/t3418-rebase-continue.sh |  19 
 t/t3901-i18n-patch.sh  |  62 +
 t/t4150-am.sh  | 217 +
 t/t4151-am-abort.sh|  15 
 4 files changed, 313 insertions(+)

diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh
index b49bdb7..509084e 100755
--- a/t/t3901-i18n-patch.sh
+++ b/t/t3901-i18n-patch.sh
@@ -262,7 +262,7 @@ test_expect_success 'am (U/U)' '
check_encoding 2
 '
 
-test_expect_success 'am (L/L)' '
+test_expect_success !MINGW 'am (L/L)' '
# Apply ISO-8859-1 patches with ISO-8859-1 commitencoding
git config i18n.commitencoding ISO8859-1 
. $TEST_DIRECTORY/t3901-8859-1.txt 

-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 08/12] t4150: am with pre-applypatch hook

2015-07-19 Thread Paul Tan
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07),
git-am.sg will invoke the pre-applypatch hook after applying the patch
to the index, but before a commit is made. Should the hook exit with a
non-zero status, git am will exit.

Add tests for this hook.

Helped-by: Junio C Hamano gits...@pobox.com
Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t4150-am.sh | 33 +
 1 file changed, 33 insertions(+)

diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 7878e32..957c63c 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -234,6 +234,39 @@ test_expect_success 'am with failing applypatch-msg hook' '
test_cmp_rev first HEAD
 '
 
+test_expect_success 'am with pre-applypatch hook' '
+   test_when_finished rm -f .git/hooks/pre-applypatch 
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout first 
+   mkdir -p .git/hooks 
+   write_script .git/hooks/pre-applypatch -\EOF 
+   git diff first diff.actual
+   exit 0
+   EOF
+   git am patch1 
+   test_path_is_missing .git/rebase-apply 
+   git diff --exit-code second 
+   test_cmp_rev second HEAD 
+   git diff first..second diff.expected 
+   test_cmp diff.expected diff.actual
+'
+
+test_expect_success 'am with failing pre-applypatch hook' '
+   test_when_finished rm -f .git/hooks/pre-applypatch 
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout first 
+   mkdir -p .git/hooks 
+   write_script .git/hooks/pre-applypatch -\EOF 
+   exit 1
+   EOF
+   test_must_fail git am patch1 
+   test_path_is_dir .git/rebase-apply 
+   git diff --exit-code second 
+   test_cmp_rev first HEAD
+'
+
 test_expect_success 'setup: new author and committer' '
GIT_AUTHOR_NAME=Another Thor 
GIT_AUTHOR_EMAIL=a.t...@example.com 
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 03/12] t4151: am --abort will keep dirty index intact

2015-07-19 Thread Paul Tan
Since 7b3b7e3 (am --abort: keep unrelated commits since the last failure
and warn, 2010-12-21), git-am --abort will not touch the index if on the
previous invocation, git-am failed because the index is dirty. This is
to ensure that the user's modifications to the index are not discarded.

Add a test for this.

Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t4151-am-abort.sh | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh
index 833e7b2..05bdc3e 100755
--- a/t/t4151-am-abort.sh
+++ b/t/t4151-am-abort.sh
@@ -95,6 +95,21 @@ test_expect_success 'am --abort will keep the local commits 
intact' '
test_cmp expect actual
 '
 
+test_expect_success 'am --abort will keep dirty index intact' '
+   git reset --hard initial 
+   echo dirtyfile dirtyfile 
+   cp dirtyfile dirtyfile.expected 
+   git add dirtyfile 
+   test_must_fail git am 0001-*.patch 
+   test_cmp_rev initial HEAD 
+   test_path_is_file dirtyfile 
+   test_cmp dirtyfile.expected dirtyfile 
+   git am --abort 
+   test_cmp_rev initial HEAD 
+   test_path_is_file dirtyfile 
+   test_cmp dirtyfile.expected dirtyfile
+'
+
 test_expect_success 'am -3 stops on conflict on unborn branch' '
git checkout -f --orphan orphan 
git reset 
-- 
2.5.0.rc2.110.gf2a5fc6

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


[PATCH v3 04/12] t4150: am refuses patches when paused

2015-07-19 Thread Paul Tan
Since c95b138 (Fix git-am safety checks, 2006-09-15), when there is a
session in progress, git-am will check the command-line arguments and
standard input to ensure that the user does not pass it any patches.

Add a test for this.

Reviewed-by: Stefan Beller sbel...@google.com
Reviewed-by: Johannes Schindelin johannes.schinde...@gmx.de
Signed-off-by: Paul Tan pyoka...@gmail.com
---
 t/t4150-am.sh | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index a85e06a..c350967 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -397,6 +397,20 @@ test_expect_success 'am --abort removes a stray directory' 
'
test_path_is_missing .git/rebase-apply
 '
 
+test_expect_success 'am refuses patches when paused' '
+   rm -fr .git/rebase-apply 
+   git reset --hard 
+   git checkout lorem2^^ 
+
+   test_must_fail git am lorem-move.patch 
+   test_path_is_dir .git/rebase-apply 
+   test_cmp_rev lorem2^^ HEAD 
+
+   test_must_fail git am lorem-move.patch 
+   test_path_is_dir .git/rebase-apply 
+   test_cmp_rev lorem2^^ HEAD
+'
+
 test_expect_success 'am --resolved works' '
echo goodbye expected 
rm -fr .git/rebase-apply 
-- 
2.5.0.rc2.110.gf2a5fc6

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


  1   2   >