cdnget 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9204fce30417104ddfeb1a49af1c1e770c630cc1
4
+ data.tar.gz: 1e9dc0c2d1fba34882a0dd5c6fc26a8ccc6edb57
5
+ SHA512:
6
+ metadata.gz: 087992a00501a6d1f3dd179a741b708eed1c80266666c0a61f8465325d2c7f0f7592ecc8015c3edb7e0987613a811e92fba0e4b7ecdb058a54b68f3f8a0b6f43
7
+ data.tar.gz: 1bed28d10dc90f2e2ab241178dc74a9762a866efe5860f31c2eab01a4f6377978653756932ddd8a2a170bbd9061fa3a77a78ecb5493dbf05b48ce0fdf76a27ce
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ $Copyright: copyright(c) 2016 kuwata-lab.com all rights reserved $
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,45 @@
1
+ CDNget
2
+ ======
3
+
4
+ ($Release: 0.1.0 $)
5
+
6
+ CDNget is a utility script to download files from CDNJS, jsDelivr or Google.
7
+
8
+
9
+ Install
10
+ -------
11
+
12
+ $ gem install cdnget
13
+
14
+ Or:
15
+
16
+ $ curl -sO https://github.com/kwatch/cdnget/raw/ruby-release/bin/cdnget
17
+ $ chmod a+x cdnget
18
+ $ sudo cp cdnget /usr/local/bin
19
+
20
+ CDNget is implemented in Ruby and requires Ruby >= 2.0.
21
+
22
+
23
+ Usage
24
+ -----
25
+
26
+ $ cdnget # list CDN (cdnjs/jsdelivr/google)
27
+ $ cdnget [-q] cdnjs # list libraries
28
+ $ cdnget [-q] cdnjs '*jquery*' # search libraries
29
+ $ cdnget [-q] cdnjs jquery # list library versions
30
+ $ cdnget [-q] cdnjs jquery 2.2.0 # list library files
31
+ $ cdnget [-q] cdnjs jquery 2.2.0 /tmp # download files
32
+ /tmp/jquery/2.2.0/jquery.js ... Done (258,388 byte)
33
+ /tmp/jquery/2.2.0/jquery.min.js ... Done (85,589 byte)
34
+ /tmp/jquery/2.2.0/jquery.min.map ... Done (129,544 byte)
35
+
36
+ $ ls /tmp/jquery/2.2.0
37
+ jquery.js jquery.min.js jquery.min.map
38
+
39
+
40
+ Copyright and License
41
+ ---------------------
42
+
43
+ $Copyright: copyright(c) 2016 kuwata-lab.com all rights reserved $
44
+
45
+ $License: MIT License $
@@ -0,0 +1,144 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ###
4
+
5
+ RELEASE = '$Release: 0.1.0 $'.split()[1]
6
+ COPYRIGHT = 'copyright(c) 2016 kuwata-lab.com all rights reserved'
7
+ LICENSE = 'MIT License'
8
+
9
+ PROJECT = 'cdnget'
10
+
11
+
12
+ ### helpers
13
+
14
+ def run(command)
15
+ print '[rake]$ '; sh command
16
+ end
17
+
18
+ def edit_content(content, release=RELEASE)
19
+ s = content
20
+ s = s.gsub /\$Release\:.*?\$/, "$Release\: #{release} $"
21
+ s = s.gsub /\$Copyright\:.*?\$/, "$Copyright\: #{COPYRIGHT} $"
22
+ s = s.gsub /\$License\:.*?\$/, "$License\: #{LICENSE} $"
23
+ s = s.gsub /\$Release\$/, release
24
+ s = s.gsub /\$Copyright\$/, COPYRIGHT
25
+ s = s.gsub /\$License\$/, LICENSE
26
+ s
27
+ end
28
+
29
+ def load_gemspec
30
+ spec = eval File.read("#{PROJECT}.gemspec", encoding: 'utf-8')
31
+ return spec
32
+ end
33
+
34
+
35
+ ### tasks
36
+
37
+
38
+ #task :default => :test
39
+
40
+ desc "run test scripts"
41
+ task :test do
42
+ #sh "ruby -r minitest/autorun test/*_test.rb"
43
+ run "ruby test/#{PROJECT}_test.rb"
44
+ end
45
+
46
+
47
+ desc "remove *.rbc"
48
+ task :clean do
49
+ rm_f [Dir.glob("lib/**/*.rbc"), Dir.glob("test/**/*.rbc")]
50
+ end
51
+
52
+
53
+ desc "how to release"
54
+ task :howtorelease do
55
+ rel = ENV['rel'] || RELEASE
56
+ ver = rel.sub(/\.\d+$/,'')
57
+ patch_zero = !! (rel =~ /\.0$/)
58
+ puts <<END
59
+ $ git branch | grep '\*'
60
+ * ruby-dev
61
+ $ git checkout #{patch_zero ? '-b ': ''}ruby-#{ver}
62
+ $ rake edit rel=#{rel}
63
+ $ git diff
64
+ $ git commit -a -m "ruby: release preparation for #{rel}"
65
+ $ rake package
66
+ $ rake publish
67
+ END
68
+ end
69
+
70
+
71
+ desc "create 'bin/cdnget'"
72
+ task :bin do
73
+ material = "lib/cdnget.rb"
74
+ product = "bin/cdnget"
75
+ run %Q`cat #{material} | awk '{c=""}/if __FILE__/{f=1;c="#"}f&&/end/{c="#"}{print c $0}' > #{product}`
76
+ run %Q`chmod a+x #{product}`
77
+ end
78
+
79
+
80
+ desc "edit '$Release\:...$' in files"
81
+ task :edit => :bin do
82
+ rel = ENV['rel']
83
+ unless rel
84
+ $stderr.puts "*** Release number is not speicified"
85
+ $stderr.puts "*** Usage: rake edit rel=X.X.X"
86
+ raise StandardError
87
+ end
88
+ spec = load_gemspec()
89
+ spec.files.each do |fpath|
90
+ if fpath =~ /\.(gz|jpg|png|form)\z/
91
+ puts "[ignore] #{fpath}"
92
+ next
93
+ end
94
+ s1 = File.open(fpath, encoding: 'utf-8') {|f| f.read() }
95
+ s2 = edit_content(s1, rel)
96
+ if s1 == s2
97
+ puts "[skip] #{fpath}"
98
+ else
99
+ puts "[Edit] #{fpath}"
100
+ File.open(fpath, 'w', encoding: 'utf-8') {|f| f.write(s2) }
101
+ end
102
+ end
103
+ end
104
+
105
+
106
+ desc "create rubygem pacakge"
107
+ task :package do
108
+ spec = load_gemspec()
109
+ name = spec.name
110
+ ver = spec.version
111
+ run "gem build #{name}.gemspec"
112
+ puts ""
113
+ puts "## files"
114
+ puts spec.files.collect {|x| "- #{x}" }
115
+ end
116
+
117
+
118
+ desc "release gem"
119
+ task :publish do
120
+ diff = `git diff --stat`
121
+ if diff && ! diff.empty?
122
+ raise "[ERROR] Please commit changes before publishing gem."
123
+ end
124
+ #
125
+ spec = load_gemspec()
126
+ name = spec.name
127
+ ver = spec.version
128
+ #
129
+ gem = "#{name}-#{ver}.gem"
130
+ File.exist?(gem) or
131
+ raise "[ERROR] run 'rake package' before publishing gem."
132
+ mtime = File.mtime(gem)
133
+ ! spec.files.any? {|fpath| File.mtime(fpath) >= mtime } or
134
+ raise "[ERROR] run 'rake package' again because gem file seems obsoleted."
135
+ #
136
+ print "Upload #{gem}. OK? [y/N]: "
137
+ if $stdin.gets() =~ /[yY]/
138
+ run "gem push #{gem}"
139
+ run "git push -u origin `git rev-parse --abbrev-ref HEAD`"
140
+ run "git push -f origin ruby-release"
141
+ run "git tag ruby-#{ver}"
142
+ run "git push --tags"
143
+ end
144
+ end
@@ -0,0 +1,530 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ ##
5
+ ## Download files from CDN (CDNJS, Google, jsDelivr).
6
+ ##
7
+ ## - CDNJS (https://cdnjs.com/)
8
+ ## - Google (https://developers.google.com/speed/libraries/)
9
+ ## - jsDelivr (https://www.jsdelivr.com/)
10
+ ##
11
+ ## Example:
12
+ ## $ cdnget # list public CDN
13
+ ## $ cdnget [-q] cdnjs # list libraries
14
+ ## $ cdnget [-q] cdnjs jquery # list versions
15
+ ## $ cdnget [-q] cdnjs jquery 2.2.0 # list files
16
+ ## $ cdnget [-q] cdnjs jquery 2.2.0 /tmp # download files
17
+ ##
18
+
19
+ require 'open-uri'
20
+ require 'json'
21
+ require 'fileutils'
22
+
23
+
24
+ module CDNGet
25
+
26
+
27
+ RELEASE = '$Release: 0.1.0 $'.split()[1]
28
+
29
+ CLASSES = []
30
+
31
+
32
+ class Base
33
+
34
+ def self.inherited(klass)
35
+ CLASSES << klass
36
+ end
37
+
38
+ def list()
39
+ raise NotImplementedError.new("#{self.class.name}#list(): not implemented yet.")
40
+ end
41
+
42
+ def find(library)
43
+ raise NotImplementedError.new("#{self.class.name}#find(): not implemented yet.")
44
+ end
45
+
46
+ def get(library, version)
47
+ raise NotImplementedError.new("#{self.class.name}#get(): not implemented yet.")
48
+ end
49
+
50
+ def download(library, version, basedir=".", quiet: false)
51
+ validate(library, version)
52
+ File.exist?(basedir) or
53
+ raise CommandError.new("#{basedir}: not exist.")
54
+ File.directory?(basedir) or
55
+ raise CommandError.new("#{basedir}: not a directory.")
56
+ target_dir = File.join(basedir, library, version)
57
+ d = get(library, version)
58
+ d[:files].each do |file|
59
+ filepath = File.join(target_dir, file)
60
+ dirpath = File.dirname(filepath)
61
+ print "#{filepath} ..." unless quiet
62
+ url = File.join(d[:baseurl], file) # not use URI.join!
63
+ content = fetch(url)
64
+ content = content.force_encoding('ascii-8bit')
65
+ print " Done (#{format_integer(content.bytesize)} byte)" unless quiet
66
+ FileUtils.mkdir_p(dirpath) unless File.exist?(dirpath)
67
+ unchanged = File.exist?(filepath) && File.read(filepath, mode: 'rb') == content
68
+ if unchanged
69
+ print " (Unchanged)" unless quiet
70
+ else
71
+ File.open(filepath, 'wb') {|f| f.write(content) }
72
+ end
73
+ puts() unless quiet
74
+ end
75
+ nil
76
+ end
77
+
78
+ protected
79
+
80
+ def fetch(url, library=nil)
81
+ begin
82
+ html = open(url, 'rb') {|f| f.read() }
83
+ return html
84
+ rescue OpenURI::HTTPError => ex
85
+ raise CommandError.new("GET #{url} : #{ex.message}")
86
+ end
87
+ end
88
+
89
+ def validate(library, version)
90
+ if library
91
+ library =~ /\A[-.\w]+\z/ or
92
+ raise ArgumentError.new("#{library.inspect}: Unexpected library name.")
93
+ end
94
+ if version
95
+ version =~ /\A\d+(\.\d+)+([-.\w]+)?/ or
96
+ raise ArgumentError.new("#{version.inspect}: Unexpected version number.")
97
+ end
98
+ end
99
+
100
+ def format_integer(value)
101
+ return value.to_s.reverse.scan(/..?.?/).collect {|s| s.reverse }.reverse.join(',')
102
+ end
103
+
104
+ end
105
+
106
+
107
+ class HttpError < StandardError
108
+ end
109
+
110
+
111
+ class CDNJS < Base # TODO: use jsdelivr api
112
+ CODE = "cdnjs"
113
+ SITE_URL = 'https://cdnjs.com/'
114
+
115
+ def fetch(url, library=nil)
116
+ begin
117
+ html = open(url, 'rb') {|f| f.read() }
118
+ if library
119
+ html =~ /<h1\b.*?>(.*?)<\/h1>/ or
120
+ raise CommandError.new("#{library}: Library not found.")
121
+ library == $1.strip() or
122
+ raise CommandError.new("#{library}: Library not found (maybe '#{$1.strip()}'?).")
123
+ end
124
+ return html
125
+ rescue OpenURI::HTTPError => ex
126
+ raise HttpError.new("GET #{url} : #{ex.message}")
127
+ end
128
+ end
129
+ protected :fetch
130
+
131
+ def list
132
+ libs = []
133
+ html = fetch("https://cdnjs.com/libraries")
134
+ html.scan(/<td\b(.*?)<\/td>/m) do |str,|
135
+ name = desc = nil
136
+ name = $1 if str =~ /href="\/libraries\/([-.\w]+)">\s*\1\s*<\/a>/
137
+ desc = $1.strip if str =~ /<div style="display: none;">(.*?)<\/div>/m
138
+ libs << {name: name, desc: desc} if name
139
+ end
140
+ return libs.sort_by {|d| d[:name] }.uniq
141
+ end
142
+
143
+ def find(library)
144
+ validate(library, nil)
145
+ html = fetch("https://cdnjs.com/libraries/#{library}", library)
146
+ versions = []
147
+ html.scan(/<option value="([^"]+)" *(?:selected)?>/) do |ver,|
148
+ versions << ver
149
+ end
150
+ desc = tags = nil
151
+ if html =~ /<p>(.*?)<\/p>\s*<em>(.*?)<\/em>/
152
+ desc = $1
153
+ tags = $2
154
+ end
155
+ return {
156
+ name: library,
157
+ desc: desc,
158
+ tags: tags,
159
+ versions: versions,
160
+ }
161
+ end
162
+
163
+ def get(library, version)
164
+ validate(library, version)
165
+ html = fetch("https://cdnjs.com/libraries/#{library}/#{version}", library)
166
+ baseurl = "https://cdnjs.cloudflare.com/ajax/libs/#{library}/#{version}"
167
+ urls = []
168
+ files = []
169
+ rexp = %r`>(#{Regexp.escape(baseurl)}/([^<]+))<\/p>`
170
+ html.scan(%r`>(#{Regexp.escape(baseurl)}/([^<]+))<\/p>`) do |url, file|
171
+ urls << url .gsub(/&#x2F;/, '/')
172
+ files << file.gsub(/&#x2F;/, '/')
173
+ end
174
+ return {
175
+ name: library,
176
+ version: version,
177
+ urls: urls,
178
+ files: files,
179
+ baseurl: baseurl,
180
+ }
181
+ end
182
+
183
+ end
184
+
185
+
186
+ class JSDelivr < Base
187
+ CODE = "jsdelivr"
188
+ SITE_URL = "https://www.jsdelivr.com/"
189
+ API_URL = "https://api.jsdelivr.com/v1/jsdelivr/libraries"
190
+
191
+ def list
192
+ json = fetch("#{API_URL}?fields=name,description,homepage")
193
+ arr = JSON.load(json)
194
+ return arr.collect {|d|
195
+ {name: d["name"], desc: d["description"], site: d["homepage"] }
196
+ }
197
+ end
198
+
199
+ def find(library)
200
+ validate(library, nil)
201
+ json = fetch("#{API_URL}?name=#{library}&fields=name,description,homepage,versions")
202
+ arr = JSON.load(json)
203
+ d = arr.first or
204
+ raise CommandError.new("#{library}: Library not found.")
205
+ return {
206
+ name: d['name'],
207
+ desc: d['description'],
208
+ site: d['homepage'],
209
+ versions: d['versions'],
210
+ }
211
+ end
212
+
213
+ def get(library, version)
214
+ validate(library, version)
215
+ baseurl = "https://cdn.jsdelivr.net/#{library}/#{version}"
216
+ url = "#{API_URL}/#{library}/#{version}"
217
+ json = fetch("#{API_URL}/#{library}/#{version}")
218
+ files = JSON.load(json)
219
+ ! files.empty? or
220
+ raise CommandError.new("#{library}: Library not found.")
221
+ urls = files.collect {|x| "#{baseurl}/#{x}" }
222
+ return {
223
+ name: library,
224
+ version: version,
225
+ urls: urls,
226
+ files: files,
227
+ baseurl: baseurl,
228
+ }
229
+ end
230
+
231
+ end
232
+
233
+
234
+ class GoogleCDN < Base # TODO: use jsdelivr api
235
+ CODE = "google"
236
+ SITE_URL = 'https://developers.google.com/speed/libraries/'
237
+
238
+ def list
239
+ libs = []
240
+ html = fetch("https://developers.google.com/speed/libraries/")
241
+ rexp = %r`"https://ajax\.googleapis\.com/ajax/libs/([^/]+)/([^/]+)/([^"]+)"`
242
+ html.scan(rexp) do |lib, ver, file|
243
+ libs << {name: lib, desc: "latest version: #{ver}" }
244
+ end
245
+ return libs.sort_by {|d| d[:name] }.uniq
246
+ end
247
+
248
+ def find(library)
249
+ validate(library, nil)
250
+ html = fetch("https://developers.google.com/speed/libraries/")
251
+ rexp = %r`"https://ajax\.googleapis\.com/ajax/libs/#{library}/`
252
+ site_url = nil
253
+ versions = []
254
+ urls = []
255
+ found = false
256
+ html.scan(/<h3\b.*?>.*?<\/h3>\s*<dl>(.*?)<\/dl>/m) do |text,|
257
+ if text =~ rexp
258
+ found = true
259
+ if text =~ /<dt>.*?snippet:<\/dt>\s*<dd>(.*?)<\/dd>/m
260
+ s = $1
261
+ s.scan(/\b(?:src|href)="([^"]*?)"/) do |href,|
262
+ urls << href
263
+ end
264
+ end
265
+ if text =~ /<dt>site:<\/dt>\s*<dd>(.*?)<\/dd>/m
266
+ s = $1
267
+ if s =~ %r`href="([^"]+)"`
268
+ site_url = $1
269
+ end
270
+ end
271
+ text.scan(/<dt>(?:stable |unstable )?versions:<\/dt>\s*<dd\b.*?>(.*?)<\/dd>/m) do
272
+ s = $1
273
+ vers = s.split(/,/).collect {|x| x.strip() }
274
+ versions.concat(vers)
275
+ end
276
+ break
277
+ end
278
+ end
279
+ found or
280
+ raise CommandError.new("#{library}: Library not found.")
281
+ return {
282
+ name: library,
283
+ site: site_url,
284
+ urls: urls,
285
+ versions: versions,
286
+ }
287
+ end
288
+
289
+ def get(library, version)
290
+ validate(library, version)
291
+ d = find(library)
292
+ d[:versions].find(version) or
293
+ raise CommandError.new("#{version}: No such version of #{library}.")
294
+ urls = d[:urls]
295
+ if urls
296
+ rexp = /(\/libs\/#{library})\/[^\/]+/
297
+ urls = urls.collect {|x| x.gsub(rexp, "\\1/#{version}") }
298
+ end
299
+ baseurl = "https://ajax.googleapis.com/ajax/libs/#{library}/#{version}"
300
+ files = urls ? urls.collect {|x| x[baseurl.length..-1] } : nil
301
+ return {
302
+ name: d[:name],
303
+ site: d[:site],
304
+ urls: urls,
305
+ files: files,
306
+ baseurl: baseurl,
307
+ version: version,
308
+ }
309
+ end
310
+
311
+ end
312
+
313
+
314
+ #class JQueryCDN < Base
315
+ # CODE = "jquery"
316
+ # SITE_URL = 'https://code.jquery.com/'
317
+ #end
318
+
319
+
320
+ #class ASPNetCDN < Base
321
+ # CODE = "aspnet"
322
+ # SITE_URL = 'https://www.asp.net/ajax/cdn/'
323
+ #end
324
+
325
+
326
+ class CommandError < StandardError
327
+ end
328
+
329
+
330
+ class Main
331
+
332
+ def initialize(script=nil)
333
+ @script = script || File.basename($0)
334
+ end
335
+
336
+ def help_message
337
+ script = @script
338
+ return <<END
339
+ #{script} -- download files from public CDN
340
+
341
+ Usage: #{script} [options] [CDN] [library] [version] [directory]
342
+
343
+ Options:
344
+ -h, --help : help
345
+ -v, --version : version
346
+ -q, --quiet : minimal output
347
+
348
+ Example:
349
+ $ #{script} # list public CDN
350
+ $ #{script} [-q] cdnjs # list libraries
351
+ $ #{script} [-q] cdnjs jquery # list versions
352
+ $ #{script} [-q] cdnjs jquery 2.2.0 # list files
353
+ $ #{script} [-q] cdnjs jquery 2.2.0 /tmp # download files
354
+ END
355
+ end
356
+
357
+ def self.main(args=nil)
358
+ args ||= ARGV
359
+ s = self.new().run(*args)
360
+ puts s if s
361
+ exit 0
362
+ rescue CommandError => ex
363
+ $stderr.puts ex.message
364
+ exit 1
365
+ end
366
+
367
+ def run(*args)
368
+ cmdopts = parse_cmdopts(args, "hvq", ["help", "version", "quiet"])
369
+ return help_message() if cmdopts['h'] || cmdopts['help']
370
+ return RELEASE + "\n" if cmdopts['v'] || cmdopts['version']
371
+ @quiet = cmdopts['quiet'] || cmdopts['q']
372
+ #
373
+ validate(args[1], args[2])
374
+ #
375
+ case args.length
376
+ when 0
377
+ return do_list_cdns()
378
+ when 1
379
+ cdn_code = args[0]
380
+ return do_list_libraries(cdn_code)
381
+ when 2
382
+ cdn_code, library = args
383
+ if library.include?('*')
384
+ return do_search_libraries(cdn_code, library)
385
+ else
386
+ return do_find_library(cdn_code, library)
387
+ end
388
+ when 3
389
+ cdn_code, library, version = args
390
+ return do_get_library(cdn_code, library, version)
391
+ when 4
392
+ cdn_code, library, version, basedir = args
393
+ do_download_library(cdn_code, library, version, basedir)
394
+ return ""
395
+ else
396
+ raise CommandError.new("'#{args[4]}': Too many arguments.")
397
+ end
398
+ end
399
+
400
+ def validate(library, version)
401
+ if library && ! library.include?('*')
402
+ library =~ /\A[-.\w]+\z/ or
403
+ raise CommandError.new("#{library}: Unexpected library name.")
404
+ end
405
+ if version
406
+ version =~ /\A[-.\w]+\z/ or
407
+ raise CommandError.new("#{version}: Unexpected version number.")
408
+ end
409
+ end
410
+
411
+ def parse_cmdopts(cmdargs, short_opts, long_opts)
412
+ cmdopts = {}
413
+ while cmdargs[0] && cmdargs[0].start_with?('-')
414
+ cmdarg = cmdargs.shift
415
+ if cmdarg == '--'
416
+ break
417
+ elsif cmdarg.start_with?('--')
418
+ cmdarg =~ /\A--(\w[-\w]+)(=.*?)?/ or
419
+ raise CommandError.new("#{cmdarg}: invalid command option.")
420
+ name = $1
421
+ value = $2 ? $2[1..-1] : true
422
+ long_opts.include?(name) or
423
+ raise CommandError.new("#{cmdarg}: unknown command option.")
424
+ cmdopts[name] = value
425
+ elsif cmdarg.start_with?('-')
426
+ cmdarg[1..-1].each_char do |c|
427
+ short_opts.include?(c) or
428
+ raise CommandError.new("-#{c}: unknown command option.")
429
+ cmdopts[c] = true
430
+ end
431
+ else
432
+ raise "unreachable"
433
+ end
434
+ end
435
+ return cmdopts
436
+ end
437
+
438
+ def find_cdn(cdn_code)
439
+ klass = CLASSES.find {|c| c::CODE == cdn_code } or
440
+ raise CommandError.new("#{cdn_code}: no such CDN.")
441
+ return klass.new
442
+ end
443
+
444
+ def render_list(list)
445
+ if @quiet
446
+ return list.collect {|d| "#{d[:name]}\n" }.join()
447
+ else
448
+ return list.collect {|d| "%-20s # %s\n" % [d[:name], d[:desc]] }.join()
449
+ end
450
+ end
451
+
452
+ def do_list_cdns
453
+ if @quiet
454
+ return CLASSES.map {|c| "#{c::CODE}\n" }.join()
455
+ else
456
+ return CLASSES.map {|c| "%-10s # %s\n" % [c::CODE, c::SITE_URL] }.join()
457
+ end
458
+ end
459
+
460
+ def do_list_libraries(cdn_code)
461
+ cdn = find_cdn(cdn_code)
462
+ return render_list(cdn.list)
463
+ end
464
+
465
+ def do_search_libraries(cdn_code, pattern)
466
+ cdn = find_cdn(cdn_code)
467
+ rexp_str = pattern.split('*', -1).collect {|x| Regexp.escape(x) }.join('.*')
468
+ rexp = Regexp.compile("\\A#{rexp_str}\\z", Regexp::IGNORECASE)
469
+ return render_list(cdn.list.select {|a| a[:name] =~ rexp })
470
+ end
471
+
472
+ def do_find_library(cdn_code, library)
473
+ cdn = find_cdn(cdn_code)
474
+ d = cdn.find(library)
475
+ s = ""
476
+ if @quiet
477
+ d[:versions].each do |ver|
478
+ s << "#{ver}\n"
479
+ end if d[:versions]
480
+ else
481
+ s << "name: #{d[:name]}\n"
482
+ s << "desc: #{d[:desc]}\n" if d[:desc]
483
+ s << "tags: #{d[:tags]}\n" if d[:tags]
484
+ s << "site: #{d[:site]}\n" if d[:site]
485
+ s << "snippet: |\n" << d[:snippet].gsub(/^/, ' ') if d[:snippet]
486
+ s << "versions:\n"
487
+ d[:versions].each do |ver|
488
+ s << " - #{ver}\n"
489
+ end if d[:versions]
490
+ end
491
+ return s
492
+ end
493
+
494
+ def do_get_library(cdn_code, library, version)
495
+ cdn = find_cdn(cdn_code)
496
+ d = cdn.get(library, version)
497
+ s = ""
498
+ if @quiet
499
+ d[:urls].each do |url|
500
+ s << "#{url}\n"
501
+ end if d[:urls]
502
+ else
503
+ s << "name: #{d[:name]}\n"
504
+ s << "version: #{d[:version]}\n"
505
+ s << "tags: #{d[:tags]}\n" if d[:tags]
506
+ s << "site: #{d[:site]}\n" if d[:site]
507
+ s << "snippet: |\n" << d[:snippet].gsub(/^/, ' ') if d[:snippet]
508
+ s << "urls:\n" if d[:urls]
509
+ d[:urls].each do |url|
510
+ s << " - #{url}\n"
511
+ end if d[:urls]
512
+ end
513
+ return s
514
+ end
515
+
516
+ def do_download_library(cdn_code, library, version, basedir)
517
+ cdn = find_cdn(cdn_code)
518
+ cdn.download(library, version, basedir, quiet: @quiet)
519
+ return nil
520
+ end
521
+
522
+ end
523
+
524
+
525
+ end
526
+
527
+
528
+ #if __FILE__ == $0
529
+ CDNGet::Main.main()
530
+ #end