defmastership 1.0.3 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.gitlab-ci.yml +0 -1
  4. data/.rubocop.yml +3 -2
  5. data/Gemfile +1 -0
  6. data/LICENSE +22 -0
  7. data/Rakefile +2 -2
  8. data/bin/defmastership +37 -24
  9. data/cucumber.yml +2 -0
  10. data/defmastership.gemspec +16 -9
  11. data/features/changeref.feature +82 -129
  12. data/features/definition_checksum.feature +244 -0
  13. data/features/definition_version.feature +24 -0
  14. data/features/export.feature +49 -31
  15. data/features/modify.feature +165 -0
  16. data/features/rename_included_files.feature +121 -0
  17. data/features/step_definitions/defmastership_steps.rb +1 -0
  18. data/features/support/env.rb +1 -0
  19. data/lib/defmastership.rb +15 -3
  20. data/lib/defmastership/batch_modifier.rb +35 -0
  21. data/lib/defmastership/{ref_changer.rb → change_ref_line_modifier.rb} +19 -35
  22. data/lib/defmastership/change_ref_modifier.rb +15 -0
  23. data/lib/defmastership/comment_filter.rb +1 -0
  24. data/lib/defmastership/constants.rb +15 -1
  25. data/lib/defmastership/csv_formatter.rb +26 -19
  26. data/lib/defmastership/csv_formatter_body.rb +20 -11
  27. data/lib/defmastership/csv_formatter_header.rb +16 -10
  28. data/lib/defmastership/definition.rb +15 -3
  29. data/lib/defmastership/definition_parser.rb +46 -0
  30. data/lib/defmastership/document.rb +60 -85
  31. data/lib/defmastership/filters.rb +30 -0
  32. data/lib/defmastership/line_modifier_base.rb +29 -0
  33. data/lib/defmastership/modifier_base.rb +29 -0
  34. data/lib/defmastership/rename_included_files_line_modifier.rb +126 -0
  35. data/lib/defmastership/rename_included_files_modifier.rb +15 -0
  36. data/lib/defmastership/update_def_checksum_line_modifier.rb +39 -0
  37. data/lib/defmastership/update_def_checksum_modifier.rb +21 -0
  38. data/lib/defmastership/version.rb +2 -1
  39. data/spec/spec_helper.rb +2 -0
  40. data/spec/unit/defmastership/batch_modifier_spec.rb +123 -0
  41. data/spec/unit/defmastership/{ref_changer_spec.rb → change_ref_line_modifier_spec.rb} +49 -26
  42. data/spec/unit/defmastership/change_ref_modifier_spec.rb +76 -0
  43. data/spec/unit/defmastership/comment_filter_spec.rb +9 -4
  44. data/spec/unit/defmastership/csv_formatter_body_spec.rb +89 -82
  45. data/spec/unit/defmastership/csv_formatter_header_spec.rb +69 -22
  46. data/spec/unit/defmastership/csv_formatter_spec.rb +209 -110
  47. data/spec/unit/defmastership/definition_parser_spec.rb +63 -0
  48. data/spec/unit/defmastership/definition_spec.rb +46 -4
  49. data/spec/unit/defmastership/document_spec.rb +237 -35
  50. data/spec/unit/defmastership/rename_included_files_line_modifier_spec.rb +203 -0
  51. data/spec/unit/defmastership/rename_included_files_modifier_spec.rb +67 -0
  52. data/spec/unit/defmastership/update_def_checksum_line_modifier_spec.rb +68 -0
  53. data/spec/unit/defmastership/update_def_checksum_modifier_spec.rb +75 -0
  54. data/spec/unit/defmastership_spec.rb +1 -0
  55. metadata +49 -17
  56. data/Gemfile.lock +0 -140
  57. data/lib/defmastership/batch_changer.rb +0 -40
  58. data/lib/defmastership/project_ref_changer.rb +0 -27
  59. data/spec/unit/defmastership/batch_changer_spec.rb +0 -108
  60. data/spec/unit/defmastership/project_ref_changer_spec.rb +0 -79
