class GitDiffService
Constants
- ALLOWED_EXTENSION
- EXCLUDE_ROOT_FOLDERS
restrict scope: for Rails app exclude autogenerated code and omit any files except .rb
- PATTERN_MATCH
Public Class Methods
call(diff_lines, exclude_folders = [])
click to toggle source
# File lib/git_diff_service.rb, line 8 def call(diff_lines, exclude_folders = []) @diff_lines = diff_lines # TO-DO: support @only_folders @exclude_folders = exclude_folders + EXCLUDE_ROOT_FOLDERS patch_pos_start = lines_with_file_paths.map { |line| patch_start_pos(line) } # array with start and end positions for each patch @patches_pos = patch_pos_start.zip(patch_end_pos(patch_pos_start)) slice_diff @patches = @patches.select { |patch| allowed_patch?(patch) } @diff_data = @patches.map { |patch| fname_diff(patch) } @diff_data += @patches.map { |patch| class_diff(patch) } @diff_data.compact end
Private Class Methods
allowed_patch?(patch)
click to toggle source
# File lib/git_diff_service.rb, line 30 def allowed_patch?(patch) fname_string = patch.first extension_allowed = extract_file_paths(fname_string).last.end_with?(ALLOWED_EXTENSION) folder_allowed = !extract_file_paths(fname_string).last.start_with?(*@exclude_folders) extension_allowed && folder_allowed end
class_diff(patch)
click to toggle source
# File lib/git_diff_service.rb, line 83 def class_diff(patch) return { old_name: old_class_name(patch), new_name: new_class_name(patch), status: :renamed_class } if class_renamed?(patch) end
class_renamed?(patch)
click to toggle source
# File lib/git_diff_service.rb, line 50 def class_renamed?(patch) patch.select { |line| line.start_with?('-class') }.any? && patch.select { |line| line.start_with?('+class') }.any? end
deleted_file?(patch)
click to toggle source
# File lib/git_diff_service.rb, line 42 def deleted_file?(patch) patch.select { |line| line.start_with?('deleted file mode ') }.any? end
extract_file_paths(line)
click to toggle source
# File lib/git_diff_service.rb, line 106 def extract_file_paths(line) # diff --git a/project_v1/README.md b/project_v2/README2.md line = line.delete_prefix('diff --git ') path1, path2 = line.split(' ') [path1, path2].map! { |path| file_path(path) } end
file_path(str)
click to toggle source
# File lib/git_diff_service.rb, line 113 def file_path(str) # a/project_v1/README.md -> project_v1/README.md prefix, *path_parts = str.split('/') path_parts.join('/') end
fname_diff(patch)
click to toggle source
# File lib/git_diff_service.rb, line 69 def fname_diff(patch) # first line in patch contains info about file path file_path_line = patch.first return { old_name: extract_file_paths(file_path_line).first, new_name: extract_file_paths(file_path_line).last, status: :renamed } if renamed_file?(patch) return { old_name: nil, new_name: extract_file_paths(file_path_line).last, status: :new } if new_file?(patch) return { old_name: extract_file_paths(file_path_line).first, new_name: nil, status: :deleted } if deleted_file?(patch) # changed file without renaming return { old_name: extract_file_paths(file_path_line).first, new_name: extract_file_paths(file_path_line).last, status: :changed } end
lines_with_file_paths()
click to toggle source
# File lib/git_diff_service.rb, line 98 def lines_with_file_paths @diff_lines.select { |line| line.scan(PATTERN_MATCH).any? } end
new_class_name(patch)
click to toggle source
# File lib/git_diff_service.rb, line 62 def new_class_name(patch) res = patch.select { |line| line.start_with?('+class') } return if res.empty? line = res.first line.split(' ').last.strip end
new_file?(patch)
click to toggle source
# File lib/git_diff_service.rb, line 38 def new_file?(patch) patch.select { |line| line.start_with?('new file mode ') }.any? end
old_class_name(patch)
click to toggle source
# File lib/git_diff_service.rb, line 55 def old_class_name(patch) res = patch.select { |line| line.start_with?('-class') } return if res.empty? line = res.first line.split(' ').last.strip end
patch_end_pos(patch_pos_start)
click to toggle source
end line index for current patch
# File lib/git_diff_service.rb, line 89 def patch_end_pos(patch_pos_start) end_line_pos = patch_pos_start.size - 1 pos_end = patch_pos_start.map.with_index do |pos, i| i == patch_pos_start.size - 1 ? @diff_lines.size - 1 : patch_pos_start[i + 1] - 1 end pos_end end
patch_start_pos(line)
click to toggle source
# File lib/git_diff_service.rb, line 102 def patch_start_pos(line) @diff_lines.index(line) end
renamed_file?(patch)
click to toggle source
# File lib/git_diff_service.rb, line 46 def renamed_file?(patch) patch.select { |line| line.start_with?('rename from ') }.any? end
slice_diff()
click to toggle source
split diff lines into separate patches for each file
# File lib/git_diff_service.rb, line 26 def slice_diff @patches = @patches_pos.map { |pos| @diff_lines[pos.first..pos.last] } end