3

I am trying to generate a HTML-formatted output of the information provided by git log. I am a beginner in bash so while I searched the web and StackOverflow for help, I could well have missed the obvious.

What I am attempting is to output each commit statement (of the past 5 statements) in a div tag. Inside the div, I want a header that is the commit message subject, a paragraph that is the commit body and then a list of affected files with the type of change (created, deleted or modified). The script I have is close. It creates the header, it creates the list of files (without change type) and it can display the message body in one of two incorrect ways. Either the body has one word per line (as it is in the script below) or it has everything mashed onto one line (if I just echo the $lines variable without doing a for loop on it).

The file list has a similar issue. If I select "--name-status", it gives me the change type and the file name but on separate lines. That is why currently the name list looks up "--name-only". It works but it doesn't give me all the information I want.

Here is my current bash script:

revlist=$(git rev-list -n 5 HEAD)
(
  echo '<div>'
  for rev in $revlist
  do
    lines=$(git log -1 --pretty="format:%b" $rev) 
    files=$(git log -1 --pretty="format:" --name-only $rev)
    echo '<div><h2>'
    echo "$(git log -1 --pretty="%s" $rev)"
    echo '</h2>'
    for line in $lines
    do
      echo "$line <br />"
    done
    echo '<h3>Files Affected</h3><ul>'
    for file in $files
    do
      echo "<li>$file</li>"
    done
    echo '</ul></div>'
  done
  echo '</div>'
) > out.html

If I have a commit statement like this:

My Commit Header

commit line one

commit line two

and it affects the following files:

file1.txt

file2.txt

I'll get an output like so:

<div><h2>
My Commit Header
</h2>
commit <br />
line <br />
one <br />
commit <br />
line <br />
two <br />
<h3>Files Affected</h3><ul>
<li>file1.txt</li>
<li>file2.txt</li>
</ul></div>

Obviously that isn't what I want. So, my two questions are:

  1. How do I get the commit body to have one line per physical line (not one per space)?
  2. How do I get the change type associated with the file without the same issue as the commit message? Basically, I'm looking for "(M) file1.txt" or something similar.

It shouldn't affect anything, but I am running git on Windows.

Edit: Solution

Thanks to the help of VonC and those who commented, I was able to complete my script. I utilized the IFS on the first loop and I ran the second loop through a while statement instead of a for loop. Here is the working result:

revlist=$(git rev-list -n 5 HEAD)
(
  echo '<div>'
  for rev in $revlist
  do
    lines=$(git log -1 --pretty="format:%b" $rev) 
    files=$(git log -1 --pretty="format:" --name-status $rev)
    echo '<div><h2>'
    echo "$(git log -1 --pretty="%s" $rev)"
    echo '</h2>'
    IFS=$'\n'
    for line in $lines
    do
      echo "$line <br />"
    done
    unset IFS
    echo '<h3>Files Affected</h3><ul>'
    while read change file; do 
      if [ ${#file} -gt 0 ]
      then
        echo "<li>($change) $file </li>"; 
      fi
    done <<< "$files"
    echo '</ul></div><hr>'
  done
  echo '</div>'
) > out.html
Community
  • 1
  • 1
IAmTimCorey
  • 16,412
  • 5
  • 39
  • 75
  • 1
    em... just for curiosity, what makes you decide to write a bash script to generate html from scratch in windows? – Jason Hu Jul 02 '15 at 20:46
  • you can transform it into a better structure and continue processing: http://stackoverflow.com/questions/4600445/git-log-output-to-xml-json-or-yaml – Jason Hu Jul 02 '15 at 20:48
  • You should use lower-level (plumbing) commands rather than the porcelain command `git log`. If the Git devs decide to change the output of `git log`, that may break your parser. – jub0bs Jul 02 '15 at 20:56
  • "How do I get the commit body to have one line per physical line?" [BashFAQ/001](http://mywiki.wooledge.org/BashFAQ/001). – 4ae1e1 Jul 02 '15 at 21:09
  • @HuStmpHrrr - I decided to write a bash script because it was what I saw recommended (I'm doing this on a CI server). I saw the question you referenced but really didn't want to take two or three steps when I could take one. – IAmTimCorey Jul 03 '15 at 14:38
  • @Jubobs - I love the idea of making this more stable but I'm not sure how to accomplish what you are talking about. Can you point me in the right direction or give me an example? – IAmTimCorey Jul 03 '15 at 14:39
  • @4ae1e1 - Thanks for the link. I hadn't seen that. I tried what they were saying on my change and file name (which looks like "M file1.txt"). Here is what I did: $files|while read -r change file; do echo '
  • (%s) %s
  • ' "$change" "$file" done However, that does not work. It gives me the error "sh.exe": M: command not found" – IAmTimCorey Jul 03 '15 at 14:46