@@ -0,0 +1,15 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ module DefMastership
5
+ # Change all refs of a given project
6
+ class ChangeRefModifier < ModifierBase
7
+ def replacements
8
+ %i[replace_refdef replace_irefs]
9
+ end
10
+
11
+ def new_line_modifier(config, _adoc_texts)
12
+ ChangeRefLineModifier.from_config(config)
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,4 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
1
2
  # frozen_string_literal: true
2
3
 
3
4
  # Add a class to handled asciidoctor comments
@@ -1,3 +1,4 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module DefMastership
@@ -18,8 +19,11 @@ module DefMastership
18
19
  \s*
19
20
  (,\s*\[\s*(?<labels>.*?)\s*\])?\s*\]
20
21
  AFT
22
+
23
+ DEF_VERSION_AND_CHECKSUM = '(\((?<explicit_version>[^~]+)?(?<explicit_checksum>~[[:alnum:]]+)?\))?'
24
+
21
25
  DEFINITION = Regexp.new(
22
- "#{DEF_BEFORE_REF}(?<reference>[\\w:_-]+)#{DEF_AFTER_REF}",
26
+ "#{DEF_BEFORE_REF}(?<reference>[\\w:_-]+)#{DEF_VERSION_AND_CHECKSUM}#{DEF_AFTER_REF}",
23
27
  Regexp::EXTENDED
24
28
  )
25
29
 
@@ -55,6 +59,16 @@ module DefMastership
55
59
 
56
60
  WHATEVER = //.freeze
57
61
 
62
+ INCLUDE_KEYWORD = '\binclude::'
63
+ INCLUDE_PATH = '(?<path>.*/)?'
64
+ INCLUDE_FILENAME = '(?<filename>[^\\/]+)'
65
+ INCLUDE_OPTIONS = '\[(?<options>[\]]*)\]'
66
+
67
+ INCLUDE = Regexp.new(
68
+ INCLUDE_KEYWORD + INCLUDE_PATH + INCLUDE_FILENAME + INCLUDE_OPTIONS,
69
+ Regexp::EXTENDED
70
+ )
71
+
58
72
  public_constant :SINGLE_LINE_COMMENT,
59
73
  :MULTI_LINE_COMMENT_DELIM,
60
74
  :DEF_BEFORE_REF,
@@ -1,3 +1,4 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require('csv')
@@ -7,36 +8,42 @@ require('defmastership/csv_formatter_body')
7
8
  module DefMastership
8
9
  # to export a CSV file
9
10
  class CSVFormatter
10
- COLUMN_LIST = %w[fixed labels eref iref attributes].freeze
11
- private_constant :COLUMN_LIST
12
-
13
- def initialize(doc)
11
+ def initialize(doc, sep = ',')
14
12
  @doc = doc
15
- @header_formatter = CSVFormatterHeader.new(@doc)
16
- @body_formatter = CSVFormatterBody.new(@doc)
13
+ @sep = sep
17
14
  end
18
15
 
19
16
  def export_to(output_file)
20
- CSV.open(output_file, 'w:ISO-8859-1') do |csv|
21
- csv << header
22
- @doc.definitions.each { |definition| csv << body(definition) }
17
+ column_list = build_column_list
18
+ CSV.open(output_file, 'w:ISO-8859-1', { col_sep: @sep }) do |csv|
19
+ csv << header(column_list)
20
+ @doc.definitions.each { |definition| csv << body(definition, column_list) }
23
21
  end
24
22
  end
25
23
 
26
- def header
27
- header_line =
28
- COLUMN_LIST.map do |part|
29
- @header_formatter.public_send("#{part}_header".to_sym)
30
- end
24
+ private
25
+
26
+ def header(column_list)
27
+ header_formatter = CSVFormatterHeader.new(@doc)
28
+ header_line = column_list.map { |part| header_formatter.public_send(part) }
31
29
  header_line.reduce(:+)
