defmastership 1.0.17 → 1.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +22 -10
  3. data/Gemfile +51 -1
  4. data/Rakefile +16 -61
  5. data/bin/defmastership +9 -6
  6. data/config/mutant.yml +23 -3
  7. data/defmastership.gemspec +0 -10
  8. data/features/definition_checksum.feature +31 -1
  9. data/features/export.feature +43 -1
  10. data/features/rename_included_files.feature +28 -0
  11. data/lib/defmastership/batch_modifier.rb +17 -12
  12. data/lib/defmastership/change_ref_modifier.rb +88 -6
  13. data/lib/defmastership/comment_filter.rb +1 -1
  14. data/lib/defmastership/constants.rb +5 -4
  15. data/lib/defmastership/csv_formatter.rb +16 -12
  16. data/lib/defmastership/csv_formatter_body.rb +18 -15
  17. data/lib/defmastership/csv_formatter_header.rb +1 -1
  18. data/lib/defmastership/definition.rb +58 -19
  19. data/lib/defmastership/document.rb +109 -74
  20. data/lib/defmastership/matching_line.rb +17 -0
  21. data/lib/defmastership/modifier.rb +42 -0
  22. data/lib/defmastership/modifier_factory.rb +12 -0
  23. data/lib/defmastership/parsing_state.rb +15 -9
  24. data/lib/defmastership/rename_included_files_modifier.rb +172 -5
  25. data/lib/defmastership/set_join_hack.rb +11 -0
  26. data/lib/defmastership/update_def_checksum_modifier.rb +8 -13
  27. data/lib/defmastership/update_def_modifier.rb +49 -0
  28. data/lib/defmastership/update_def_version_modifier.rb +56 -15
  29. data/lib/defmastership/version.rb +1 -1
  30. data/lib/defmastership.rb +1 -6
  31. data/spec/spec_helper.rb +3 -1
  32. data/spec/unit/def_mastership/batch_modifier_spec.rb +38 -36
  33. data/spec/unit/def_mastership/change_ref_modifier_spec.rb +196 -51
  34. data/spec/unit/def_mastership/csv_formatter_body_spec.rb +60 -31
  35. data/spec/unit/def_mastership/csv_formatter_header_spec.rb +1 -1
  36. data/spec/unit/def_mastership/csv_formatter_spec.rb +79 -87
  37. data/spec/unit/def_mastership/definition_parser_spec.rb +1 -1
  38. data/spec/unit/def_mastership/definition_spec.rb +16 -6
  39. data/spec/unit/def_mastership/document_spec.rb +81 -38
  40. data/spec/unit/def_mastership/matching_line_spec.rb +37 -0
  41. data/spec/unit/def_mastership/modifier_factory_spec.rb +37 -0
  42. data/spec/unit/def_mastership/modifier_spec.rb +83 -0
  43. data/spec/unit/def_mastership/parsing_state_spec.rb +1 -1
  44. data/spec/unit/def_mastership/rename_included_files_modifier_spec.rb +219 -47
  45. data/spec/unit/def_mastership/string_spec.rb +1 -1
  46. data/spec/unit/def_mastership/update_def_checksum_modifier_spec.rb +82 -50
  47. data/spec/unit/def_mastership/update_def_modifier_spec.rb +119 -0
  48. data/spec/unit/def_mastership/update_def_version_modifier_spec.rb +135 -56
  49. data/tasks/console.rake +8 -0
  50. data/tasks/package.task +9 -0
  51. data/tasks/smelling_code.rake +38 -0
  52. data/tasks/test.rake +45 -0
  53. metadata +16 -153
  54. data/lib/defmastership/change_ref_line_modifier.rb +0 -85
  55. data/lib/defmastership/line_modifier_base.rb +0 -29
  56. data/lib/defmastership/modifier_base.rb +0 -36
  57. data/lib/defmastership/rename_included_files_line_modifier.rb +0 -126
  58. data/lib/defmastership/update_def_checksum_line_modifier.rb +0 -38
  59. data/lib/defmastership/update_def_version_line_modifier.rb +0 -58
  60. data/spec/unit/def_mastership/change_ref_line_modifier_spec.rb +0 -250
  61. data/spec/unit/def_mastership/rename_included_files_line_modifier_spec.rb +0 -207
  62. data/spec/unit/def_mastership/update_def_checksum_line_modifier_spec.rb +0 -82
  63. data/spec/unit/def_mastership/update_def_version_line_modifier_spec.rb +0 -131
