git_diff_to_json.sh 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #!/bin/bash
  2. # Copyright 2021 Google LLC
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. # USAGE: git diff -U0 [base_commit] HEAD | get_diff_lines.sh
  16. #
  17. # This will generate a JSON output of changed files and their newly added
  18. # lines.
  19. oIFS=$IFS
  20. json_output="["
  21. # Concatenate files and line indices into a JSON file.
  22. concatenate() {
  23. local path=$1
  24. shift
  25. IFS=","
  26. local lines=$@
  27. echo "{\"file\": \"${path}\", \"added_lines\": [${lines[*]}]}"
  28. IFS=$oIFS
  29. }
  30. diff-lines() {
  31. local path=
  32. local line=
  33. local lines=()
  34. while read; do
  35. esc='\033'
  36. # Skip lines starting with "---". e.g. "--- a/.github/workflows/database.yml".
  37. # $REPLY, containing one line at a time, here and below are the default variable
  38. # of `read`.
  39. if [[ "$REPLY" =~ ---\ (a/)?.* ]]; then
  40. continue
  41. # Detect new changed files from `git diff`. e.g. "+++ b/.github/workflows/combine.yml".
  42. elif [[ "$REPLY" =~ ^\+\+\+\ (b/)?([^[:blank:]$esc]+).* ]]; then
  43. # Add the last changed file and its indices of added line to the output variable.
  44. if [ ${#lines[@]} -ne 0 ]; then
  45. json_output+="$(concatenate "${path}" ${lines[@]}),"
  46. fi
  47. # Refresh the array of line indices and file path for the new changed file.
  48. lines=()
  49. path=${BASH_REMATCH[2]}
  50. # Detect the started line index of a changed file, e.g. "@@ -53,0 +54,24 @@ jobs:" where "54" will be fetched.
  51. elif [[ "$REPLY" =~ @@\ -[0-9]+(,[0-9]+)?\ \+([0-9]+)(,[0-9]+)?\ @@.* ]]; then
  52. line=${BASH_REMATCH[2]}
  53. # Detect newly added lines. e.g. "+ storage-combine-integration:"
  54. elif [[ "$REPLY" =~ ^($esc\[[0-9;]+m)*([+]) ]]; then
  55. lines+=($line)
  56. ((line++))
  57. fi
  58. done
  59. json_output+=$(concatenate "${path}" ${lines[@]} )
  60. }
  61. diff-lines
  62. json_output="${json_output}]"
  63. echo $json_output