32
30
  end
33
31
 
34
- def body(definition)
35
- body_line =
36
- COLUMN_LIST.map do |part|
37
- @body_formatter.public_send("#{part}_body".to_sym, definition)
38
- end
32
+ def body(definition, column_list)
33
+ body_formatter = CSVFormatterBody.new(@doc)
34
+ body_line = column_list.map { |part| body_formatter.public_send(part, definition) }
39
35
  body_line.reduce(:+)
40
36
  end
37
+
38
+ def build_column_list
39
+ column_list = [:fixed]
40
+ column_list += [:wrong_explicit_checksum] if @doc.wrong_explicit_checksum?
41
+ column_list += [:explicit_version] if @doc.explicit_version?
42
+ column_list += [:labels] unless @doc.labels.empty?
43
+ column_list += [:eref] unless @doc.eref.empty?
44
+ column_list += [:iref] if @doc.iref
45
+ column_list += [:attributes] unless @doc.attributes.empty?
46
+ column_list
47
+ end
41
48
  end
42
49
  end
@@ -1,3 +1,4 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require('csv')
@@ -9,26 +10,34 @@ module DefMastership
9
10
  @doc = doc
10
11
  end
11
12
 
12
- def fixed_body(definition)
13
- [definition.type, definition.reference, definition.value]
13
+ def fixed(definition)
14
+ [definition.type, definition.reference, definition.value, definition.sha256]
14
15
  end
15
16
 
16
- def labels_body(definition)
17
- @doc.labels.empty? ? [] : [definition.labels.to_a.join("\n")]
17
+ def wrong_explicit_checksum(definition)
18
+ wrong_explicit_checksum = definition.wrong_explicit_checksum
19
+ wrong_explicit_checksum ? [wrong_explicit_checksum] : ['']
18
20
  end
19
21
 
20
- def eref_body(definition)
22
+ def explicit_version(definition)
23
+ explicit_version = definition.explicit_version
24
+ explicit_version ? [explicit_version] : ['']
25
+ end
26
+
27
+ def labels(definition)
28
+ [definition.labels.to_a.join("\n")]
29
+ end
30
+
31
+ def eref(definition)
21
32
  @doc.eref.map { |key, _| definition.eref[key].join("\n") }
22
33
  end
23
34
 
24
- def iref_body(definition)
25
- @doc.iref ? [definition.iref.join("\n")] : []
35
+ def iref(definition)
36
+ [definition.iref.join("\n")]
26
37
  end
27
38
 
28
- def attributes_body(definition)
29
- @doc.attributes.map do |key, _|
30
- definition.attributes[key]
31
- end
39
+ def attributes(definition)
40
+ @doc.attributes.map { |key, _| definition.attributes[key] }
32
41
  end
33
42
  end
34
43
  end
@@ -1,3 +1,4 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require('csv')
@@ -9,26 +10,31 @@ module DefMastership
9
10
  @doc = doc
10
11
  end
11
12
 
12
- def fixed_header
13
- %w[Type Reference Value]
13
+ def fixed
14
+ %w[Type Reference Value Checksum]
14
15
  end
15
16
 
16
- def labels_header
17
+ def wrong_explicit_checksum
18
+ @doc.wrong_explicit_checksum? ? ['Wrong explicit checksum'] : []
19
+ end
20
+
21
+ def explicit_version
22
+ @doc.explicit_version? ? ['Version'] : []
23
+ end
24
+
25
+ def labels
17
26
  @doc.labels.empty? ? [] : %w[Labels]
18
27
  end
19
28
 
20
- def eref_header
21
- @doc.eref.map do |_, ref|
22
- ref[:prefix] +
23
- (ref[:url].nil? || ref[:url] == 'none' ? '' : " #{ref[:url]}")
24
- end
29
+ def eref
30
+ @doc.eref.map { |_, ref| ref[:prefix] }
25
31
  end
