|
1 | | -# encoding: utf-8 |
2 | | - |
3 | | -require 'yaml' |
4 | | -require 'pathname' |
5 | | - |
6 | | -module Indexer |
7 | | - |
8 | | - # Convert index data into a gemspec. |
9 | | - # |
10 | | - # Notes: |
11 | | - # * Assumes all executables are in bin/. |
12 | | - # * Does not yet handle default_executable setting. |
13 | | - # * Does not yet handle platform setting. |
14 | | - # * Does not yet handle required_ruby_version. |
15 | | - # * Support for rdoc entries is weak. |
16 | | - # |
17 | | - class GemspecExporter |
18 | | - |
19 | | - # File globs to include in package --unless a manifest file exists. |
20 | | - FILES = ".index .yardopts alt bin data demo ext features lib man spec test try* [A-Z]*.*" unless defined?(FILES) |
21 | | - |
22 | | - # File globs to omit from FILES. |
23 | | - OMIT = "Config.rb" unless defined?(OMIT) |
24 | | - |
25 | | - # Standard file patterns. |
26 | | - PATTERNS = { |
27 | | - :root => '{.index,Gemfile}', |
28 | | - :bin => 'bin/*', |
29 | | - :lib => 'lib/{**/}*', #.rb', |
30 | | - :ext => 'ext/{**/}extconf.rb', |
31 | | - :doc => '*.{txt,rdoc,md,markdown,tt,textile}', |
32 | | - :test => '{test,spec}/{**/}*.rb' |
33 | | - } unless defined?(PATTERNS) |
34 | | - |
35 | | - # For which revision of indexer spec is this converter intended? |
36 | | - REVISION = 2013 unless defined?(REVISION) |
37 | | - |
38 | | - # |
39 | | - def self.gemspec |
40 | | - new.to_gemspec |
41 | | - end |
42 | | - |
43 | | - # |
44 | | - attr :metadata |
45 | | - |
46 | | - # |
47 | | - def initialize(metadata=nil) |
48 | | - @root_check = false |
49 | | - |
50 | | - if metadata |
51 | | - root_dir = metadata.delete(:root) |
52 | | - if root_dir |
53 | | - @root = root_dir |
54 | | - @root_check = true |
55 | | - end |
56 | | - metadata = nil if metadata.empty? |
57 | | - end |
58 | | - |
59 | | - @metadata = metadata || YAML.load_file(root + '.index') |
60 | | - |
61 | | - if @metadata['revision'].to_i != REVISION |
62 | | - warn "This gemspec exporter was not designed for this revision of index metadata." |
63 | | - end |
64 | | - end |
65 | | - |
66 | | - # |
67 | | - def has_root? |
68 | | - root ? true : false |
69 | | - end |
70 | | - |
71 | | - # |
72 | | - def root |
73 | | - return @root if @root || @root_check |
74 | | - @root_check = true |
75 | | - @root = find_root |
76 | | - end |
77 | | - |
78 | | - # |
79 | | - def manifest |
80 | | - return nil unless root |
81 | | - @manifest ||= Dir.glob(root + 'manifest{,.txt}', File::FNM_CASEFOLD).first |
82 | | - end |
83 | | - |
84 | | - # |
85 | | - def scm |
86 | | - return nil unless root |
87 | | - @scm ||= %w{git hg}.find{ |m| (root + ".#{m}").directory? }.to_sym |
88 | | - end |
89 | | - |
90 | | - # |
91 | | - def files |
92 | | - return [] unless root |
93 | | - @files ||= \ |
94 | | - if manifest |
95 | | - File.readlines(manifest). |
96 | | - map{ |line| line.strip }. |
97 | | - reject{ |line| line.empty? || line[0,1] == '#' } |
98 | | - else |
99 | | - list = [] |
100 | | - Dir.chdir(root) do |
101 | | - FILES.split(/\s+/).each do |pattern| |
102 | | - list.concat(glob(pattern)) |
103 | | - end |
104 | | - OMIT.split(/\s+/).each do |pattern| |
105 | | - list = list - glob(pattern) |
106 | | - end |
107 | | - end |
108 | | - list |
109 | | - end.select{ |path| File.file?(path) }.uniq |
110 | | - end |
111 | | - |
112 | | - # |
113 | | - def glob_files(pattern) |
114 | | - return [] unless root |
115 | | - Dir.chdir(root) do |
116 | | - Dir.glob(pattern).select do |path| |
117 | | - File.file?(path) && files.include?(path) |
118 | | - end |
119 | | - end |
120 | | - end |
121 | | - |
122 | | - def patterns |
123 | | - PATTERNS |
124 | | - end |
125 | | - |
126 | | - def executables |
127 | | - @executables ||= \ |
128 | | - glob_files(patterns[:bin]).map do |path| |
129 | | - File.basename(path) |
130 | | - end |
131 | | - end |
132 | | - |
133 | | - def extensions |
134 | | - @extensions ||= \ |
135 | | - glob_files(patterns[:ext]).map do |path| |
136 | | - File.basename(path) |
137 | | - end |
138 | | - end |
139 | | - |
140 | | - def name |
141 | | - metadata['name'] || metadata['title'].downcase.gsub(/\W+/,'_') |
142 | | - end |
143 | | - |
144 | | - def homepage |
145 | | - page = ( |
146 | | - metadata['resources'].find{ |r| r['type'] =~ /^home/i } || |
147 | | - metadata['resources'].find{ |r| r['name'] =~ /^home/i } || |
148 | | - metadata['resources'].find{ |r| r['name'] =~ /^web/i } |
149 | | - ) |
150 | | - page ? page['uri'] : false |
151 | | - end |
152 | | - |
153 | | - def licenses |
154 | | - metadata['copyrights'].map{ |c| c['license'] }.compact |
155 | | - end |
156 | | - |
157 | | - def require_paths |
158 | | - paths = metadata['paths'] || {} |
159 | | - paths['load'] || ['lib'] |
160 | | - end |
161 | | - |
162 | | - # |
163 | | - # Convert to gemnspec. |
164 | | - # |
165 | | - def to_gemspec |
166 | | - if has_root? |
167 | | - Gem::Specification.new do |gemspec| |
168 | | - to_gemspec_data(gemspec) |
169 | | - to_gemspec_paths(gemspec) |
170 | | - end |
171 | | - else |
172 | | - Gem::Specification.new do |gemspec| |
173 | | - to_gemspec_data(gemspec) |
174 | | - to_gemspec_paths(gemspec) |
175 | | - end |
176 | | - end |
177 | | - end |
178 | | - |
179 | | - # |
180 | | - # Convert pure data settings. |
181 | | - # |
182 | | - def to_gemspec_data(gemspec) |
183 | | - gemspec.name = name |
184 | | - gemspec.version = metadata['version'] |
185 | | - gemspec.summary = metadata['summary'] |
186 | | - gemspec.description = metadata['description'] |
187 | | - |
188 | | - metadata['authors'].each do |author| |
189 | | - gemspec.authors << author['name'] |
190 | | - |
191 | | - if author.has_key?('email') |
192 | | - if gemspec.email |
193 | | - gemspec.email << author['email'] |
194 | | - else |
195 | | - gemspec.email = [author['email']] |
196 | | - end |
197 | | - end |
198 | | - end |
199 | | - |
200 | | - gemspec.licenses = licenses |
201 | | - |
202 | | - requirements = metadata['requirements'] || [] |
203 | | - requirements.each do |req| |
204 | | - next if req['optional'] |
205 | | - next if req['external'] |
206 | | - |
207 | | - name = req['name'] |
208 | | - groups = req['groups'] || [] |
209 | | - |
210 | | - version = gemify_version(req['version']) |
211 | | - |
212 | | - if groups.empty? or groups.include?('runtime') |
213 | | - # populate runtime dependencies |
214 | | - if gemspec.respond_to?(:add_runtime_dependency) |
215 | | - gemspec.add_runtime_dependency(name,*version) |
216 | | - else |
217 | | - gemspec.add_dependency(name,*version) |
218 | | - end |
219 | | - else |
220 | | - # populate development dependencies |
221 | | - if gemspec.respond_to?(:add_development_dependency) |
222 | | - gemspec.add_development_dependency(name,*version) |
223 | | - else |
224 | | - gemspec.add_dependency(name,*version) |
225 | | - end |
226 | | - end |
227 | | - end |
228 | | - |
229 | | - # convert external dependencies into gemspec requirements |
230 | | - requirements.each do |req| |
231 | | - next unless req['external'] |
232 | | - gemspec.requirements << ("%s-%s" % req.values_at('name', 'version')) |
233 | | - end |
234 | | - |
235 | | - gemspec.homepage = homepage |
236 | | - gemspec.require_paths = require_paths |
237 | | - gemspec.post_install_message = metadata['install_message'] |
238 | | - end |
239 | | - |
240 | | - # |
241 | | - # Set gemspec settings that require a root directory path. |
242 | | - # |
243 | | - def to_gemspec_paths(gemspec) |
244 | | - gemspec.files = files |
245 | | - gemspec.extensions = extensions |
246 | | - gemspec.executables = executables |
247 | | - |
248 | | - if Gem::VERSION < '1.7.' |
249 | | - gemspec.default_executable = gemspec.executables.first |
250 | | - end |
251 | | - |
252 | | - unless gemspec.files.include?('.document') |
253 | | - gemspec.extra_rdoc_files = glob_files(patterns[:doc]) |
254 | | - end |
255 | | - end |
256 | | - |
257 | | - # |
258 | | - # Return a copy of this file. This is used to generate a local |
259 | | - # .gemspec file that can automatically read the index file. |
260 | | - # |
261 | | - def self.source_code |
262 | | - File.read(__FILE__) |
263 | | - end |
264 | | - |
265 | | - private |
266 | | - |
267 | | - def find_root |
268 | | - root_files = patterns[:root] |
269 | | - if Dir.glob(root_files).first |
270 | | - Pathname.new(Dir.pwd) |
271 | | - elsif Dir.glob("../#{root_files}").first |
272 | | - Pathname.new(Dir.pwd).parent |
273 | | - else |
274 | | - #raise "Can't find root of project containing `#{root_files}'." |
275 | | - warn "Can't find root of project containing `#{root_files}'." |
276 | | - nil |
277 | | - end |
278 | | - end |
279 | | - |
280 | | - def glob(pattern) |
281 | | - if File.directory?(pattern) |
282 | | - Dir.glob(File.join(pattern, '**', '*')) |
283 | | - else |
284 | | - Dir.glob(pattern) |
285 | | - end |
286 | | - end |
287 | | - |
288 | | - def gemify_version(version) |
289 | | - case version |
290 | | - when /^(.*?)\+$/ |
291 | | - ">= #{$1}" |
292 | | - when /^(.*?)\-$/ |
293 | | - "< #{$1}" |
294 | | - when /^(.*?)\~$/ |
295 | | - "~> #{$1}" |
296 | | - else |
297 | | - version |
298 | | - end |
299 | | - end |
300 | | - |
301 | | - end |
302 | | - |
| 1 | +Gem::Specification.new do |s| |
| 2 | + s.name = 'facets' |
| 3 | + s.version = '3.2.0' |
| 4 | + s.summary = 'The premier collection of extension methods for Ruby.' |
| 5 | + s.description = 'Facets is the premier collection of extension methods for the Ruby ' \ |
| 6 | + 'programming language. Facets extensions are unique by virtue of their ' \ |
| 7 | + 'atomicity. They are stored in individual files allowing for highly ' \ |
| 8 | + 'granular control of requirements. In addition, Facets includes a few ' \ |
| 9 | + 'additional classes and mixins suitable to a wide variety of applications.' |
| 10 | + |
| 11 | + s.authors = ['Thomas Sawyer'] |
| 12 | + s.email = ['transfire@gmail.com'] |
| 13 | + s.homepage = 'https://github.com/rubyworks/facets' |
| 14 | + s.license = 'BSD-2-Clause' |
| 15 | + |
| 16 | + s.required_ruby_version = '>= 3.1' |
| 17 | + |
| 18 | + s.files = Dir[ |
| 19 | + 'lib/**/*.rb', |
| 20 | + 'LICENSE.txt', |
| 21 | + 'README.md', |
| 22 | + 'HISTORY.md', |
| 23 | + 'CONTRIBUTING.md' |
| 24 | + ] |
| 25 | + |
| 26 | + s.require_paths = ['lib/core', 'lib/standard'] |
| 27 | + |
| 28 | + s.metadata = { |
| 29 | + 'homepage_uri' => s.homepage, |
| 30 | + 'source_code_uri' => 'https://github.com/rubyworks/facets', |
| 31 | + 'changelog_uri' => 'https://github.com/rubyworks/facets/blob/main/HISTORY.md' |
| 32 | + } |
303 | 33 | end |
304 | | - |
305 | | -Indexer::GemspecExporter.gemspec |
0 commit comments