将 Git 日志格式化为 HTML

3
我正在尝试生成git log提供的信息的HTML格式输出。我是bash的新手,所以虽然我在网上和StackOverflow上搜索了帮助,但很可能会错过显而易见的东西。
我想要输出过去5个语句的每个提交语句到一个div标签中。在div内部,我想要一个作为提交消息主题的标题,一个作为提交正文的段落,然后是一个包含更改类型(已创建、已删除或已修改)的受影响文件列表。我现有的脚本已经接近目标。它可以创建标题,创建文件列表(没有更改类型),并且可以将消息正文以两种错误方式之一显示。如果我只是echo $lines变量而没有对其进行for循环,那么正文内容就会被压缩到一行中。
文件列表也有类似的问题。如果我选择“--name-status”,它会在不同的行上给出更改类型和文件名。这就是为什么当前名称列表查找“--name-only”的原因。这样做可以工作,但它不能提供我想要的所有信息。
以下是我的当前bash脚本:
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

如果我有一个像这样的提交语句:

我的提交标题

提交第一行

提交第二行

并且它影响了以下文件:

file1.txt

file2.txt

我将得到如下输出:

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

显然,这不是我想要的。所以,我的两个问题是:
  1. 如何使提交正文每行都是物理行(而不是每个空格一行)?
  2. 如何获得与文件相关联的更改类型而不出现与提交消息相同的问题?基本上,我正在寻找“(M) file1.txt”或类似的东西。
这不应该影响任何事情,但我在Windows上运行git。
编辑:解决方案
感谢VonC和那些评论者的帮助,我能够完成我的脚本。 我利用了第一个循环中的IFS,并通过while语句而不是for循环来运行第二个循环。 这是工作结果:
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

1
仅出于好奇,是什么促使您决定在Windows中编写Bash脚本来从头生成HTML? - Jason Hu
“如何让提交说明正文每行只有一个物理行?” [BashFAQ/001] (http://mywiki.wooledge.org/BashFAQ/001)。 - 4ae1e1
@HuStmpHrrr - 我决定编写一个 Bash 脚本,因为这是我看到的推荐方式(我在 CI 服务器上进行此操作)。我看到了你提到的问题,但实际上不想采取两三个步骤,只想采取一步。 - IAmTimCorey
@Jubobs - 我喜欢让这个更加稳定的想法,但我不确定如何实现你所说的。你能指点我正确的方向或给我一个例子吗? - IAmTimCorey
@4ae1e1 - 感谢提供的链接。我之前没有看到过。我尝试了他们在我的更改和文件名上所说的(看起来像“M file1.txt”)。这是我做的:$files|while read -r change file; do echo '<li>(%s) %s</li>' "$change" "$file" done 然而,这并不起作用。它给我报错:“sh.exe”:M:找不到命令”。 - IAmTimCorey
显示剩余2条评论
1个回答

2
这看起来像是 "如何在带有空格的'for'循环中读取完整行" 中提到的内容:
尝试将分隔符IFS设置为\n
IFS=$'\n'  
for line in $lines
do
  echo "$line <br />"
done

HuStmpHrrr在评论中提出了以下建议,与git日志的html格式化相关:

while read line; do 
  echo "$line <br />"; 
done <<< "$lines"

这绝对解决了问题#1。非常好的发现。我没有意识到你可以设置IFS。现在我仍然需要处理文件(在文件名旁边获取更改类型)。如果我只是将--name-only修改为--name-status,我会得到更改类型,一个空格,然后是文件名。我很想能够稍微格式化一下,所以我想单独处理文件名和更改类型。有没有办法将该行解析成两个变量? - IAmTimCorey
有没有办法将这一行解析成两个变量?这就是awk应该做的(例如和说明:https://dev59.com/1Gkw5IYBdhLWcg3wdKXD) - VonC
提供另一个技巧:while read line; do echo "$line <br />"; done <<< “$lines”。 引号包裹着lines是必需的。 - Jason Hu
1
@BiggsTRC 关于“解析为两个变量”的事情,我不知道你的意思,但这里有一个说明:while read a b; do echo a= $a b= $b; done <<< "$t"。只需尝试调整 IFS。 - Jason Hu
@HuStmpHrrr 不错的变化。我已经将它包含在答案中以增加可见性。 - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接