26
32
 
27
- def iref_header
33
+ def iref
28
34
  @doc.iref ? ['Internal links'] : []
29
35
  end
30
36
 
31
- def attributes_header
37
+ def attributes
32
38
  @doc.attributes.map { |_, value| value }
33
39
  end
34
40
  end
@@ -1,20 +1,24 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
1
2
  # frozen_string_literal: true
2
3
 
4
+ require 'digest'
5
+
3
6
  module DefMastership
4
7
  # DefMastership definition: contains all data of a definition
5
8
  class Definition
6
- attr_reader :type, :reference, :lines, :labels, :eref, :iref, :attributes
9
+ attr_reader :type, :reference, :lines, :labels, :eref, :iref, :attributes, :explicit_version
7
10
 
8
11
  def initialize(match)
9
12
  @type = match[:type]
10
13
  @reference = match[:reference]
11
14
  @lines = []
12
15
  @labels = Set.new
13
- labels = match[:labels]
14
- @labels.merge(labels.split(/\s*,\s*/).to_set) if labels
16
+ @labels.merge(match[:labels].split(/\s*,\s*/).to_set) if match[:labels]
15
17
  @eref = Hash.new([])
16
18
  @iref = []
17
19
  @attributes = {}
20
+ @explicit_checksum = match[:explicit_checksum]
21
+ @explicit_version = match[:explicit_version]
18
22
  end
19
23
 
20
24
  def <<(new_line)
@@ -26,6 +30,14 @@ module DefMastership
26
30
  @lines.join("\n")
27
31
  end
28
32
 
33
+ def sha256
34
+ "~#{Digest::SHA2.new(256).hexdigest(value).split(//).last(8).join}"
35
+ end
36
+
37
+ def wrong_explicit_checksum
38
+ @explicit_checksum if @explicit_checksum != sha256
39
+ end
40
+
29
41
  def add_eref(refname, extrefs)
30
42
  @eref[refname] = extrefs.strip.split(/\s*,\s*/)
31
43
  end
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require('aasm')
5
+
6
+ module DefMastership
7
+ # DefMastership definition: contains all data of a definition
8
+ class DefinitionParser
9
+ include AASM
10
+
11
+ def initialize(document)
12
+ @document = document
13
+ end
14
+
15
+ aasm do
16
+ state :idle, initial: true
17
+ state :wait_content
18
+ state :in_block
19
+ state :single_para
20
+
21
+ event :new_definition do
22
+ transitions from: :idle, to: :wait_content, after: ->(*args) { @document.add_new_definition(*args) }
23
+ end
24
+
25
+ event :block_delimiter do
26
+ transitions from: :wait_content, to: :in_block
27
+ transitions from: %i[in_block idle single_para], to: :idle
28
+ end
29
+
30
+ event :new_line do
31
+ transitions from: %i[wait_content single_para],
32
+ to: :single_para,
33
+ after: ->(*args) { @document.add_line(*args) }
34
+ transitions from: :in_block,
35
+ to: :in_block,
36
+ after: ->(*args) { @document.add_line(*args) }
37
+ transitions from: :idle, to: :idle
38
+ end
39
+
40
+ event :empty_line do
41
+ transitions from: %i[wait_content single_para idle], to: :idle
42
+ transitions from: :in_block, to: :in_block
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,40 +1,13 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
1
2
  # frozen_string_literal: true
2
3
 
3
- require('aasm')
4
+ require('asciidoctor')
4
5
 
5
6
  module DefMastership
6
7
  # Contains the content of a DefMastership document: mainly definitions