@@ -1,85 +0,0 @@
1
- # Copyright (c) 2020 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- require 'defmastership/constants'
5
- require 'defmastership/line_modifier_base'
6
-
7
- module DefMastership
8
- # Change references from temporary to definitive with multiple RefChangers
9
- class ChangeRefLineModifier < LineModifierBase
10
- def self.from_config(hash)
11
- new.from_config(hash)
12
- end
13
-
14
- REGEXP_FROM = {
15
- definition: {
16
- before: DMRegexp::DEF_BEFORE_REF,
17
- after: DMRegexp::DEF_AFTER_REF
18
- },
19
- iref: {
20
- before: DMRegexp::IREF_DEF_BEF,
21
- after: DMRegexp::IREF_DEF_AFT
22
- }
23
- }.freeze
24
-
25
- private_constant :REGEXP_FROM
26
-
27
- def initialize
28
- super
29
- @config = {
30
- from_regexp: '',
31
- to_template: '',
32
- next_ref: 0
33
- }
34
- @parsing_state = ParsingState.new
35
- end
36
-
37
- def replace(method, line)
38
- public_send("replace_#{method}".to_sym, line)
39
- end
40
-
41
- def replace_refdef(line)
42
- if @parsing_state.enabled?(line)
43
- do_replace_refdef(line)
44
- else
45
- line
46
- end
47
- end
48
-
49
- def replace_irefs(line)
50
- changes.reduce(line) do |res_line, (from, to)|
51
- res_line.gsub(regexp_from(:iref, from)) do
52
- text_with(Regexp.last_match, to)
53
- end
54
- end
55
- end
56
-
57
- private
58
-
59
- def do_replace_refdef(line)
60
- line.gsub(regexp_from(:definition, from_regexp)) do
61
- replacement = to_template % hmerge(Regexp.last_match)
62
- changes << [Regexp.last_match[:from], replacement]
63
- @config[:next_ref] += 1
64
- text_with(Regexp.last_match, replacement)
65
- end
66
- end
67
-
68
- def regexp_from(const, from)
69
- regexp_str =
70
- "(?<before>#{REGEXP_FROM[const][:before]})" \
71
- "(?<from>#{from})" \
72
- "#{DMRegexp::DEF_VERSION_AND_CHECKSUM}" \
73
- "(?<after>#{REGEXP_FROM[const][:after]})"
74
- Regexp.new(regexp_str, Regexp::EXTENDED)
75
- end
76
-
77
- def text_with(match, replacement)
78
- match[:before] + replacement + (match[:version_and_checksum] || '') + match[:after]
79
- end
80
-
81
- def hmerge(match)
82
- @config.merge(match.names.map(&:to_sym).zip(match.captures).to_h)
83
- end
84
- end
85
- end
@@ -1,29 +0,0 @@
1
- # Copyright (c) 2020 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- module DefMastership
5
- # Change references from temporary to definitive with multiple RefChangers
6
- class LineModifierBase
7
- attr_reader :changes, :config
8
-
9
- def initialize
10
- @config = {}
11
- @changes = []
12
- end
13
-
14
- def method_missing(method_name, *args, &block)
15
- return @config[method_name] if @config[method_name]
16
-
17
- super
18
- end
19
-
20
- def respond_to_missing?(method_name, *args)
21
- @config[method_name] || super
22
- end
23
-
24
- def from_config(config)
25
- @config.merge!(config)
26
- self
27
- end
28
- end
29
- end
@@ -1,36 +0,0 @@
1
- # Copyright (c) 2020 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- module DefMastership
5
- # Change references from temporary to definitive with multiple RefChangers
6
- class ModifierBase
7
- attr_reader :config, :changes
8
-
9
- def initialize(config)
10
- @config = config
11
- @changes = []
12
- end
13
-
14
- def do_modifications(adoc_texts)
15
- line_modifier = new_line_modifier(@config, adoc_texts)
16
-
17
- adoc_texts =
18
- replacements.reduce(adoc_texts) do |texts, method|
19
- transform_values(texts, line_modifier, method)
20
- end
21
-
22
- @config = line_modifier.config
23
- @changes = line_modifier.changes
24
- adoc_texts
25
- end
26
-
27
- private
28
-
29
- def transform_values(texts, line_modifier, method)
30
- texts.transform_values do |text|
31
- text.lines.map { |line| line_modifier.public_send(method, line) }
32
- .join
33
- end
34
- end
35
- end
36
- end
@@ -1,126 +0,0 @@
1
- # Copyright (c) 2020 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- module DefMastership
5
- # Change included filenames on one line at a time
6
- class RenameIncludedFilesLineModifier < LineModifierBase
7
- LOCAL_FILTERS = [
8
- Filter.new(DMRegexp::VARIABLE_DEF, :new_variable_def, false),
9
- Filter.new(DMRegexp::DEFINITION, :new_definition, true),
10
- Filter.new(DMRegexp::BLOCK, :block_delimiter, true),
11
- Filter.new(DMRegexp::EMPTY_LINE, :empty_line, false),
12
- Filter.new(DMRegexp::WHATEVER, :new_line, true)
13
- ].freeze
14
- private_constant :LOCAL_FILTERS
15
-
16
- def self.from_config(config)
17
- new.from_config(config)
18
- end
19
-
20
- def initialize
21
- super
22
- @config = {
23
- from_regexp: '',
24
- to_template: ''
25
- }
26
- @variables = {}
27
- @definition_parser = DefinitionParser.new(self)
28
- end
29
-
30
- def replace(line)
31
- match = matched?(line)
32
-
33
- return line unless match
34
-
35
- new_line =
36
- line.gsub(complete_regexp_from(from_regexp)) do
37
- text_with(match, to_template % hmerge(match))
38
- end
39
-
40
- rename_file(line, new_line)
41
-
42
- new_line
43
- end
44
-
45
- def add_new_definition(match, _line)
46
- @config[:reference] = match[:reference]
47
- end
48
-
49
- def add_line(_match, _line) end
50
-
51
- def new_variable_def(match, line)
52
- @variables[match[:varname].to_sym] = match[:value]
53
- line
54
- end
55
-
56
- private
57
-
58
- def matched?(line)
59
- return if line.commented?
60
-
61
- parse(line)
62
-
63
- return if @definition_parser.idle?
64
- return unless line =~ complete_regexp_from(from_regexp)
65
-
66
- match = Regexp.last_match
67
-
68
- return if @config[:cancel_if_match] && match[:filename] =~ Regexp.new(cancel_if_match)
69
-
70
- match
71
- end
72
-
73
- def parse(line)
74
- LOCAL_FILTERS.each do |filter|
75
- next unless line.match(filter.regexp)
76
-
77
- line = generate_event(filter.event, Regexp.last_match, line)
78
-
79
- break if filter.consumed_line
80
- end
81
- end
82
-
83
- def rename_file(from, to)
84
- @changes << [extract_filename(from), extract_filename(to)]
85
- File.rename(extract_filename(from), extract_filename(to))
86
- end
87
-
88
- def extract_filename(include_statement)
89
- filename = include_statement
90
- .gsub(Regexp.new(DMRegexp::INCLUDE_KEYWORD), '')
91
- .gsub(Regexp.new(DMRegexp::INCLUDE_OPTIONS), '')
92
-
93
- filename.dup.scan(DMRegexp::VARIABLE_USE) do |_|
94
- varname = Regexp.last_match[:varname]
95
- next if @variables[varname.to_sym].nil?
96
-
97
- filename.gsub!("{#{varname}}", @variables[varname.to_sym])
98
- end
99
- filename.chomp
100
- end
101
-
102
- def complete_regexp_from(from)
103
- Regexp.new(
104
- DMRegexp::INCLUDE_KEYWORD + DMRegexp::INCLUDE_PATH +
105
- "(?<filename>#{from})" + DMRegexp::INCLUDE_OPTIONS
106
- )
107
- end
108
-
109
- def text_with(match, to)
110
- "include::#{match[:path] || ''}#{to}[#{match[:options]}]"
111
- end
112
-
113
- def hmerge(match)
114
- @config.merge(match.names.map(&:to_sym).zip(match.captures).to_h)
115
- end
116
-
117
- def generate_event(event, match, line)
118
- if respond_to?(event)
119
- public_send(event, match, line)
120
- else
121
- @definition_parser.public_send(event, match, line)
122
- end
123
- line
124
- end
125
- end
126
- end
@@ -1,38 +0,0 @@
1
- # Copyright (c) 2020 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- module DefMastership
5
- # modify one line after another
6
- class UpdateDefChecksumLineModifier < LineModifierBase
7
- attr_accessor :document
8
-
9
- def self.from_config(hash)
10
- new.from_config(hash)
11
- end
12
-
13
- def initialize
14
- super
15
- @config = {
16
- def_type: ''
17
- }
18
- end
19
-
20
- def replace(line)
21
- match = matched?(line)
22
-
23
- return line unless match
24
- return line unless match[:type] == def_type
25
-
26
- line.gsub(Regexp.new("#{match[:reference]}#{DMRegexp::DEF_VERSION_AND_CHECKSUM}")) do
27
- "#{match[:reference]}(#{match[:explicit_version]}#{@document.ref_to_def(match[:reference]).sha256})"
28
- end
29
- end
30
-
31
- def matched?(line)
32
- return if line.commented?
33
- return unless line =~ DMRegexp::DEFINITION
34
-
35
- Regexp.last_match
36
- end
37
- end
38
- end
@@ -1,58 +0,0 @@
1
- # Copyright (c) 2020 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- module DefMastership
5
- # modify one line after another
6
- class UpdateDefVersionLineModifier < LineModifierBase
7
- attr_accessor :document, :ref_document
8
-
9
- def self.from_config(hash)
10
- new.from_config(hash)
11
- end
12
-
13
- def initialize
14
- super
15
- @config = {
16
- def_type: '',
17
- ref_document: '',
18
- first_version: ''
19
- }
20
- end
21
-
22
- def replace(line)
23
- match = matched?(line)
24
-
25
- return line unless match
26
- return line unless match[:type] == def_type
27
-
28
- version_and_checksum = ''
29
- if match[:explicit_checksum] || version_string(match)
30
- version_and_checksum = "(#{version_string(match)}#{match[:explicit_checksum]})"
31
- end
32
-
33
- line.gsub(Regexp.new("#{match[:reference]}#{DMRegexp::DEF_VERSION_AND_CHECKSUM}")) do
34
- "#{match[:reference]}#{version_and_checksum}"
35
- end
36
- end
37
-
38
- private
39
-
40
- def matched?(line)
41
- return if line.commented?
42
- return unless line =~ DMRegexp::DEFINITION
43
-
44
- Regexp.last_match
45
- end
46
-
47
- def version_string(match)
48
- ref_definition = @ref_document.ref_to_def(match[:reference])
49
- definition = @document.ref_to_def(match[:reference])
50
-
51
- return if ref_definition.nil?
52
- return ref_definition.explicit_version if definition.sha256 == ref_definition.sha256
53
-
54
- ref_version = @ref_document.ref_to_def(match[:reference]).explicit_version
55
- ref_version.nil? ? @config[:first_version] : ref_version.next
56
- end
57
- end
58
- end
@@ -1,250 +0,0 @@
1
- # Copyright (c) 2020 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- require('defmastership')
5
-
6
- RSpec.describe(DefMastership::ChangeRefLineModifier) do
7
- subject(:refchanger) { described_class.new }
8
-
9
- describe '.new' do
10
- it { is_expected.not_to(be_nil) }
11
- it { is_expected.to(have_attributes(from_regexp: '')) }
12
- it { is_expected.to(have_attributes(to_template: '')) }
13
- it { is_expected.to(have_attributes(next_ref: 0)) }
14
- it { is_expected.to(have_attributes(changes: [])) }
15
-
16
- it do
17
- expect { refchanger.user_defined_attribute }
18
- .to(raise_error(NoMethodError))
19
- end
20
- end
21
-
22
- describe '.from_config' do
23
- subject(:refchanger) do
24
- described_class.from_config(
25
- from_regexp: 'Whatever.+',
26
- to_template: 'Whatever',
27
- next_ref: 17
28
- )
29
- end
30
-
31
- it { is_expected.not_to(be_nil) }
32
- it { is_expected.to(have_attributes(from_regexp: 'Whatever.+')) }
33
- it { is_expected.to(have_attributes(to_template: 'Whatever')) }
34
- it { is_expected.to(have_attributes(next_ref: 17)) }
35
- end
36
-
37
- describe '#from_config' do
38
- before do
39
- refchanger.from_config(
40
- from_regexp: 'Whatever.+',
41
- to_template: 'Whatever',
42
- next_ref: 17,
43
- user_defined_attribute: 'Tadaam'
44
- )
45
- end
46
-
47
- it { is_expected.to(have_attributes(from_regexp: 'Whatever.+')) }
48
- it { is_expected.to(have_attributes(to_template: 'Whatever')) }
49
- it { is_expected.to(have_attributes(next_ref: 17)) }
50
- it { is_expected.to(have_attributes(user_defined_attribute: 'Tadaam')) }
51
- end
52
-
53
- describe '#config' do
54
- context 'when not initalized' do
55
- it do
56
- expect(refchanger.config).to(
57
- include(from_regexp: '', to_template: '', next_ref: 0)
58
- )
59
- end
60
- end
61
-
62
- context 'when initalized with additionnal keys' do
63
- before do
64
- refchanger.from_config(
65
- next_ref: 1256,
66
- user_defined_attribute: 'Tadaam'
67
- )
68
- end
69
-
70
- it { expect(refchanger.config).to(include(from_regexp: '')) }
71
- it { expect(refchanger.config).to(include(to_template: '')) }
72
- it { expect(refchanger.config).to(include(next_ref: 1256)) }
73
- it { expect(refchanger.config).to(include(user_defined_attribute: 'Tadaam')) }
74
- end
75
- end
76
-
77
- describe '#replace_def' do
78
- context 'when really simple rule' do
79
- before do
80
- refchanger.from_config(
81
- from_regexp: 'TEMP',
82
- to_template: 'TUTU'
83
- )
84
- end
85
-
86
- context 'when valid definition' do
87
- it do
88
- expect(refchanger.replace_refdef('[define, whatever, TEMP]'))
89
- .to(eq('[define, whatever, TUTU]'))
90
- end
91
- end
92
-
93
- context 'when no valid definition' do
94
- it do
95
- expect(refchanger.replace_refdef('[pouet, whatever, TEMP]'))
96
- .to(eq('[pouet, whatever, TEMP]'))
97
- end
98
- end
99
- end
100
-
101
- context 'when template is variable' do
102
- before do
103
- refchanger.from_config(
104
- from_regexp: 'TEMP',
105
- to_template: 'TOTO-%<next_ref>04d',
106
- next_ref: 124
107
- )
108
- end
109
-
110
- it do
111
- expect(refchanger.replace_refdef('[define, whatever, TEMP]'))
112
- .to(eq('[define, whatever, TOTO-0124]'))
113
- end
114
-
115
- it do
116
- refchanger.replace_refdef('[define, whatever, TEMP]')
117
- expect(refchanger).to(have_attributes(next_ref: 125))
118
- end
119
- end
120
-
121
- context 'when capture group in regexp' do
122
- before do
123
- refchanger.from_config(
124
- from_regexp: '(?<cg>TOTO|TITI)-TEMP[\d]*',
125
- to_template: '%<cg>s-%<next_ref>04d',
126
- next_ref: 132
127
- )
128
- end
129
-
130
- it do
131
- expect(refchanger.replace_refdef('[define, whatever, TOTO-TEMP]'))
132
- .to(eq('[define, whatever, TOTO-0132]'))
133
- end
134
-
135
- it do
136
- refchanger.replace_refdef('[define, whatever, TOTO-TEMP]')
137
- expect(refchanger.replace_refdef('[define, whatever, TITI-TEMP]'))
138
- .to(eq('[define, whatever, TITI-0133]'))
139
- end
140
-
141
- it do
142
- refchanger.replace_refdef('[define, whatever, TOTO-TEMP1]')
143
- refchanger.replace_refdef('[define, whatever, TITI-TEMP2]')
144
- expect(refchanger).to(have_attributes(changes: [%w[TOTO-TEMP1 TOTO-0132], %w[TITI-TEMP2 TITI-0133]]))
145
- end
146
- end
147
-
148
- context 'when definition is in literal block' do
149
- before do
150
- refchanger.from_config(
151
- from_regexp: 'TEMP',
152
- to_template: 'TUTU'
153
- )
154
- refchanger.replace_refdef('....')
155
- end
156
-
157
- it do
158
- expect(refchanger.replace_refdef('[define, whatever, TEMP]'))
159
- .to(eq('[define, whatever, TEMP]'))
160
- end
161
- end
162
-
163
- context 'when defintion is after literal block' do
164
- before do
165
- refchanger.from_config(
166
- from_regexp: 'TEMP',
167
- to_template: 'TUTU'
168
- )
169
- refchanger.replace_refdef("....\n")
170
- refchanger.replace_refdef('[define, whatever, TEMP]')
171
- refchanger.replace_refdef("....\n")
172
- end
173
-
174
- it do
175
- expect(refchanger.replace_refdef('[define, whatever, TEMP]'))
176
- .to(eq('[define, whatever, TUTU]'))
177
- end
178
- end
179
- end
180
-
181
- describe '#replace_irefs' do
182
- before do
183
- refchanger.from_config(
184
- from_regexp: '(?<cg>TOTO|TITI)-TEMP[\d]*',
185
- to_template: '%<cg>s-%<next_ref>04d',
186
- next_ref: 132
187
- )
188
- refchanger.replace_refdef('[define, whatever, TOTO-TEMP123]')
189
- refchanger.replace_refdef('[define, whatever, TITI-TEMP421]')
190
- end
191
-
192
- it do
193
- expect(refchanger.replace_irefs('defs:iref[TOTO-TEMP1234]'))
194
- .to(eq('defs:iref[TOTO-TEMP1234]'))
195
- end
196
-
197
- it do
198
- expect(refchanger.replace_irefs('defs:iref[TOTO-TEMP123]'))
199
- .to(eq('defs:iref[TOTO-0132]'))
200
- end
201
-
202
- it do
203
- expect(
204
- refchanger.replace_irefs(
205
- 'defs:iref[TOTO-TEMP123] defs:iref[TITI-TEMP421] bla'
206
- )
207
- ).to(eq('defs:iref[TOTO-0132] defs:iref[TITI-0133] bla'))
208
- end
209
- end
210
-
211
- describe '#replace' do
212
- before do
213
- refchanger.from_config(
214
- from_regexp: 'TEMP',
215
- to_template: 'TUTU'
216
- )
217
- end
218
-
219
- it do
220
- expect(refchanger.replace(:refdef, '[define, whatever, TEMP]'))
221
- .to(eq('[define, whatever, TUTU]'))
222
- end
223
-
224
- it do
225
- expect(refchanger.replace(:refdef, '[define, whatever, TEMP(a~12345678)]'))
226
- .to(eq('[define, whatever, TUTU(a~12345678)]'))
227
- end
228
-
229
- it do
230
- expect(refchanger.replace(:refdef, '[define, whatever, TEMP(~12345678)]'))
231
- .to(eq('[define, whatever, TUTU(~12345678)]'))
232
- end
233
-
234
- it do
235
- expect(refchanger.replace(:refdef, '[define, whatever, TEMP(a)]'))
236
- .to(eq('[define, whatever, TUTU(a)]'))
237
- end
238
-
239
- it do
240
- refchanger.replace(:refdef, '[define, whatever, TEMP]')
241
- expect(refchanger.replace(:irefs, 'defs:iref[TEMP]'))
242
- .to(eq('defs:iref[TUTU]'))
243
- end
244
-
245
- it do
246
- expect { refchanger.replace(:pouet, 'whatever') }
247
- .to(raise_error(NoMethodError))
248
- end
249
- end
250
- end