-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspecification.rb
2667 lines (2153 loc) · 69 KB
/
specification.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# frozen_string_literal: true
#
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
require_relative "deprecate"
require_relative "basic_specification"
require_relative "stub_specification"
require_relative "platform"
require_relative "specification_record"
require_relative "util/list"
require "rbconfig"
##
# The Specification class contains the information for a gem. Typically
# defined in a .gemspec file or a Rakefile, and looks like this:
#
# Gem::Specification.new do |s|
# s.name = 'example'
# s.version = '0.1.0'
# s.licenses = ['MIT']
# s.summary = "This is an example!"
# s.description = "Much longer explanation of the example!"
# s.authors = ["Ruby Coder"]
# s.email = 'rubycoder@example.com'
# s.files = ["lib/example.rb"]
# s.homepage = 'https://rubygems.org/gems/example'
# s.metadata = { "source_code_uri" => "https://github.com/example/example" }
# end
#
# Starting in RubyGems 2.0, a Specification can hold arbitrary
# metadata. See #metadata for restrictions on the format and size of metadata
# items you may add to a specification.
class Gem::Specification < Gem::BasicSpecification
extend Gem::Deprecate
# REFACTOR: Consider breaking out this version stuff into a separate
# module. There's enough special stuff around it that it may justify
# a separate class.
##
# The version number of a specification that does not specify one
# (i.e. RubyGems 0.7 or earlier).
NONEXISTENT_SPECIFICATION_VERSION = -1
##
# The specification version applied to any new Specification instances
# created. This should be bumped whenever something in the spec format
# changes.
#
# Specification Version History:
#
# spec ruby
# ver ver yyyy-mm-dd description
# -1 <0.8.0 pre-spec-version-history
# 1 0.8.0 2004-08-01 Deprecated "test_suite_file" for "test_files"
# "test_file=x" is a shortcut for "test_files=[x]"
# 2 0.9.5 2007-10-01 Added "required_rubygems_version"
# Now forward-compatible with future versions
# 3 1.3.2 2009-01-03 Added Fixnum validation to specification_version
# 4 1.9.0 2011-06-07 Added metadata
#--
# When updating this number, be sure to also update #to_ruby.
#
# NOTE RubyGems < 1.2 cannot load specification versions > 2.
CURRENT_SPECIFICATION_VERSION = 4 # :nodoc:
##
# An informal list of changes to the specification. The highest-valued
# key should be equal to the CURRENT_SPECIFICATION_VERSION.
SPECIFICATION_VERSION_HISTORY = { # :nodoc:
-1 => ["(RubyGems versions up to and including 0.7 did not have versioned specifications)"],
1 => [
'Deprecated "test_suite_file" in favor of the new, but equivalent, "test_files"',
'"test_file=x" is a shortcut for "test_files=[x]"',
],
2 => [
'Added "required_rubygems_version"',
"Now forward-compatible with future versions",
],
3 => [
"Added Fixnum validation to the specification_version",
],
4 => [
"Added sandboxed freeform metadata to the specification version.",
],
}.freeze
MARSHAL_FIELDS = { # :nodoc:
-1 => 16,
1 => 16,
2 => 16,
3 => 17,
4 => 18,
}.freeze
today = Time.now.utc
TODAY = Time.utc(today.year, today.month, today.day) # :nodoc:
@load_cache = {} # :nodoc:
@load_cache_mutex = Thread::Mutex.new
VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/ # :nodoc:
# :startdoc:
##
# List of attribute names: [:name, :version, ...]
@@required_attributes = [:rubygems_version,
:specification_version,
:name,
:version,
:date,
:summary,
:require_paths]
##
# Map of attribute names to default values.
@@default_value = {
authors: [],
autorequire: nil,
bindir: "bin",
cert_chain: [],
date: nil,
dependencies: [],
description: nil,
email: nil,
executables: [],
extensions: [],
extra_rdoc_files: [],
files: [],
homepage: nil,
licenses: [],
metadata: {},
name: nil,
platform: Gem::Platform::RUBY,
post_install_message: nil,
rdoc_options: [],
require_paths: ["lib"],
required_ruby_version: Gem::Requirement.default,
required_rubygems_version: Gem::Requirement.default,
requirements: [],
rubygems_version: Gem::VERSION,
signing_key: nil,
specification_version: CURRENT_SPECIFICATION_VERSION,
summary: nil,
test_files: [],
version: nil,
}.freeze
# rubocop:disable Style/MutableConstant
INITIALIZE_CODE_FOR_DEFAULTS = {} # :nodoc:
# rubocop:enable Style/MutableConstant
@@default_value.each do |k,v|
INITIALIZE_CODE_FOR_DEFAULTS[k] = case v
when [], {}, true, false, nil, Numeric, Symbol
v.inspect
when String
v.dump
else
"default_value(:#{k}).dup"
end
end
@@attributes = @@default_value.keys.sort_by(&:to_s)
@@array_attributes = @@default_value.select {|_k,v| v.is_a?(Array) }.keys
@@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition do |k|
@@default_value[k].nil?
end
# Sentinel object to represent "not found" stubs
NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc:
deprecate_constant :NOT_FOUND
# Tracking removed method calls to warn users during build time.
REMOVED_METHODS = [:rubyforge_project=, :mark_version].freeze # :nodoc:
def removed_method_calls
@removed_method_calls ||= []
end
######################################################################
# :section: Required gemspec attributes
##
# This gem's name.
#
# Usage:
#
# spec.name = 'rake'
attr_accessor :name
##
# This gem's version.
#
# The version string can contain numbers and periods, such as +1.0.0+.
# A gem is a 'prerelease' gem if the version has a letter in it, such as
# +1.0.0.pre+.
#
# Usage:
#
# spec.version = '0.4.1'
attr_reader :version
##
# A short summary of this gem's description. Displayed in <tt>gem list -d</tt>.
#
# The #description should be more detailed than the summary.
#
# Usage:
#
# spec.summary = "This is a small summary of my gem"
attr_reader :summary
##
# Files included in this gem. You cannot append to this accessor, you must
# assign to it.
#
# Only add files you can require to this list, not directories, etc.
#
# Directories are automatically stripped from this list when building a gem,
# other non-files cause an error.
#
# Usage:
#
# require 'rake'
# spec.files = FileList['lib/**/*.rb',
# 'bin/*',
# '[A-Z]*'].to_a
#
# # or without Rake...
# spec.files = Dir['lib/**/*.rb'] + Dir['bin/*']
# spec.files += Dir['[A-Z]*']
# spec.files.reject! { |fn| fn.include? "CVS" }
def files
# DO NOT CHANGE TO ||= ! This is not a normal accessor. (yes, it sucks)
# DOC: Why isn't it normal? Why does it suck? How can we fix this?
@files = [@files,
@test_files,
add_bindir(@executables),
@extra_rdoc_files,
@extensions].flatten.compact.uniq.sort
end
##
# A list of authors for this gem.
#
# Alternatively, a single author can be specified by assigning a string to
# +spec.author+
#
# Usage:
#
# spec.authors = ['John Jones', 'Mary Smith']
def authors=(value)
@authors = Array(value).flatten.grep(String)
end
######################################################################
# :section: Recommended gemspec attributes
##
# The version of Ruby required by this gem
#
# Usage:
#
# spec.required_ruby_version = '>= 2.7.0'
attr_reader :required_ruby_version
##
# A long description of this gem
#
# The description should be more detailed than the summary but not
# excessively long. A few paragraphs is a recommended length with no
# examples or formatting.
#
# Usage:
#
# spec.description = <<~EOF
# Rake is a Make-like program implemented in Ruby. Tasks and
# dependencies are specified in standard Ruby syntax.
# EOF
attr_reader :description
##
# A contact email address (or addresses) for this gem
#
# Usage:
#
# spec.email = 'john.jones@example.com'
# spec.email = ['jack@example.com', 'jill@example.com']
attr_accessor :email
##
# The URL of this gem's home page
#
# Usage:
#
# spec.homepage = 'https://github.com/ruby/rake'
attr_accessor :homepage
##
# The license for this gem.
#
# The license must be no more than 64 characters.
#
# This should just be the name of your license. The full text of the license
# should be inside of the gem (at the top level) when you build it.
#
# The simplest way is to specify the standard SPDX ID
# https://spdx.org/licenses/ for the license.
# Ideally, you should pick one that is OSI (Open Source Initiative)
# https://opensource.org/licenses/ approved.
#
# The most commonly used OSI-approved licenses are MIT and Apache-2.0.
# GitHub also provides a license picker at https://choosealicense.com/.
#
# You can also use a custom license file along with your gemspec and specify
# a LicenseRef-<idstring>, where idstring is the name of the file containing
# the license text.
#
# You should specify a license for your gem so that people know how they are
# permitted to use it and any restrictions you're placing on it. Not
# specifying a license means all rights are reserved; others have no right
# to use the code for any purpose.
#
# You can set multiple licenses with #licenses=
#
# Usage:
# spec.license = 'MIT'
def license=(o)
self.licenses = [o]
end
##
# The license(s) for the library.
#
# Each license must be a short name, no more than 64 characters.
#
# This should just be the name of your license. The full
# text of the license should be inside of the gem when you build it.
#
# See #license= for more discussion
#
# Usage:
# spec.licenses = ['MIT', 'GPL-2.0']
def licenses=(licenses)
@licenses = Array licenses
end
##
# The metadata holds extra data for this gem that may be useful to other
# consumers and is settable by gem authors.
#
# Metadata items have the following restrictions:
#
# * The metadata must be a Hash object
# * All keys and values must be Strings
# * Keys can be a maximum of 128 bytes and values can be a maximum of 1024
# bytes
# * All strings must be UTF-8, no binary data is allowed
#
# You can use metadata to specify links to your gem's homepage, codebase,
# documentation, wiki, mailing list, issue tracker and changelog.
#
# s.metadata = {
# "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
# "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
# "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
# "homepage_uri" => "https://bestgemever.example.io",
# "mailing_list_uri" => "https://groups.example.com/bestgemever",
# "source_code_uri" => "https://example.com/user/bestgemever",
# "wiki_uri" => "https://example.com/user/bestgemever/wiki",
# "funding_uri" => "https://example.com/donate"
# }
#
# These links will be used on your gem's page on rubygems.org and must pass
# validation against following regex.
#
# %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}
attr_accessor :metadata
######################################################################
# :section: Optional gemspec attributes
##
# Singular (alternative) writer for #authors
#
# Usage:
#
# spec.author = 'John Jones'
def author=(o)
self.authors = [o]
end
##
# The path in the gem for executable scripts. Usually 'exe'
#
# Usage:
#
# spec.bindir = 'exe'
attr_accessor :bindir
##
# The certificate chain used to sign this gem. See Gem::Security for
# details.
attr_accessor :cert_chain
##
# A message that gets displayed after the gem is installed.
#
# Usage:
#
# spec.post_install_message = "Thanks for installing!"
attr_accessor :post_install_message
##
# The platform this gem runs on.
#
# This is usually Gem::Platform::RUBY or Gem::Platform::CURRENT.
#
# Most gems contain pure Ruby code; they should simply leave the default
# value in place. Some gems contain C (or other) code to be compiled into a
# Ruby "extension". The gem should leave the default value in place unless
# the code will only compile on a certain type of system. Some gems consist
# of pre-compiled code ("binary gems"). It's especially important that they
# set the platform attribute appropriately. A shortcut is to set the
# platform to Gem::Platform::CURRENT, which will cause the gem builder to set
# the platform to the appropriate value for the system on which the build is
# being performed.
#
# If this attribute is set to a non-default value, it will be included in
# the filename of the gem when it is built such as:
# nokogiri-1.6.0-x86-mingw32.gem
#
# Usage:
#
# spec.platform = Gem::Platform.local
def platform=(platform)
@original_platform = platform
case platform
when Gem::Platform::CURRENT then
@new_platform = Gem::Platform.local
@original_platform = @new_platform.to_s
when Gem::Platform then
@new_platform = platform
# legacy constants
when nil, Gem::Platform::RUBY then
@new_platform = Gem::Platform::RUBY
when "mswin32" then # was Gem::Platform::WIN32
@new_platform = Gem::Platform.new "x86-mswin32"
when "i586-linux" then # was Gem::Platform::LINUX_586
@new_platform = Gem::Platform.new "x86-linux"
when "powerpc-darwin" then # was Gem::Platform::DARWIN
@new_platform = Gem::Platform.new "ppc-darwin"
else
@new_platform = Gem::Platform.new platform
end
@platform = @new_platform.to_s
invalidate_memoized_attributes
end
##
# Paths in the gem to add to <code>$LOAD_PATH</code> when this gem is
# activated.
#--
# See also #require_paths
#++
# If you have an extension you do not need to add <code>"ext"</code> to the
# require path, the extension build process will copy the extension files
# into "lib" for you.
#
# The default value is <code>"lib"</code>
#
# Usage:
#
# # If all library files are in the root directory...
# spec.require_paths = ['.']
def require_paths=(val)
@require_paths = Array(val)
end
##
# The RubyGems version required by this gem
attr_reader :required_rubygems_version
##
# The key used to sign this gem. See Gem::Security for details.
attr_accessor :signing_key
##
# Adds a development dependency named +gem+ with +requirements+ to this
# gem.
#
# Usage:
#
# spec.add_development_dependency 'example', '~> 1.1', '>= 1.1.4'
#
# Development dependencies aren't installed by default and aren't
# activated when a gem is required.
def add_development_dependency(gem, *requirements)
add_dependency_with_type(gem, :development, requirements)
end
##
# Adds a runtime dependency named +gem+ with +requirements+ to this gem.
#
# Usage:
#
# spec.add_dependency 'example', '~> 1.1', '>= 1.1.4'
def add_dependency(gem, *requirements)
if requirements.uniq.size != requirements.size
warn "WARNING: duplicated #{gem} dependency #{requirements}"
end
add_dependency_with_type(gem, :runtime, requirements)
end
##
# Executables included in the gem.
#
# For example, the rake gem has rake as an executable. You don't specify the
# full path (as in bin/rake); all application-style files are expected to be
# found in bindir. These files must be executable Ruby files. Files that
# use bash or other interpreters will not work.
#
# Executables included may only be ruby scripts, not scripts for other
# languages or compiled binaries.
#
# Usage:
#
# spec.executables << 'rake'
def executables
@executables ||= []
end
##
# Extensions to build when installing the gem, specifically the paths to
# extconf.rb-style files used to compile extensions.
#
# These files will be run when the gem is installed, causing the C (or
# whatever) code to be compiled on the user's machine.
#
# Usage:
#
# spec.extensions << 'ext/rmagic/extconf.rb'
#
# See Gem::Ext::Builder for information about writing extensions for gems.
def extensions
@extensions ||= []
end
##
# Extra files to add to RDoc such as README or doc/examples.txt
#
# When the user elects to generate the RDoc documentation for a gem (typically
# at install time), all the library files are sent to RDoc for processing.
# This option allows you to have some non-code files included for a more
# complete set of documentation.
#
# Usage:
#
# spec.extra_rdoc_files = ['README', 'doc/user-guide.txt']
def extra_rdoc_files
@extra_rdoc_files ||= []
end
##
# The version of RubyGems that installed this gem. Returns
# <code>Gem::Version.new(0)</code> for gems installed by versions earlier
# than RubyGems 2.2.0.
def installed_by_version # :nodoc:
@installed_by_version ||= Gem::Version.new(0)
end
##
# Sets the version of RubyGems that installed this gem. See also
# #installed_by_version.
def installed_by_version=(version) # :nodoc:
@installed_by_version = Gem::Version.new version
end
##
# Specifies the rdoc options to be used when generating API documentation.
#
# Usage:
#
# spec.rdoc_options << '--title' << 'Rake -- Ruby Make' <<
# '--main' << 'README' <<
# '--line-numbers'
def rdoc_options
@rdoc_options ||= []
end
LATEST_RUBY_WITHOUT_PATCH_VERSIONS = Gem::Version.new("2.1")
##
# The version of Ruby required by this gem. The ruby version can be
# specified to the patch-level:
#
# $ ruby -v -e 'p Gem.ruby_version'
# ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]
# #<Gem::Version "2.0.0.247">
#
# Prereleases can also be specified.
#
# Usage:
#
# # This gem will work with 1.8.6 or greater...
# spec.required_ruby_version = '>= 1.8.6'
#
# # Only with final releases of major version 2 where minor version is at least 3
# spec.required_ruby_version = '~> 2.3'
#
# # Only prereleases or final releases after 2.6.0.preview2
# spec.required_ruby_version = '> 2.6.0.preview2'
#
# # This gem will work with 2.3.0 or greater, including major version 3, but lesser than 4.0.0
# spec.required_ruby_version = '>= 2.3', '< 4'
def required_ruby_version=(req)
@required_ruby_version = Gem::Requirement.create req
@required_ruby_version.requirements.map! do |op, v|
if v >= LATEST_RUBY_WITHOUT_PATCH_VERSIONS && v.release.segments.size == 4
[op == "~>" ? "=" : op, Gem::Version.new(v.segments.tap {|s| s.delete_at(3) }.join("."))]
else
[op, v]
end
end
end
##
# The RubyGems version required by this gem
def required_rubygems_version=(req)
@required_rubygems_version = Gem::Requirement.create req
end
##
# Lists the external (to RubyGems) requirements that must be met for this gem
# to work. It's simply information for the user.
#
# Usage:
#
# spec.requirements << 'libmagick, v6.0'
# spec.requirements << 'A good graphics card'
def requirements
@requirements ||= []
end
##
# A collection of unit test files. They will be loaded as unit tests when
# the user requests a gem to be unit tested.
#
# Usage:
# spec.test_files = Dir.glob('test/tc_*.rb')
# spec.test_files = ['tests/test-suite.rb']
def test_files=(files) # :nodoc:
@test_files = Array files
end
######################################################################
# :section: Read-only attributes
##
# The version of RubyGems used to create this gem.
attr_accessor :rubygems_version
##
# The path where this gem installs its extensions.
def extensions_dir
@extensions_dir ||= super
end
######################################################################
# :section: Specification internals
##
# True when this gemspec has been activated. This attribute is not persisted.
attr_accessor :activated
alias_method :activated?, :activated
##
# Autorequire was used by old RubyGems to automatically require a file.
#
# Deprecated: It is neither supported nor functional.
attr_accessor :autorequire # :nodoc:
##
# Sets the default executable for this gem.
#
# Deprecated: You must now specify the executable name to Gem.bin_path.
attr_writer :default_executable
rubygems_deprecate :default_executable=
##
# Allows deinstallation of gems with legacy platforms.
attr_writer :original_platform # :nodoc:
##
# The Gem::Specification version of this gemspec.
#
# Do not set this, it is set automatically when the gem is packaged.
attr_accessor :specification_version
def self._all # :nodoc:
specification_record.all
end
def self.clear_load_cache # :nodoc:
@load_cache_mutex.synchronize do
@load_cache.clear
end
end
private_class_method :clear_load_cache
def self.gem_path # :nodoc:
Gem.path
end
private_class_method :gem_path
def self.each_gemspec(dirs) # :nodoc:
dirs.each do |dir|
Gem::Util.glob_files_in_dir("*.gemspec", dir).each do |path|
yield path
end
end
end
def self.gemspec_stubs_in(dir, pattern) # :nodoc:
Gem::Util.glob_files_in_dir(pattern, dir).map {|path| yield path }.select(&:valid?)
end
def self.each_spec(dirs) # :nodoc:
each_gemspec(dirs) do |path|
spec = self.load path
yield spec if spec
end
end
##
# Returns a Gem::StubSpecification for every installed gem
def self.stubs
specification_record.stubs
end
##
# Returns a Gem::StubSpecification for default gems
def self.default_stubs(pattern = "*.gemspec")
base_dir = Gem.default_dir
gems_dir = File.join base_dir, "gems"
gemspec_stubs_in(Gem.default_specifications_dir, pattern) do |path|
Gem::StubSpecification.default_gemspec_stub(path, base_dir, gems_dir)
end
end
##
# Returns a Gem::StubSpecification for installed gem named +name+
# only returns stubs that match Gem.platforms
def self.stubs_for(name)
specification_record.stubs_for(name)
end
##
# Finds stub specifications matching a pattern from the standard locations,
# optionally filtering out specs not matching the current platform
#
def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc:
specification_record.stubs_for_pattern(pattern, match_platform)
end
def self._resort!(specs) # :nodoc:
specs.sort! do |a, b|
names = a.name <=> b.name
next names if names.nonzero?
versions = b.version <=> a.version
next versions if versions.nonzero?
platforms = Gem::Platform.sort_priority(b.platform) <=> Gem::Platform.sort_priority(a.platform)
next platforms if platforms.nonzero?
default_gem = a.default_gem_priority <=> b.default_gem_priority
next default_gem if default_gem.nonzero?
a.base_dir_priority(gem_path) <=> b.base_dir_priority(gem_path)
end
end
##
# Loads the default specifications. It should be called only once.
def self.load_defaults
each_spec([Gem.default_specifications_dir]) do |spec|
# #load returns nil if the spec is bad, so we just ignore
# it at this stage
Gem.register_default_spec(spec)
end
end
##
# Adds +spec+ to the known specifications, keeping the collection
# properly sorted.
def self.add_spec(spec)
specification_record.add_spec(spec)
end
##
# Removes +spec+ from the known specs.
def self.remove_spec(spec)
specification_record.remove_spec(spec)
end
##
# Returns all specifications. This method is discouraged from use.
# You probably want to use one of the Enumerable methods instead.
def self.all
warn "NOTE: Specification.all called from #{caller(1, 1).first}" unless
Gem::Deprecate.skip
_all
end
##
# Sets the known specs to +specs+.
def self.all=(specs)
specification_record.all = specs
end
##
# Return full names of all specs in sorted order.
def self.all_names
specification_record.all_names
end
##
# Return the list of all array-oriented instance variables.
#--
# Not sure why we need to use so much stupid reflection in here...
def self.array_attributes
@@array_attributes.dup
end
##
# Return the list of all instance variables.
#--
# Not sure why we need to use so much stupid reflection in here...
def self.attribute_names
@@attributes.dup
end
##
# Return the directories that Specification uses to find specs.
def self.dirs
@@dirs ||= Gem::SpecificationRecord.dirs_from(gem_path)
end
##
# Set the directories that Specification uses to find specs. Setting
# this resets the list of known specs.
def self.dirs=(dirs)
reset
@@dirs = Gem::SpecificationRecord.dirs_from(Array(dirs))
end
extend Enumerable
##
# Enumerate every known spec. See ::dirs= and ::add_spec to set the list of
# specs.
def self.each(&block)
specification_record.each(&block)
end
##
# Returns every spec that matches +name+ and optional +requirements+.
def self.find_all_by_name(name, *requirements)
specification_record.find_all_by_name(name, *requirements)
end
##
# Returns every spec that has the given +full_name+
def self.find_all_by_full_name(full_name)
stubs.select {|s| s.full_name == full_name }.map(&:to_spec)
end
##
# Find the best specification matching a +name+ and +requirements+. Raises
# if the dependency doesn't resolve to a valid specification.
def self.find_by_name(name, *requirements)
requirements = Gem::Requirement.default if requirements.empty?
Gem::Dependency.new(name, *requirements).to_spec
end
##
# Find the best specification matching a +full_name+.
def self.find_by_full_name(full_name)
stubs.find {|s| s.full_name == full_name }&.to_spec
end
##
# Return the best specification that contains the file matching +path+.
def self.find_by_path(path)
specification_record.find_by_path(path)
end
##
# Return the best specification that contains the file matching +path+
# amongst the specs that are not activated.
def self.find_inactive_by_path(path)
specification_record.find_inactive_by_path(path)
end
##
# Return the best specification that contains the file matching +path+, among
# those already activated.
def self.find_active_stub_by_path(path)
specification_record.find_active_stub_by_path(path)
end
##
# Return currently unresolved specs that contain the file matching +path+.
def self.find_in_unresolved(path)
unresolved_specs.find_all {|spec| spec.contains_requirable_file? path }
end
##
# Search through all unresolved deps and sub-dependencies and return
# specs that contain the file matching +path+.