7
- # TODO: make this class smaller by defining a separated parser
8
-
9
- # Contains regexp / action couples
10
- Filter = Struct.new(:regexp, :event, :consumed_line)
11
- private_constant :Filter
12
-
13
- FILTERS_IN_LITERAL = [
14
- Filter.new(DMRegexp::LITERAL_BLOCK, :code_block_delimiter, false),
15
- Filter.new(DMRegexp::WHATEVER, :new_line, true)
16
- ].freeze
17
- private_constant :FILTERS_IN_LITERAL
18
-
19
- FILTERS = [
20
- Filter.new(DMRegexp::VARIABLE_DEF, :new_variable_def, false),
21
- Filter.new(DMRegexp::VARIABLE_USE, :new_variable_use, false),
22
- Filter.new(DMRegexp::DEFINITION, :new_definition, true),
23
- Filter.new(DMRegexp::EREF_CONFIG, :new_eref_setup, true),
24
- Filter.new(DMRegexp::EREF_DEF, :new_eref_def, false),
25
- Filter.new(DMRegexp::IREF_DEF, :new_iref_def, false),
26
- Filter.new(DMRegexp::ATTR_CONFIG, :new_attribute_conf, true),
27
- Filter.new(DMRegexp::ATTR_SET, :new_attribute_value, false),
28
- Filter.new(DMRegexp::BLOCK, :block_delimiter, true),
29
- Filter.new(DMRegexp::LITERAL_BLOCK, :code_block_delimiter, true),
30
- Filter.new(DMRegexp::EMPTY_LINE, :empty_line, false),
31
- Filter.new(DMRegexp::WHATEVER, :new_line, true)
32
- ].freeze
33
- private_constant :FILTERS
34
8
 
35
9
  # Reflects document structure from a definition point of view
36
10
  class Document
37
- include AASM
38
11
  attr_reader :definitions, :labels, :eref, :iref, :attributes, :variables
39
12
 
40
13
  def initialize
@@ -44,110 +17,112 @@ module DefMastership
44
17
  @iref = false
45
18
  @attributes = {}
46
19
  @in_literal = true
47
- @current_line = nil
48
20
  @variables = {}
21
+ @definition_parser = DefinitionParser.new(self)
49
22
  end
50
23
 
51
- aasm do
52
- state :idle, initial: true
53
- state :wait_content
54
- state :in_block
55
- state :single_para
24
+ def parse(lines)
25
+ lines.reject(&:commented?).each do |line|
26
+ (@in_literal ? FILTERS : FILTERS_IN_LITERAL).each do |filter|
27
+ next unless line.match(filter.regexp)
56
28
 
57
- event :new_definition do
58
- transitions from: :idle, to: :wait_content, after: :add_new_definition
59
- end
29
+ line = generate_event(filter.event, Regexp.last_match, line)
60
30
 
61
- event :block_delimiter do
62
- transitions from: :wait_content, to: :in_block
63
- transitions from: %i[in_block idle], to: :idle
64
- transitions from: :single_para, to: :idle
31
+ break if filter.consumed_line
32
+ end
65
33
  end
34
+ end
35
+
36
+ def parse_file_with_preprocessor(adoc_file)
37
+ parse(Asciidoctor.load_file(adoc_file, safe: :unsafe, parse: false).reader.read_lines)
38
+ end
66
39
 
67
- event :new_line do
68
- transitions from: :wait_content, to: :single_para, after: :add_line
69
- transitions from: :single_para, to: :single_para, after: :add_line
70
- transitions from: :in_block, to: :in_block, after: :add_line
71
- transitions from: :idle, to: :idle
40
+ def wrong_explicit_checksum?
41
+ @definitions.reduce(false) do |res, definition|
42
+ res || !definition.wrong_explicit_checksum.nil?
72
43
  end
44
+ end
73
45
 
74
- event :empty_line do
75
- transitions from: %i[wait_content single_para idle], to: :idle
76
- transitions from: :in_block, to: :in_block
46
+ def explicit_version?
47
+ @definitions.reduce(false) do |res, definition|
48
+ res || !definition.explicit_version.nil?
77
49
  end
78
50
  end
79
51
 
