baltix 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +44 -0
- data/.gitignore +10 -0
- data/Gemfile +8 -0
- data/LICENSE +8 -0
- data/README.md +60 -0
- data/Rakefile +8 -0
- data/TODO +84 -0
- data/baltix.gemspec +39 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/baltix +4 -0
- data/lib/baltix/actor/copy.rb +19 -0
- data/lib/baltix/actor/link.rb +20 -0
- data/lib/baltix/actor/spec.rb +25 -0
- data/lib/baltix/actor/touch.rb +17 -0
- data/lib/baltix/actor.rb +75 -0
- data/lib/baltix/cli.rb +173 -0
- data/lib/baltix/deps.rb +280 -0
- data/lib/baltix/dsl.rb +311 -0
- data/lib/baltix/extensions.rb +536 -0
- data/lib/baltix/i18n.rb +64 -0
- data/lib/baltix/loader/cmake.rb +11 -0
- data/lib/baltix/loader/git-version-gen.rb +36 -0
- data/lib/baltix/loader/mast.rb +139 -0
- data/lib/baltix/loader/pom.rb +27 -0
- data/lib/baltix/loader/rookbook.rb +26 -0
- data/lib/baltix/loader/yaml.rb +18 -0
- data/lib/baltix/loader.rb +192 -0
- data/lib/baltix/log.rb +73 -0
- data/lib/baltix/rake.rb +57 -0
- data/lib/baltix/scheme.erb.yaml +20 -0
- data/lib/baltix/source/base.rb +438 -0
- data/lib/baltix/source/fake.rb +17 -0
- data/lib/baltix/source/gem.rb +407 -0
- data/lib/baltix/source/gemfile.rb +35 -0
- data/lib/baltix/source/rakefile.rb +24 -0
- data/lib/baltix/source.rb +57 -0
- data/lib/baltix/space/spec.rb +11 -0
- data/lib/baltix/space.rb +424 -0
- data/lib/baltix/spec/rpm/name.rb +155 -0
- data/lib/baltix/spec/rpm/parser.rb +412 -0
- data/lib/baltix/spec/rpm/secondary.rb +170 -0
- data/lib/baltix/spec/rpm/spec_core.rb +580 -0
- data/lib/baltix/spec/rpm.erb +188 -0
- data/lib/baltix/spec/rpm.rb +822 -0
- data/lib/baltix/spec.rb +48 -0
- data/lib/baltix/version.rb +3 -0
- data/lib/baltix.rb +19 -0
- data/locale/en_US.UTF-8.yaml +27 -0
- data/locale/ru_RU.UTF-8.yaml +23 -0
- metadata +216 -0
data/lib/baltix/space.rb
ADDED
@@ -0,0 +1,424 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'baltix/version'
|
4
|
+
require 'baltix/log'
|
5
|
+
require 'baltix/source'
|
6
|
+
require 'baltix/spec'
|
7
|
+
require 'baltix/cli'
|
8
|
+
|
9
|
+
class Baltix::Space
|
10
|
+
include Baltix::Log
|
11
|
+
|
12
|
+
class InvalidSpaceFileError < StandardError; end
|
13
|
+
|
14
|
+
TYPES = {
|
15
|
+
sources: Baltix::Source
|
16
|
+
}
|
17
|
+
|
18
|
+
STATES = {
|
19
|
+
invalid: ->(_, source, _) { !source.valid? },
|
20
|
+
disabled: ->(space, source, _) { space.is_disabled?(source) },
|
21
|
+
duplicated: ->(_, _, dup) { dup },
|
22
|
+
}
|
23
|
+
|
24
|
+
TYPE_CHARS = {
|
25
|
+
fake: '·',
|
26
|
+
gem: '*',
|
27
|
+
gemfile: '&',
|
28
|
+
rakefile: '^',
|
29
|
+
}
|
30
|
+
|
31
|
+
STATUS_CHARS = {
|
32
|
+
invalid: 'X',
|
33
|
+
disabled: '-',
|
34
|
+
duplicated: '=',
|
35
|
+
valid: 'V',
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
Gem.load_yaml
|
40
|
+
|
41
|
+
@@space = {}
|
42
|
+
@@options = {}
|
43
|
+
|
44
|
+
# +options+ property returns the hash of the loaded options if any
|
45
|
+
#
|
46
|
+
# options #=> {...}
|
47
|
+
#
|
48
|
+
attr_reader :options, :state
|
49
|
+
|
50
|
+
# +name+ returns a default name of the space with a prefix if any. It returns name of a source when
|
51
|
+
# its root is the same as the space's root, or returns name defined in the spec if any.
|
52
|
+
# If no spec defined returns name of last folder in rootdir or "root" as a default main source name.
|
53
|
+
#
|
54
|
+
# space.name # => space-name
|
55
|
+
#
|
56
|
+
def name
|
57
|
+
return @name if @name
|
58
|
+
|
59
|
+
@name = spec&.name || main_source&.name
|
60
|
+
end
|
61
|
+
|
62
|
+
# +version+ returns a default version for the space. Returns version of a source when
|
63
|
+
# its root is the same as the space's root, or returns version defined in the spec if any,
|
64
|
+
# or returns default one.
|
65
|
+
#
|
66
|
+
# space.version # => 2.1.1
|
67
|
+
#
|
68
|
+
def version
|
69
|
+
return @version if @version
|
70
|
+
|
71
|
+
@version ||= main_source&.version || spec&.version
|
72
|
+
end
|
73
|
+
|
74
|
+
attr_writer :rootdir
|
75
|
+
|
76
|
+
# +rootdir+ returns the root dir for the space got from the options,
|
77
|
+
# defaulting to the current folder.
|
78
|
+
#
|
79
|
+
# rootdir #=> /root/dir/for/the/space
|
80
|
+
#
|
81
|
+
def rootdir
|
82
|
+
@rootdir ||= read_attribute(:rootdir) || Dir.pwd
|
83
|
+
end
|
84
|
+
|
85
|
+
# +main_source+ selects main source from the list of sources when source root dir is the space's one and
|
86
|
+
# source's name contains minimum name size among the matching sources
|
87
|
+
#
|
88
|
+
def main_source
|
89
|
+
return @main_source if @main_source
|
90
|
+
|
91
|
+
reals = valid_sources.select { |source| !source.is_a?(Baltix::Source::Fake) }
|
92
|
+
if spec && !spec.state.blank?
|
93
|
+
specen_source = reals.find { |real| spec.state["name"] === real.name }
|
94
|
+
end
|
95
|
+
|
96
|
+
root_source ||= valid_sources.sort {|x, y| x.name.size <=> y.name.size }.find { |source| source.rootdir == rootdir }
|
97
|
+
@main_source =
|
98
|
+
specen_source || root_source.is_a?(Baltix::Source::Fake) && reals.size == 1 && reals.first || root_source
|
99
|
+
end
|
100
|
+
|
101
|
+
def time_stamp
|
102
|
+
Time.now.strftime("%Y%m%d")
|
103
|
+
end
|
104
|
+
|
105
|
+
# +changes+ returns a list of open-struct formatted changes in the space or
|
106
|
+
# spec defined if any, otherwise returns blank array.
|
107
|
+
#
|
108
|
+
# space.changes # => []
|
109
|
+
#
|
110
|
+
def changes
|
111
|
+
@changes ||= spec&.changes || main_source&.respond_to?(:changes) && main_source.changes || []
|
112
|
+
end
|
113
|
+
|
114
|
+
# +summaries+ returns an open-struct formatted summaries with locales as keys
|
115
|
+
# in the space or spec defined if any, otherwise returns blank open struct.
|
116
|
+
#
|
117
|
+
# space.summaries # => #<OpenStruct en_US.UTF-8: ...>
|
118
|
+
#
|
119
|
+
def summaries
|
120
|
+
return @summaries if @summaries
|
121
|
+
|
122
|
+
if summaries = spec&.summaries || state.summaries
|
123
|
+
summaries
|
124
|
+
elsif summary = main_source&.summary
|
125
|
+
{ Baltix::I18n.default_locale => summary }.to_os
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# +licenses+ returns license list defined in all the valid sources found in the space.
|
130
|
+
#
|
131
|
+
# space.licenses => # ["MIT"]
|
132
|
+
#
|
133
|
+
def licenses
|
134
|
+
return @licenses if @licenses
|
135
|
+
|
136
|
+
licenses = valid_sources.map { |source| source.licenses rescue [] }.flatten.uniq
|
137
|
+
|
138
|
+
@licenses = !licenses.blank? && licenses || spec&.licenses || []
|
139
|
+
end
|
140
|
+
|
141
|
+
# +dependencies+ returns all the valid source dependencies list as an array of Gem::Dependency
|
142
|
+
# objects, otherwise returning blank array.
|
143
|
+
def dependencies
|
144
|
+
@dependencies ||= valid_sources.map do |source|
|
145
|
+
source.respond_to?(:dependencies) && source.dependencies || []
|
146
|
+
end.flatten.reject do |dep|
|
147
|
+
match_platform?(dep) || sources.any? do |s|
|
148
|
+
dep.name == s.name &&
|
149
|
+
dep.requirement.satisfied_by?(Gem::Version.new(s.version))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def match_platform? dep
|
155
|
+
if dep.respond_to?(:platforms)
|
156
|
+
(dep.platforms & options.skip_platforms).any?
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def files
|
161
|
+
@files ||= valid_sources.map { |s| s.files rescue [] }.flatten.uniq
|
162
|
+
end
|
163
|
+
|
164
|
+
def executables
|
165
|
+
@executables ||= valid_sources.map { |s| s.executables rescue [] }.flatten.uniq
|
166
|
+
end
|
167
|
+
|
168
|
+
def docs
|
169
|
+
@docs ||= valid_sources.map { |s| s.docs rescue [] }.flatten.uniq
|
170
|
+
end
|
171
|
+
|
172
|
+
def compilables
|
173
|
+
@compilables ||= valid_sources.map { |s| s.extensions rescue [] }.flatten.uniq
|
174
|
+
end
|
175
|
+
|
176
|
+
# +sources+ returns all the sources in the space. It will load from the space sources,
|
177
|
+
# or by default will search sources in the provided folder or the current one.
|
178
|
+
#
|
179
|
+
# space.sources => # [#<Baltix::Source:...>, #<...>]
|
180
|
+
#
|
181
|
+
def sources
|
182
|
+
@sources ||= stat_sources.map { |x| x.first }
|
183
|
+
end
|
184
|
+
|
185
|
+
# +valid_sources+ returns all the valid sources based on the current source list.
|
186
|
+
#
|
187
|
+
# space.valid_sources => # [#<Baltix::Source:...>, #<...>]
|
188
|
+
#
|
189
|
+
# def valid_sources
|
190
|
+
# @valid_sources ||= sources.select do |source|
|
191
|
+
# source.valid? && is_regarded?(source)
|
192
|
+
# end
|
193
|
+
# end
|
194
|
+
def valid_sources
|
195
|
+
@valid_sources = stat_sources.map {|(source, status)| status == :valid && source || nil }.compact
|
196
|
+
end
|
197
|
+
|
198
|
+
# def is_regarded? source
|
199
|
+
# regarded_names.any? {|i| i === source.name } ||
|
200
|
+
# !ignored_names.any? {|i| i === source.name } &&
|
201
|
+
# !ignored_path_tokens.any? {|t| /\/#{t}\// =~ source.source_file }
|
202
|
+
# end
|
203
|
+
|
204
|
+
def ignored_names
|
205
|
+
@ignored_names ||= (read_attribute(:ignored_names) || [])
|
206
|
+
end
|
207
|
+
|
208
|
+
def regarded_names
|
209
|
+
@regarded_names ||= read_attribute(:regarded_names) || []
|
210
|
+
end
|
211
|
+
|
212
|
+
def ignored_path_tokens
|
213
|
+
@ignored_path_tokens ||= (read_attribute(:ignored_path_tokens) || [])
|
214
|
+
end
|
215
|
+
|
216
|
+
def spec_type
|
217
|
+
@spec_type ||= read_attribute(:spec_type) || spec && spec.class.to_s.split("::").last.downcase
|
218
|
+
end
|
219
|
+
|
220
|
+
def read_attribute attr
|
221
|
+
options.send(attr) || state.send(attr)
|
222
|
+
end
|
223
|
+
|
224
|
+
def options_for type
|
225
|
+
@@options[type] = type::OPTIONS.map do |option|
|
226
|
+
value = self.options[option] || self.respond_to?(option) && self.send(option) || nil
|
227
|
+
|
228
|
+
[ option, value ]
|
229
|
+
end.compact.to_os
|
230
|
+
end
|
231
|
+
|
232
|
+
# +spec+ property returns the hash of the loaded spec if any, it can be freely
|
233
|
+
# reassigned.
|
234
|
+
#
|
235
|
+
# spec #=> {...}
|
236
|
+
#
|
237
|
+
def spec
|
238
|
+
@spec ||= gen_spec
|
239
|
+
end
|
240
|
+
|
241
|
+
def spec= value
|
242
|
+
gen_spec(value)
|
243
|
+
end
|
244
|
+
|
245
|
+
def is_disabled? source
|
246
|
+
options.ignored_path_tokens.any? { |t| /\/#{t}\// =~ source.source_file } ||
|
247
|
+
options.regarded_names.all? { |i| !i.match?(source.name) } &&
|
248
|
+
options.ignored_names.any? { |i| i === source.name }
|
249
|
+
end
|
250
|
+
|
251
|
+
protected
|
252
|
+
|
253
|
+
def gen_spec spec_in = nil
|
254
|
+
spec_pre = spec_in || state.spec
|
255
|
+
|
256
|
+
@spec =
|
257
|
+
if spec_pre.is_a?(Baltix::Spec::Rpm)
|
258
|
+
spec_pre
|
259
|
+
elsif spec_pre.is_a?(String)
|
260
|
+
self.class.load(spec_pre)
|
261
|
+
elsif options&.spec_file
|
262
|
+
Baltix::Spec.load_from(source: IO.read(options.spec_file), options: options, space: self)
|
263
|
+
elsif @spec_type || options&.spec_type
|
264
|
+
Baltix::Spec.find(@spec_type || options.spec_type).new(options: options, space: self)
|
265
|
+
end
|
266
|
+
|
267
|
+
@spec.assign_space(self) if @spec
|
268
|
+
|
269
|
+
@spec
|
270
|
+
end
|
271
|
+
|
272
|
+
def initialize state_in = {}, options = {}
|
273
|
+
@options = Baltix::CLI::DEFAULT_OPTIONS.merge(options || {})
|
274
|
+
@state = (state_in || {}).to_os
|
275
|
+
|
276
|
+
baltix_log
|
277
|
+
end
|
278
|
+
|
279
|
+
# init log
|
280
|
+
def baltix_log
|
281
|
+
ios = DEFAULT_IO_NAMES.merge(%i(error warn info debug).map {|k| [k, options["#{k}_io"]]}.to_h)
|
282
|
+
Baltix::Log.setup(options.log_level.to_sym, ios)
|
283
|
+
end
|
284
|
+
|
285
|
+
def show_tree
|
286
|
+
info("Sources:")
|
287
|
+
stat_source_tree.each do |(path_in, stated_sources)|
|
288
|
+
stated_sources.each do |(source, status)|
|
289
|
+
path = source.source_path_from(rootdir) if source.source_file
|
290
|
+
stat = [STATUS_CHARS[status], TYPE_CHARS[source.type.to_sym]].join(" ")
|
291
|
+
namever = [source.name, source.version].compact.join(":")
|
292
|
+
info_in = "#{stat}#{namever} [#{path}]"
|
293
|
+
|
294
|
+
info(info_in)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# returns all the sources with their statuses, and sorted by a its rootdir value
|
300
|
+
#
|
301
|
+
def stat_sources &block
|
302
|
+
return @stat_sources if @stat_sources
|
303
|
+
|
304
|
+
@stat_sources =
|
305
|
+
read_attribute(:stat_sources) || Baltix::Source.search_in(rootdir, options).group_by do |x|
|
306
|
+
[x.name, x.version].compact.join(":")
|
307
|
+
end.map do |(full_name, v)|
|
308
|
+
sorten =
|
309
|
+
v.sort do |x,y|
|
310
|
+
c0 = ::Baltix::Source.loaders.index(x.loader) <=> ::Baltix::Source.loaders.index(y.loader)
|
311
|
+
c1 = c0 == 0 && x.name <=> y.name || c0
|
312
|
+
c2 = c1 == 0 && y.version <=> x.version || c1
|
313
|
+
c3 = c2 == 0 && y.platform <=> x.platform || c2
|
314
|
+
c4 = c3 == 0 && y.source_names.grep(/gemspec/).count <=> x.source_names.grep(/gemspec/).count
|
315
|
+
|
316
|
+
c2 == 0 && c3 == 0 && c4 == 0 && x.rootdir.size <=> y.rootdir.size || c4 != 0 && c4 || c3 != 0 && c3 || c2
|
317
|
+
end.reduce([[], 0]) do |(res, index), source|
|
318
|
+
dup = source.valid? && index > 0
|
319
|
+
dup_index = source.valid? && index + 1 || index
|
320
|
+
|
321
|
+
[res | [[source, source_status(source, dup)]], dup_index]
|
322
|
+
end.first
|
323
|
+
|
324
|
+
sorten[1..-1].each { |x| sorten.first.first.alias_to(x.first) }
|
325
|
+
|
326
|
+
sorten
|
327
|
+
end.flatten(1).sort_by {|(x, _)| x.rootdir.size }.each do |(source, status)|
|
328
|
+
block[source, status] if block_given?
|
329
|
+
end
|
330
|
+
|
331
|
+
show_tree
|
332
|
+
|
333
|
+
@stat_sources
|
334
|
+
end
|
335
|
+
|
336
|
+
# returns source tree, and sorted, and then grouped by a its rootdir value
|
337
|
+
#
|
338
|
+
def stat_source_tree
|
339
|
+
@stat_source_tree ||=
|
340
|
+
stat_sources.group_by {|(x, _)| x.rootdir }.map do |(path, sources)|
|
341
|
+
[File.join('.', path[rootdir.size..-1] || ''), sources]
|
342
|
+
end.to_h
|
343
|
+
end
|
344
|
+
|
345
|
+
# returns status for the source for the project
|
346
|
+
#
|
347
|
+
def source_status source, dup
|
348
|
+
%i(valid duplicated disabled invalid).reduce() do |res, status|
|
349
|
+
STATES[status][self, source, dup] && status || res
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def context
|
354
|
+
@context ||= options[:context] || spec&.context || {}
|
355
|
+
end
|
356
|
+
|
357
|
+
def method_missing method, *args
|
358
|
+
value =
|
359
|
+
instance_variable_get(:"@#{method}") ||
|
360
|
+
(spec.send(method) rescue nil) ||
|
361
|
+
options&.[](method) ||
|
362
|
+
spec&.options&.[](method.to_s) ||
|
363
|
+
state[method]
|
364
|
+
|
365
|
+
instance_variable_set(:"@#{method}", value || super)
|
366
|
+
|
367
|
+
value
|
368
|
+
end
|
369
|
+
|
370
|
+
class << self
|
371
|
+
def load string
|
372
|
+
if Gem::Version.new(Psych::VERSION) >= Gem::Version.new("4.0.0")
|
373
|
+
YAML.load(string,
|
374
|
+
aliases: true,
|
375
|
+
permitted_classes: [
|
376
|
+
Baltix::Source::Fake,
|
377
|
+
Baltix::Source::Rakefile,
|
378
|
+
Baltix::Source::Gemfile,
|
379
|
+
Baltix::Source::Gem,
|
380
|
+
Baltix::Spec::Rpm,
|
381
|
+
Baltix::Spec::Rpm::Name,
|
382
|
+
Baltix::Spec::Rpm::Secondary,
|
383
|
+
Gem::Specification,
|
384
|
+
Gem::Version,
|
385
|
+
Gem::Dependency,
|
386
|
+
Gem::Requirement,
|
387
|
+
OpenStruct,
|
388
|
+
Symbol,
|
389
|
+
Time,
|
390
|
+
Date
|
391
|
+
])
|
392
|
+
else
|
393
|
+
YAML.load(string)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def load_from! state: Dir[".space"].first, options: {}
|
398
|
+
# system_path_check # TODO required to generate spec rubocop
|
399
|
+
|
400
|
+
state_tmp =
|
401
|
+
case state
|
402
|
+
when IO, StringIO
|
403
|
+
load(state.readlines.join(""))
|
404
|
+
when String
|
405
|
+
raise InvalidSpaceFileError.new(state: state) if !File.file?(state)
|
406
|
+
|
407
|
+
load(IO.read(state))
|
408
|
+
when NilClass
|
409
|
+
else
|
410
|
+
raise InvalidSpaceFileError
|
411
|
+
end.to_os
|
412
|
+
|
413
|
+
@@space[state_tmp.name] = self.new(state_tmp, options)
|
414
|
+
end
|
415
|
+
|
416
|
+
def load_from state: Dir[".space"].first, options: {}
|
417
|
+
load_from!(state: state, options: options)
|
418
|
+
rescue InvalidSpaceFileError
|
419
|
+
@@space[nil] = new(nil, options)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
require 'baltix/space/spec'
|
@@ -0,0 +1,155 @@
|
|
1
|
+
class Baltix::Spec::Rpm::Name
|
2
|
+
class InvalidAdoptedNameError < StandardError; end
|
3
|
+
class UnsupportedMatchError < StandardError; end
|
4
|
+
|
5
|
+
PREFICES = %w(gem ruby rubygem)
|
6
|
+
RULE = /^(?<full_name>(?:(?<prefix>#{PREFICES.join('|')})-)?(?<name>.*?))(?:-(?<suffix>doc|devel))?$/
|
7
|
+
|
8
|
+
attr_reader :name, :kind, :suffix
|
9
|
+
attr_accessor :support_name
|
10
|
+
|
11
|
+
def aliases
|
12
|
+
@aliases ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
def prefix
|
16
|
+
@prefix ||= kind == "lib" && self.class.default_prefix || nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.default_prefix
|
20
|
+
"gem"
|
21
|
+
end
|
22
|
+
|
23
|
+
def support_name= value
|
24
|
+
case @support_name = value
|
25
|
+
when NilClass
|
26
|
+
@kind = kind == "exec" && "app" || @kind
|
27
|
+
else
|
28
|
+
@kind = kind == "app" && "exec" || @kind
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def eql? other, deep = false
|
33
|
+
case other
|
34
|
+
when self.class
|
35
|
+
self.eql_by?(:kind, other) && self.eql_by?(:name, other)
|
36
|
+
when String, Symbol
|
37
|
+
(([ autoname, fullname ] | [ aliases ].flatten) & self.class.parse(other).aliases).any?
|
38
|
+
else
|
39
|
+
other.to_s == self.fullname
|
40
|
+
end || deep && self.eql_by?(:support_name, other)
|
41
|
+
end
|
42
|
+
|
43
|
+
def == other
|
44
|
+
eql?(other)
|
45
|
+
end
|
46
|
+
|
47
|
+
def === other
|
48
|
+
eql?(other)
|
49
|
+
end
|
50
|
+
|
51
|
+
def =~ re
|
52
|
+
to_s =~ re
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
fullname
|
57
|
+
end
|
58
|
+
|
59
|
+
def merge other
|
60
|
+
options =
|
61
|
+
%w(prefix suffix name support_name kind).map do |prop|
|
62
|
+
[ prop.to_sym, other.send(prop) || self.send(prop) ]
|
63
|
+
end.to_h
|
64
|
+
|
65
|
+
self.class.new(options.merge(aliases: self.aliases | other.aliases))
|
66
|
+
end
|
67
|
+
|
68
|
+
def eql_by? value, other
|
69
|
+
case value
|
70
|
+
when :name
|
71
|
+
([ self.name, self.aliases ].flatten & [ other.name, other.aliases ].flatten).any?
|
72
|
+
when :kind
|
73
|
+
self.kind == other.kind
|
74
|
+
when :support_name
|
75
|
+
self.support_name === (other.is_a?(self.class) && other.support_name || other)
|
76
|
+
else
|
77
|
+
raise(UnsupportedMatchError.new)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# +fullname+ returns newly reconstructed adopted full name based on the storen data.
|
82
|
+
# All the "." and "_" is replaced with "-", and "ruby" prefix with "gem".
|
83
|
+
#
|
84
|
+
# name.fullname #=> "gem-foo-bar-baz-doc"
|
85
|
+
#
|
86
|
+
def fullname
|
87
|
+
[ autoprefix, autoname, autosuffix ].compact.join("-")
|
88
|
+
end
|
89
|
+
|
90
|
+
def original_fullname
|
91
|
+
[ prefix, name, suffix ].compact.join("-")
|
92
|
+
end
|
93
|
+
|
94
|
+
def autoprefix
|
95
|
+
%w(exec app).include?(kind) || %w(app).include?(support_name&.kind) ? nil : self.class.default_prefix
|
96
|
+
end
|
97
|
+
|
98
|
+
def autoname
|
99
|
+
name&.downcase&.gsub(/[\._]/, "-")
|
100
|
+
end
|
101
|
+
|
102
|
+
def autosuffix
|
103
|
+
%w(doc devel).include?(kind) && kind || nil
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
def initialize options = {}
|
109
|
+
@aliases = options.fetch(:aliases, []) | options.fetch(:name, "").gsub(/[\.\_]+/, "-").split(",")
|
110
|
+
@prefix = options[:prefix]
|
111
|
+
@suffix = options[:suffix]
|
112
|
+
@name = options[:name]
|
113
|
+
@support_name = options[:support_name]
|
114
|
+
@kind = options[:kind] && options[:kind].to_s ||
|
115
|
+
@suffix ||
|
116
|
+
@prefix && "lib" ||
|
117
|
+
@support_name && "exec" || "app"
|
118
|
+
end
|
119
|
+
|
120
|
+
class << self
|
121
|
+
def parse name_in, options_in = {}
|
122
|
+
m, kind =
|
123
|
+
if name_in.is_a?(self)
|
124
|
+
[name_in.original_fullname.match(RULE), name_in.kind]
|
125
|
+
else
|
126
|
+
[name_in.match(RULE)]
|
127
|
+
end
|
128
|
+
|
129
|
+
aliases_in = (options_in[:aliases] || []).flatten.uniq
|
130
|
+
subaliases = aliases_in - [ m["full_name"] ]
|
131
|
+
#aliases = subaliases | [ m["full_name"] ]
|
132
|
+
|
133
|
+
raise(InvalidAdoptedNameError) if !m
|
134
|
+
|
135
|
+
prefixed = subaliases.size >= aliases_in.size
|
136
|
+
options = {
|
137
|
+
prefix: prefixed && m["prefix"] || nil,
|
138
|
+
#prefix: subaliases.blank? && m["prefix"] || nil,
|
139
|
+
#prefix: m["prefix"],
|
140
|
+
suffix: m["suffix"],
|
141
|
+
kind: kind,
|
142
|
+
#name: m["name"],
|
143
|
+
name: prefixed && m["name"] || m["full_name"],
|
144
|
+
#name: subaliases.blank? && m["name"] || m["full_name"],
|
145
|
+
}.merge(options_in).merge({
|
146
|
+
aliases: subaliases | [ m["full_name"] ]
|
147
|
+
})
|
148
|
+
|
149
|
+
options[:name] = options[:name].blank? && options[:aliases].first || options[:name]
|
150
|
+
#binding.pry if name_in =~ /ruby/
|
151
|
+
|
152
|
+
new(options)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|