metanorma-release 0.2.2 → 0.2.3
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +19 -1
- data/.rubocop_todo.yml +250 -319
- data/README.adoc +120 -233
- data/Rakefile +2 -2
- data/exe/metanorma-release +2 -2
- data/lib/metanorma/release/aggregation_pipeline.rb +59 -45
- data/lib/metanorma/release/asset_processor.rb +10 -8
- data/lib/metanorma/release/cache_store.rb +6 -6
- data/lib/metanorma/release/change_detector.rb +7 -3
- data/lib/metanorma/release/channel.rb +13 -39
- data/lib/metanorma/release/channel_filter.rb +26 -10
- data/lib/metanorma/release/cli.rb +129 -100
- data/lib/metanorma/release/commands/aggregate.rb +39 -54
- data/lib/metanorma/release/commands/package.rb +20 -12
- data/lib/metanorma/release/commands/{publish.rb → release_command.rb} +20 -12
- data/lib/metanorma/release/config.rb +104 -0
- data/lib/metanorma/release/content_hash.rb +11 -3
- data/lib/metanorma/release/delta_state.rb +55 -18
- data/lib/metanorma/release/file_routing.rb +8 -5
- data/lib/metanorma/release/index.rb +132 -0
- data/lib/metanorma/release/interfaces.rb +15 -15
- data/lib/metanorma/release/platform/github/manifest_reader.rb +4 -4
- data/lib/metanorma/release/platform/github/publisher.rb +23 -11
- data/lib/metanorma/release/platform/github/release_fetcher.rb +12 -3
- data/lib/metanorma/release/platform/github.rb +10 -7
- data/lib/metanorma/release/platform/local/directory_discoverer.rb +1 -1
- data/lib/metanorma/release/platform/local/fetcher.rb +17 -12
- data/lib/metanorma/release/platform/local/publisher.rb +9 -7
- data/lib/metanorma/release/platform/local.rb +4 -4
- data/lib/metanorma/release/platform/null/publisher.rb +3 -2
- data/lib/metanorma/release/platform/null.rb +1 -1
- data/lib/metanorma/release/platform.rb +3 -3
- data/lib/metanorma/release/platform_factory.rb +48 -29
- data/lib/metanorma/release/publication.rb +335 -0
- data/lib/metanorma/release/release_pipeline.rb +85 -52
- data/lib/metanorma/release/repo_ref.rb +5 -2
- data/lib/metanorma/release/site.rb +66 -0
- data/lib/metanorma/release/slug_strategy.rb +163 -0
- data/lib/metanorma/release/version.rb +1 -1
- data/lib/metanorma/release/zip_packager.rb +31 -8
- data/lib/metanorma/release.rb +68 -94
- metadata +22 -26
- data/lib/metanorma/release/aggregation_interfaces.rb +0 -27
- data/lib/metanorma/release/channel_audience.rb +0 -24
- data/lib/metanorma/release/channel_config.rb +0 -55
- data/lib/metanorma/release/channel_manifest.rb +0 -192
- data/lib/metanorma/release/channel_registry.rb +0 -60
- data/lib/metanorma/release/config_fetcher.rb +0 -11
- data/lib/metanorma/release/config_locator.rb +0 -37
- data/lib/metanorma/release/config_resolver.rb +0 -37
- data/lib/metanorma/release/document_id.rb +0 -45
- data/lib/metanorma/release/document_index.rb +0 -183
- data/lib/metanorma/release/document_metadata.rb +0 -39
- data/lib/metanorma/release/document_stage.rb +0 -86
- data/lib/metanorma/release/document_type.rb +0 -55
- data/lib/metanorma/release/document_version.rb +0 -50
- data/lib/metanorma/release/naming_strategy.rb +0 -158
- data/lib/metanorma/release/platform/github/config_fetcher.rb +0 -40
- data/lib/metanorma/release/platform/local/config_fetcher.rb +0 -20
- data/lib/metanorma/release/rake_tasks.rb +0 -71
- data/lib/metanorma/release/relaton_enricher.rb +0 -138
- data/lib/metanorma/release/release_metadata.rb +0 -79
- data/lib/metanorma/release/release_tag.rb +0 -49
- data/lib/metanorma/release/rxl_extractor.rb +0 -115
- data/lib/metanorma/release/stage_filter.rb +0 -18
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Metanorma
|
|
4
|
-
module Release
|
|
5
|
-
class DocumentStage
|
|
6
|
-
PUBLISHED_NAMES = %w[published in-force approved standard].freeze
|
|
7
|
-
|
|
8
|
-
STAGE_ABBREVS = {
|
|
9
|
-
'working-draft' => 'wd',
|
|
10
|
-
'committee-draft' => 'cd',
|
|
11
|
-
'draft-standard' => 'ds',
|
|
12
|
-
'final-draft' => 'fd',
|
|
13
|
-
'proposal' => 'proposal',
|
|
14
|
-
'informational' => 'info',
|
|
15
|
-
'withdrawn' => 'withdrawn',
|
|
16
|
-
'cancelled' => 'cancelled'
|
|
17
|
-
}.freeze
|
|
18
|
-
|
|
19
|
-
ISO_STAGE_MAP = {
|
|
20
|
-
20 => 'working-draft',
|
|
21
|
-
30 => 'committee-draft',
|
|
22
|
-
40 => 'draft-standard',
|
|
23
|
-
50 => 'final-draft',
|
|
24
|
-
60 => 'published',
|
|
25
|
-
95 => 'withdrawn'
|
|
26
|
-
}.freeze
|
|
27
|
-
|
|
28
|
-
def self.from_status(status_string)
|
|
29
|
-
raise ArgumentError, 'Stage cannot be empty' if status_string.nil? || status_string.strip.empty?
|
|
30
|
-
|
|
31
|
-
normalized = status_string.to_s.downcase.strip.gsub(/\s+/, '-')
|
|
32
|
-
new(normalized)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def self.from_iso_stage(stage, _substage = nil)
|
|
36
|
-
name = ISO_STAGE_MAP[stage.to_i] || ISO_STAGE_MAP.values.first
|
|
37
|
-
new(name)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def self.published
|
|
41
|
-
new('published')
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def self.working_draft
|
|
45
|
-
new('working-draft')
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def initialize(name)
|
|
49
|
-
@name = name
|
|
50
|
-
freeze
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def to_s
|
|
54
|
-
@name
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def published?
|
|
58
|
-
PUBLISHED_NAMES.include?(@name)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def draft?
|
|
62
|
-
!published? && @name != 'withdrawn' && @name != 'cancelled'
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def withdrawn?
|
|
66
|
-
@name == 'withdrawn'
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def cancelled?
|
|
70
|
-
@name == 'cancelled'
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def tag_suffix
|
|
74
|
-
STAGE_ABBREVS[@name].to_s
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def eql?(other)
|
|
78
|
-
other.is_a?(self.class) && @name == other.to_s
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def hash
|
|
82
|
-
@name.hash
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Metanorma
|
|
4
|
-
module Release
|
|
5
|
-
module DocumentType
|
|
6
|
-
STANDARD = 'standard'
|
|
7
|
-
IETF_DRAFT = 'ietf-draft'
|
|
8
|
-
IETF_RFC = 'ietf-rfc'
|
|
9
|
-
ISO = 'iso'
|
|
10
|
-
IEC = 'iec'
|
|
11
|
-
IEEE = 'ieee'
|
|
12
|
-
ITU = 'itu'
|
|
13
|
-
BIPM = 'bipm'
|
|
14
|
-
IHO = 'iho'
|
|
15
|
-
OGC = 'ogc'
|
|
16
|
-
OIML = 'oiml'
|
|
17
|
-
UN = 'un'
|
|
18
|
-
CSA = 'csa'
|
|
19
|
-
PDFA = 'pdfa'
|
|
20
|
-
MPFA = 'mpfa'
|
|
21
|
-
M3AAWG = 'm3aawg'
|
|
22
|
-
RIBOSE = 'ribose'
|
|
23
|
-
|
|
24
|
-
DETECTION_RULES = [
|
|
25
|
-
[/^RFC\s/i, IETF_RFC],
|
|
26
|
-
[/^draft-/i, IETF_DRAFT],
|
|
27
|
-
[/^ISO/i, ISO],
|
|
28
|
-
[/^IEC/i, IEC],
|
|
29
|
-
[/^IEEE/i, IEEE],
|
|
30
|
-
[/^ITU-/i, ITU],
|
|
31
|
-
[/^BIPM/i, BIPM],
|
|
32
|
-
[/^[A-Z]-\d/i, IHO],
|
|
33
|
-
[/^\d{2}-\d{2,3}/, OGC],
|
|
34
|
-
[/^OIML/i, OIML],
|
|
35
|
-
[/^GE\./i, UN],
|
|
36
|
-
[/^csa-/i, CSA],
|
|
37
|
-
[/^(AN|BPG|TN)\s/i, PDFA],
|
|
38
|
-
[%r{^SU/}i, MPFA],
|
|
39
|
-
[/^M3AAWG/i, M3AAWG],
|
|
40
|
-
[/^Ribose/i, RIBOSE]
|
|
41
|
-
].freeze
|
|
42
|
-
|
|
43
|
-
def self.from_identifier(raw_id)
|
|
44
|
-
id = raw_id.to_s.strip
|
|
45
|
-
return STANDARD if id.empty?
|
|
46
|
-
|
|
47
|
-
DETECTION_RULES.each do |pattern, type|
|
|
48
|
-
return type if id.match?(pattern)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
STANDARD
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Metanorma
|
|
4
|
-
module Release
|
|
5
|
-
class DocumentVersion
|
|
6
|
-
attr_reader :edition, :stage
|
|
7
|
-
|
|
8
|
-
def self.from(edition, stage)
|
|
9
|
-
ed = edition.to_s.strip
|
|
10
|
-
ed = '0' if ed.empty?
|
|
11
|
-
new(edition: ed, stage: stage)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def self.published(edition:)
|
|
15
|
-
new(edition: edition.to_s.strip, stage: DocumentStage.published)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def initialize(edition:, stage:)
|
|
19
|
-
@edition = edition
|
|
20
|
-
@stage = stage
|
|
21
|
-
freeze
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def tag_component
|
|
25
|
-
base = "ed#{edition}"
|
|
26
|
-
return base if stage.published?
|
|
27
|
-
|
|
28
|
-
suffix = stage.tag_suffix
|
|
29
|
-
suffix.empty? ? base : "#{base}-#{suffix}"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def pre_release?
|
|
33
|
-
stage.draft?
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def file_name(doc_id)
|
|
37
|
-
base = "#{doc_id}-#{tag_component}"
|
|
38
|
-
"#{base}.zip"
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def eql?(other)
|
|
42
|
-
other.is_a?(self.class) && edition == other.edition && stage.eql?(other.stage)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def hash
|
|
46
|
-
[edition, stage].hash
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Metanorma
|
|
4
|
-
module Release
|
|
5
|
-
module NamingStrategy
|
|
6
|
-
def compute_tag(id, version)
|
|
7
|
-
raise NotImplementedError, "#{self.class} must implement #compute_tag"
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def compute_asset_name(id, version)
|
|
11
|
-
raise NotImplementedError, "#{self.class} must implement #compute_asset_name"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def compute_canonical_base(id, version)
|
|
15
|
-
raise NotImplementedError, "#{self.class} must implement #compute_canonical_base"
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
class EditionNaming
|
|
20
|
-
include NamingStrategy
|
|
21
|
-
|
|
22
|
-
def compute_tag(id, version)
|
|
23
|
-
tag = "#{id}/#{version.tag_component}"
|
|
24
|
-
ReleaseTag.create(tag, pre_release: version.pre_release?)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def compute_asset_name(id, version)
|
|
28
|
-
"#{id}-#{version.tag_component}.zip"
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def compute_canonical_base(id, version)
|
|
32
|
-
"#{id}-#{version.tag_component}"
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
class VersionNaming
|
|
37
|
-
include NamingStrategy
|
|
38
|
-
|
|
39
|
-
def compute_tag(id, version)
|
|
40
|
-
tag = "#{id}/v#{version.edition}"
|
|
41
|
-
ReleaseTag.create(tag, pre_release: version.pre_release?)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def compute_asset_name(id, version)
|
|
45
|
-
"#{id}-v#{version.edition}.zip"
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def compute_canonical_base(id, version)
|
|
49
|
-
"#{id}-v#{version.edition}"
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
class InternetDraftNaming
|
|
54
|
-
include NamingStrategy
|
|
55
|
-
|
|
56
|
-
DRAFT_PATTERN = /\Adraft-ietf-([a-z0-9-]+?)-(\d+)\z/i
|
|
57
|
-
|
|
58
|
-
def compute_tag(id, version)
|
|
59
|
-
match = id.match(DRAFT_PATTERN)
|
|
60
|
-
return fallback_tag(id, version) unless match
|
|
61
|
-
|
|
62
|
-
name = match[1]
|
|
63
|
-
num = match[2]
|
|
64
|
-
ReleaseTag.create("id-#{name}/#{num}", pre_release: true)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def compute_asset_name(id, _version)
|
|
68
|
-
"#{id}.zip"
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def compute_canonical_base(id, _version)
|
|
72
|
-
id.to_s
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
private
|
|
76
|
-
|
|
77
|
-
def fallback_tag(id, _version)
|
|
78
|
-
tag = "#{id}/draft"
|
|
79
|
-
ReleaseTag.create(tag, pre_release: true)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
class RfcNaming
|
|
84
|
-
include NamingStrategy
|
|
85
|
-
|
|
86
|
-
def compute_tag(id, version)
|
|
87
|
-
tag = "#{id}/ed#{version.edition}"
|
|
88
|
-
ReleaseTag.create(tag, pre_release: version.pre_release?)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def compute_asset_name(id, _version)
|
|
92
|
-
"#{id}.zip"
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def compute_canonical_base(id, version)
|
|
96
|
-
"#{id}-ed#{version.edition}"
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
class DraftSuffixNaming
|
|
101
|
-
include NamingStrategy
|
|
102
|
-
|
|
103
|
-
DRAFT_SUFFIX = /-d(\d+)\z/
|
|
104
|
-
|
|
105
|
-
def compute_tag(id, version)
|
|
106
|
-
match = id.to_s.match(DRAFT_SUFFIX)
|
|
107
|
-
return @fallback.compute_tag(id, version) unless match
|
|
108
|
-
|
|
109
|
-
base = id.to_s.sub(DRAFT_SUFFIX, '')
|
|
110
|
-
num = match[1]
|
|
111
|
-
ReleaseTag.create("#{base}/#{num}", pre_release: true)
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def compute_asset_name(id, version)
|
|
115
|
-
match = id.to_s.match(DRAFT_SUFFIX)
|
|
116
|
-
return @fallback.compute_asset_name(id, version) unless match
|
|
117
|
-
|
|
118
|
-
"#{id}.zip"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def compute_canonical_base(id, version)
|
|
122
|
-
match = id.to_s.match(DRAFT_SUFFIX)
|
|
123
|
-
return @fallback.compute_canonical_base(id, version) unless match
|
|
124
|
-
|
|
125
|
-
id.to_s
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def initialize
|
|
129
|
-
@fallback = EditionNaming.new
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
class NamingRegistry
|
|
134
|
-
def initialize(default: EditionNaming.new)
|
|
135
|
-
@default = default
|
|
136
|
-
@strategies = {}
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def register(document_type, strategy)
|
|
140
|
-
@strategies[document_type] = strategy
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def resolve(document_type)
|
|
144
|
-
@strategies.fetch(document_type, @default)
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def self.default_registry
|
|
148
|
-
registry = new
|
|
149
|
-
registry.register(DocumentType::IETF_DRAFT, InternetDraftNaming.new)
|
|
150
|
-
registry.register(DocumentType::IETF_RFC, RfcNaming.new)
|
|
151
|
-
registry.register(DocumentType::IEEE, DraftSuffixNaming.new)
|
|
152
|
-
registry.register(DocumentType::IHO, VersionNaming.new)
|
|
153
|
-
registry.register(DocumentType::OGC, VersionNaming.new)
|
|
154
|
-
registry
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'yaml'
|
|
4
|
-
|
|
5
|
-
module Metanorma
|
|
6
|
-
module Release
|
|
7
|
-
module Platform
|
|
8
|
-
module GitHub
|
|
9
|
-
class ConfigFetcher
|
|
10
|
-
include Metanorma::Release::ConfigFetcher
|
|
11
|
-
|
|
12
|
-
def initialize(client:)
|
|
13
|
-
@client = client
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def fetch(source)
|
|
17
|
-
repo, path = parse_source(source)
|
|
18
|
-
content = @client.contents(repo, path: path)
|
|
19
|
-
return nil unless content
|
|
20
|
-
|
|
21
|
-
ChannelConfig.from_yaml(content['content'].unpack1('m0'))
|
|
22
|
-
rescue StandardError
|
|
23
|
-
nil
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
def parse_source(source)
|
|
29
|
-
if source.include?('#')
|
|
30
|
-
parts = source.split('#', 2)
|
|
31
|
-
[parts[0], parts[1]]
|
|
32
|
-
else
|
|
33
|
-
[source, 'channels.yml']
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Metanorma
|
|
4
|
-
module Release
|
|
5
|
-
module Platform
|
|
6
|
-
module Local
|
|
7
|
-
class ConfigFetcher
|
|
8
|
-
include Metanorma::Release::ConfigFetcher
|
|
9
|
-
|
|
10
|
-
def fetch(source)
|
|
11
|
-
path = source.sub(/\Alocal:/, '')
|
|
12
|
-
return nil unless File.exist?(path)
|
|
13
|
-
|
|
14
|
-
ChannelConfig.from_file(path)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'rake'
|
|
4
|
-
require 'ostruct'
|
|
5
|
-
|
|
6
|
-
module Metanorma
|
|
7
|
-
module Release
|
|
8
|
-
class RakeTasks
|
|
9
|
-
include Rake::DSL
|
|
10
|
-
|
|
11
|
-
def self.install(&block)
|
|
12
|
-
new(&block).install
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def initialize(&block)
|
|
16
|
-
@config = OpenStruct.new(
|
|
17
|
-
output_dir: '_site',
|
|
18
|
-
manifest: 'metanorma.release.yml',
|
|
19
|
-
platform: 'github',
|
|
20
|
-
concurrency: 4,
|
|
21
|
-
dest: 'dist',
|
|
22
|
-
source: 'github',
|
|
23
|
-
organizations: [],
|
|
24
|
-
topic: 'metanorma-release'
|
|
25
|
-
)
|
|
26
|
-
block&.call(@config)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def install
|
|
30
|
-
install_package_task
|
|
31
|
-
install_publish_task
|
|
32
|
-
install_aggregate_task
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def install_package_task
|
|
38
|
-
desc 'Package compiled documents'
|
|
39
|
-
task :"mn:package" do
|
|
40
|
-
argv = ['--output-dir', @config.output_dir,
|
|
41
|
-
'--dest', @config.dest,
|
|
42
|
-
'--manifest', @config.manifest]
|
|
43
|
-
CLI.run_package(argv)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def install_publish_task
|
|
48
|
-
desc 'Package and publish documents'
|
|
49
|
-
task :"mn:publish" do
|
|
50
|
-
argv = ['--platform', @config.platform,
|
|
51
|
-
'--output-dir', @config.output_dir,
|
|
52
|
-
'--manifest', @config.manifest,
|
|
53
|
-
'--concurrency', @config.concurrency.to_s]
|
|
54
|
-
CLI.run_publish(argv)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def install_aggregate_task
|
|
59
|
-
desc 'Aggregate released documents'
|
|
60
|
-
task :"mn:aggregate" do
|
|
61
|
-
argv = ['--source', @config.source,
|
|
62
|
-
'--output-dir', @config.output_dir,
|
|
63
|
-
'--concurrency', @config.concurrency.to_s]
|
|
64
|
-
argv += ['--organizations', @config.organizations.join(',')] if @config.organizations.any?
|
|
65
|
-
argv += ['--topic', @config.topic] if @config.topic
|
|
66
|
-
CLI.run_aggregate(argv)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'relaton/bib'
|
|
4
|
-
require 'json'
|
|
5
|
-
require 'yaml'
|
|
6
|
-
require 'fileutils'
|
|
7
|
-
|
|
8
|
-
module Metanorma
|
|
9
|
-
module Release
|
|
10
|
-
class RelatonEnricher
|
|
11
|
-
EnrichResult = Struct.new(
|
|
12
|
-
:item_count, :output_dir, :documents,
|
|
13
|
-
keyword_init: true
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
@flavor_registry = {}
|
|
17
|
-
|
|
18
|
-
class << self
|
|
19
|
-
def register_flavor(name, &loader)
|
|
20
|
-
@flavor_registry[name.to_s] = loader
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
attr_reader :flavor_registry
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
register_flavor('calconnect') do
|
|
27
|
-
require 'relaton/calconnect'
|
|
28
|
-
Relaton::Calconnect::Item
|
|
29
|
-
end
|
|
30
|
-
register_flavor('cc') do
|
|
31
|
-
require 'relaton/calconnect'
|
|
32
|
-
Relaton::Calconnect::Item
|
|
33
|
-
end
|
|
34
|
-
register_flavor('iso') do
|
|
35
|
-
require 'relaton/iso'
|
|
36
|
-
Relaton::Iso::Item
|
|
37
|
-
end
|
|
38
|
-
register_flavor('iec') do
|
|
39
|
-
require 'relaton/iec'
|
|
40
|
-
Relaton::Iec::BibliographicItem
|
|
41
|
-
end
|
|
42
|
-
register_flavor('ogc') do
|
|
43
|
-
require 'relaton/ogc'
|
|
44
|
-
Relaton::Ogc::BibliographicItem
|
|
45
|
-
end
|
|
46
|
-
register_flavor('ietf') do
|
|
47
|
-
require 'relaton/ietf'
|
|
48
|
-
Relaton::Ietf::BibliographicItem
|
|
49
|
-
end
|
|
50
|
-
register_flavor('bipm') do
|
|
51
|
-
require 'relaton/bipm'
|
|
52
|
-
Relaton::Bipm::BibliographicItem
|
|
53
|
-
end
|
|
54
|
-
register_flavor('itu') do
|
|
55
|
-
require 'relaton/itu'
|
|
56
|
-
Relaton::Itu::BibliographicItem
|
|
57
|
-
end
|
|
58
|
-
register_flavor('nist') do
|
|
59
|
-
require 'relaton/nist'
|
|
60
|
-
Relaton::Nist::BibliographicItem
|
|
61
|
-
end
|
|
62
|
-
register_flavor('un') do
|
|
63
|
-
require 'relaton/un'
|
|
64
|
-
Relaton::Un::BibliographicItem
|
|
65
|
-
end
|
|
66
|
-
register_flavor('bsi') do
|
|
67
|
-
require 'relaton/bsi'
|
|
68
|
-
Relaton::Bsi::BibliographicItem
|
|
69
|
-
end
|
|
70
|
-
register_flavor('ribose') do
|
|
71
|
-
require 'relaton/ribose'
|
|
72
|
-
Relaton::Ribose::Item
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def initialize(flavor: nil, registry_name: 'Document Registry')
|
|
76
|
-
@flavor = flavor
|
|
77
|
-
@registry_name = registry_name
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def enrich(document_index, output_dir, bib_dir: 'relaton')
|
|
81
|
-
return nil if document_index.empty?
|
|
82
|
-
|
|
83
|
-
flavor = resolve_flavor(document_index)
|
|
84
|
-
klass = resolve_class(flavor)
|
|
85
|
-
documents = enrich_documents(document_index, output_dir, klass)
|
|
86
|
-
return nil if documents.empty?
|
|
87
|
-
|
|
88
|
-
dest = File.join(output_dir, bib_dir)
|
|
89
|
-
write_index(documents, dest)
|
|
90
|
-
|
|
91
|
-
EnrichResult.new(item_count: documents.length, output_dir: dest,
|
|
92
|
-
documents: documents)
|
|
93
|
-
rescue LoadError
|
|
94
|
-
warn ' (relaton gem not available — bibliography skipped)'
|
|
95
|
-
nil
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
private
|
|
99
|
-
|
|
100
|
-
def resolve_flavor(document_index)
|
|
101
|
-
@flavor || document_index.documents.first&.flavor
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def resolve_class(flavor)
|
|
105
|
-
loader = self.class.flavor_registry[flavor.to_s]
|
|
106
|
-
return loader.call if loader
|
|
107
|
-
|
|
108
|
-
Relaton::Bib::Item
|
|
109
|
-
rescue LoadError
|
|
110
|
-
warn " (relaton-#{flavor} gem not available — using base Relaton::Bib::Item)"
|
|
111
|
-
Relaton::Bib::Item
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def enrich_documents(document_index, output_dir, klass)
|
|
115
|
-
document_index.documents.map do |doc|
|
|
116
|
-
rxl = doc.files.find { |f| f.extension == 'rxl' }
|
|
117
|
-
path = rxl && File.join(output_dir, rxl.path)
|
|
118
|
-
|
|
119
|
-
bib = (klass.from_xml(File.read(path)) if path && File.exist?(path))
|
|
120
|
-
|
|
121
|
-
enriched = doc.to_h
|
|
122
|
-
enriched['bibliographic'] = bib.to_h if bib
|
|
123
|
-
enriched
|
|
124
|
-
rescue StandardError => e
|
|
125
|
-
warn " Skip #{File.basename(path)}: #{e.message}"
|
|
126
|
-
doc.to_h
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def write_index(documents, dest)
|
|
131
|
-
FileUtils.mkdir_p(dest)
|
|
132
|
-
index = { 'root' => { 'title' => @registry_name, 'items' => documents } }
|
|
133
|
-
File.write(File.join(dest, 'index.json'), JSON.pretty_generate(index))
|
|
134
|
-
File.write(File.join(dest, 'index.yaml'), YAML.dump(index))
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'json'
|
|
4
|
-
|
|
5
|
-
module Metanorma
|
|
6
|
-
module Release
|
|
7
|
-
class ReleaseMetadata
|
|
8
|
-
SCHEMA_VERSION = 1
|
|
9
|
-
|
|
10
|
-
def self.from_document(metadata, channels:)
|
|
11
|
-
data = {
|
|
12
|
-
'version' => SCHEMA_VERSION,
|
|
13
|
-
'id' => metadata.id.to_s,
|
|
14
|
-
'title' => metadata.title,
|
|
15
|
-
'edition' => metadata.version.edition,
|
|
16
|
-
'stage' => metadata.version.stage.to_s,
|
|
17
|
-
'doctype' => metadata.doctype.to_s,
|
|
18
|
-
'revdate' => metadata.revdate,
|
|
19
|
-
'formats' => metadata.formats,
|
|
20
|
-
'channels' => channels.map(&:to_s),
|
|
21
|
-
'flavor' => metadata.flavor,
|
|
22
|
-
'sourcePath' => metadata.source_path
|
|
23
|
-
}
|
|
24
|
-
new(data)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def self.from_json(json_string)
|
|
28
|
-
data = JSON.parse(json_string)
|
|
29
|
-
raise ArgumentError, 'Missing required field: id' unless data['id']
|
|
30
|
-
raise ArgumentError, 'Missing required field: title' unless data['title']
|
|
31
|
-
|
|
32
|
-
new(data)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def self.from_release_body(body)
|
|
36
|
-
return nil if body.nil? || body.empty?
|
|
37
|
-
|
|
38
|
-
match = body.match(/<!--\s*mn-release-metadata\s*\n(.*?)\n-->/m)
|
|
39
|
-
return nil unless match
|
|
40
|
-
|
|
41
|
-
json_str = match[1]
|
|
42
|
-
begin
|
|
43
|
-
from_json(json_str)
|
|
44
|
-
rescue JSON::ParserError
|
|
45
|
-
nil
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def initialize(data)
|
|
50
|
-
@data = data
|
|
51
|
-
freeze
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def to_json(*_args)
|
|
55
|
-
JSON.generate(@data)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def to_release_body
|
|
59
|
-
json_str = JSON.generate(@data)
|
|
60
|
-
"<!-- mn-release-metadata\n#{json_str}\n-->"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def to_h
|
|
64
|
-
@data.dup
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def id = @data['id']
|
|
68
|
-
def title = @data['title']
|
|
69
|
-
def edition = @data['edition']
|
|
70
|
-
def stage = @data['stage']
|
|
71
|
-
def doctype = @data['doctype']
|
|
72
|
-
def revdate = @data['revdate']
|
|
73
|
-
def formats = @data['formats'] || []
|
|
74
|
-
def channels = @data['channels'] || []
|
|
75
|
-
def flavor = @data['flavor']
|
|
76
|
-
def source_path = @data['sourcePath']
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|