80
- def code_block_delimiter(_match)
52
+ def code_block_delimiter(_match, line)
81
53
  @in_literal ^= true
54
+ line
82
55
  end
83
56
 
84
- def add_new_definition(match)
57
+ def add_new_definition(match, line)
85
58
  definition = Definition.new(match)
86
59
  @labels.merge(definition.labels)
87
60
  @definitions << definition
61
+ line
88
62
  end
89
63
 
90
- def add_line(_match)
91
- @definitions.last << @current_line
64
+ def ref_to_def(ref)
65
+ @definitions.find { |definition| definition.reference == ref }
92
66
  end
93
67
 
94
- def new_eref_setup(match)
95
- @eref[match[:refname].to_sym] ||= {}
68
+ def add_line(_match, line)
69
+ @definitions.last << line
70
+ line
71
+ end
96
72
 
97
- @eref[match[:refname].to_sym][match[:symb].to_sym] =
98
- match[:value]
73
+ def new_eref_setup(match, line)
74
+ @eref[match[:refname].to_sym] ||= {}
75
+ @eref[match[:refname].to_sym][match[:symb].to_sym] = match[:value]
76
+ line
99
77
  end
100
78
 
101
- def new_eref_def(match)
102
- @definitions.last.add_eref(
103
- match[:refname].to_sym,
104
- match[:extrefs]
105
- )
79
+ def new_eref_def(match, line)
80
+ @definitions.last.add_eref(match[:refname].to_sym, match[:extrefs])
81
+ line
106
82
  end
107
83
 
108
- def new_iref_def(_match)
84
+ def new_iref_def(_match, line)
109
85
  @iref = true
110
- @current_line.scan(DMRegexp::IREF_DEF) do |_|
86
+ line.scan(DMRegexp::IREF_DEF) do |_|
111
87
  @definitions.last.add_iref(Regexp.last_match[:intref])
112
88
  end
89
+ line
113
90
  end
114
91
 
115
- def new_attribute_conf(match)
92
+ def new_attribute_conf(match, line)
116
93
  @attributes[match[:attr].to_sym] = match[:prefix]
94
+ line
117
95
  end
118
96
 
119
- def new_attribute_value(match)
120
- @definitions.last.set_attribute(
121
- match[:attr].to_sym,
122
- match[:value]
123
- )
97
+ def new_attribute_value(match, line)
98
+ @definitions.last.set_attribute(match[:attr].to_sym, match[:value])
99
+ line
124
100
  end
125
101
 
126
- def new_variable_def(match)
102
+ def new_variable_def(match, line)
127
103
  @variables[match[:varname].to_sym] = match[:value]
104
+ line
128
105
  end
129
106
 
130
- def new_variable_use(_match)
131
- @current_line.scan(DMRegexp::VARIABLE_USE) do |_|
107
+ def new_variable_use(_match, line)
108
+ line.scan(DMRegexp::VARIABLE_USE) do |_|
132
109
  varname = Regexp.last_match[:varname]
133
110
  next if @variables[varname.to_sym].nil?
134
111
 
135
- @current_line = @current_line.gsub(
136
- "{#{varname}}", @variables[varname.to_sym]
137
- )
112
+ line = line.gsub("{#{varname}}", @variables[varname.to_sym])
138
113
  end
114
+ line
139
115
  end
140
116
 
141
- def parse(lines)
142
- lines.reject(&:commented?).each do |line|
143
- @current_line = line
144
- (@in_literal ? FILTERS : FILTERS_IN_LITERAL).each do |filter|
145
- next unless line.match(filter.regexp)
117
+ private
146
118
 
147
- public_send(filter.event, Regexp.last_match)
148
- break if filter.consumed_line
149
- end
119
+ def generate_event(event, match, line)
120
+ if respond_to?(event)
121
+ line = public_send(event, match, line)
122
+ else
123
+ @definition_parser.public_send(event, match, line)
150
124
  end
125
+ line
151
126
  end
152
127
  end
153
128
  end