Class: I18nContextGenerator::GitDiff

Inherits:
Object
  • Object
show all
Includes:
GitDiffXmlChanges
Defined in:
lib/i18n_context_generator/git_diff.rb

Overview

Parses git diff to extract changed translation keys

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_ref: 'main', head_ref: 'HEAD') ⇒ GitDiff

Returns a new instance of GitDiff.



18
19
20
21
# File 'lib/i18n_context_generator/git_diff.rb', line 18

def initialize(base_ref: 'main', head_ref: 'HEAD')
  @base_ref = base_ref
  @head_ref = head_ref
end

Class Method Details

.available?Boolean

Check if we're in a git repository

Returns:

  • (Boolean)


90
91
92
# File 'lib/i18n_context_generator/git_diff.rb', line 90

def self.available?
  system('git', 'rev-parse', '--git-dir', out: File::NULL, err: File::NULL)
end

Instance Method Details

#base_ref_exists?Boolean

Check if the base ref exists

Returns:

  • (Boolean)


95
96
97
# File 'lib/i18n_context_generator/git_diff.rb', line 95

def base_ref_exists?
  system('git', 'rev-parse', '--verify', @base_ref, out: File::NULL, err: File::NULL)
end

#changed_key_locations(translation_paths) ⇒ Hash{Array(String, String) => Array<ChangedLocation>}

Get changed translation keys together with the exact changed lines that produced them. Keys are scoped by translation file so duplicate keys in different files remain distinct.

Returns:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/i18n_context_generator/git_diff.rb', line 34

def changed_key_locations(translation_paths)
  translation_paths.each_with_object({}) do |path, changes|
    next unless File.exist?(path)

    diff_output = git_diff_for_path(path)
    next if diff_output.empty?

    normalized_path = Pathname.new(path).cleanpath.to_s
    base_content, head_content = revision_contents(path) if revision_contents_needed?(path, diff_output)
    head_content ||= File.binread(path)
    key_locations = case File.extname(path).downcase
                    when '.strings'
                      extract_strings_key_locations(
                        diff_output,
                        normalized_path,
                        base_content: base_content,
                        head_content: head_content
                      )
                    when '.xcstrings'
                      extract_xcstrings_key_locations(
                        diff_output,
                        normalized_path,
                        base_content: base_content,
                        head_content: head_content
                      )
                    when '.xml'
                      extract_xml_key_locations(
                        diff_output,
                        normalized_path,
                        base_content: base_content,
                        head_content: head_content
                      )
                    else
                      {}
                    end
    key_locations.each do |key, locations|
      changes[[normalized_path, key]] = locations
    end
  end
end

#changed_keys(translation_paths) ⇒ Set<String>

Get keys that were added or modified since the base ref

Parameters:

  • translation_paths (Array<String>)

    paths to translation files

Returns:

  • (Set<String>)

    set of changed keys



26
27
28
# File 'lib/i18n_context_generator/git_diff.rb', line 26

def changed_keys(translation_paths)
  changed_key_locations(translation_paths).each_key.to_set(&:last)
end

#changed_lines(source_paths) ⇒ Hash{String => Set<Integer>}

Get changed line numbers in source files since the base ref.

Parameters:

  • source_paths (Array<String>)

    paths to source files or directories

Returns:

  • (Hash{String => Set<Integer>})

    changed line numbers keyed by file path



78
79
80
81
82
83
84
85
86
87
# File 'lib/i18n_context_generator/git_diff.rb', line 78

def changed_lines(source_paths)
  source_paths.each_with_object(Hash.new { |h, k| h[k] = Set.new }) do |path, line_map|
    next unless File.exist?(path)

    diff_output = git_diff_for_path(path)
    next if diff_output.empty?

    merge_line_maps!(line_map, extract_changed_lines(diff_output, path))
  end
end

#head_ref_exists?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/i18n_context_generator/git_diff.rb', line 99

def head_ref_exists?
  system('git', 'rev-parse', '--verify', @head_ref, out: File::NULL, err: File::NULL)
end