Ruby Git Diff 行信息解析器

标签 ruby git-diff

如何解析 git diff 的输出并获取行信息(即已添加/修改了哪些行)?

我想要类似的东西

raw = `git diff`
parsed = Git.Diff.parse(raw)
parsed.each do |file|
  file.each do |line|
     puts "#{file.name} - #{line.number} - #{line.type}"
  end
end

编辑:

示例输出

[
  {
    "file": "path/to/file1",
    "lines": [
      { number: "1", type: "modified"},
      { number: "4", type: "deleted"},
      { number: "9", type: "added"}
    ]
  },
  {
    "file": "path/to/file2",
    "lines": [
      { number: "4", type: "modified"},
      { number: "5", type: "added"}
    ]
  }
]

最佳答案

您需要的是将输出正确分组到文件 block 中并保留所需的内容。

获取差异

您只需运行即可获取它

`git --diff`

需要什么线路?

  • 'diff --git' 开头的行,您可以从中获取文件名
  • '+ ' 开头的行是添加的行
  • '- ' 开头的行是已删除的行

如何对它们进行分组?

对于这些事情Enumerable#slice_before我想到了。

将其放在一起

我最终得到了这个原型(prototype):

raw_data = `git diff`.split("\n")

# Keep what is needed
clean_data = raw_data.select { |li|
  li.starts_with?('diff --git') ||
  li.starts_with?('- ') ||
  li.starts_with?('+ ')
}

# Group the by file
# [[file_1, line1, line2, line3], [file_2, line1]]
file_data = clean_data.slice_before { |li| li.starts_with?('diff --git') }

# This is the output format
output = Hash.new {|h,k| h[k] = { added: 0, removed: 0 } }

# Populate the output
file_data.each_with_object(output) do |f_data, memo|
  file, *file_info = f_data
  file = file.split(' b/').first.gsub('diff --git a/', '')
  file_info.each { |f_info|
    memo[file][f_info[0] == '+' ? :added : :removed] += 1
  }
end

输出示例

{
  "file_1" => { added: 1, removed: 12 },
  "file_2" => { added: 0, removed: 1 }
}

我相信它会变得更好:-)

关于Ruby Git Diff 行信息解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55164840/

相关文章:

git - 显示哪些文件在两次修订之间发生了变化

git - 我可以让 'git diff' 只显示行号和更改的文件名吗?

git - 为什么 `git range-diff` 不显示差异?

git - 如何让 Git diff 忽略版本号更改?

ruby-on-rails - 如何分析 Rails 应用程序的启动?

ruby - 从 Ruby 中的数组中获取第一组数字

ruby - ruby 中有类似于 perlform 的东西吗?

Ruby 没有常数值?

git - 本地存储库中的文件与源文件之间的区别

ruby-on-rails - 要求用户选择一个值