radiant-ray-extension 3.0.0.alpha
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.
- data/LICENSE +19 -0
- data/README.markdown +30 -0
- data/Rakefile +26 -0
- data/bin/ray +5 -0
- data/doc/Extension.html +1189 -0
- data/doc/Ray.html +175 -0
- data/doc/Ray/CLI.html +585 -0
- data/doc/Ray/Cache.html +709 -0
- data/doc/Ray/Gem.html +760 -0
- data/doc/Ray/Git.html +278 -0
- data/doc/Ray/GitHub.html +553 -0
- data/doc/Ray/RubyGems.html +501 -0
- data/doc/Ray/Zip.html +300 -0
- data/doc/Search.html +433 -0
- data/doc/String.html +242 -0
- data/doc/_index.html +84 -0
- data/doc/class_list.html +47 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +55 -0
- data/doc/css/style.css +322 -0
- data/doc/file.LICENSE.html +85 -0
- data/doc/file.README.html +97 -0
- data/doc/file_list.html +46 -0
- data/doc/frames.html +13 -0
- data/doc/index.html +84 -0
- data/doc/js/app.js +205 -0
- data/doc/js/full_list.js +167 -0
- data/doc/js/jquery.js +16 -0
- data/doc/method_list.html +46 -0
- data/doc/top-level-namespace.html +105 -0
- data/lib/ray.rb +8 -0
- data/lib/ray/cli.rb +271 -0
- data/lib/ray/constants.rb +17 -0
- data/lib/ray/extension.rb +116 -0
- data/lib/ray/extension/gem.rb +96 -0
- data/lib/ray/extension/git.rb +30 -0
- data/lib/ray/extension/zip.rb +44 -0
- data/lib/ray/search.rb +62 -0
- data/lib/ray/search/cache.rb +61 -0
- data/lib/ray/search/github.rb +40 -0
- data/lib/ray/search/rubygems.rb +36 -0
- data/lib/ray/string.rb +18 -0
- data/ray.gemspec +31 -0
- data/spec/fixtures/Gemfile +4 -0
- data/spec/fixtures/cache_single.yml +8 -0
- data/spec/fixtures/cassettes/github_v2_api_no_matches.yml +38 -0
- data/spec/fixtures/cassettes/github_v2_api_search_no_matches.yml +38 -0
- data/spec/fixtures/cassettes/github_v2_api_search_reorder_children.yml +75 -0
- data/spec/fixtures/cassettes/github_v2_api_search_single.yml +74 -0
- data/spec/fixtures/cassettes/github_v3_api_owner_name.yml +75 -0
- data/spec/fixtures/cassettes/rubygems_v1_api_gem_info.yml +36 -0
- data/spec/fixtures/cassettes/rubygems_v1_api_no_matches.yml +34 -0
- data/spec/fixtures/cassettes/rubygems_v1_api_search_no_matches.yml +34 -0
- data/spec/fixtures/cassettes/rubygems_v1_api_search_reorder.yml +36 -0
- data/spec/fixtures/cassettes/rubygems_v1_api_search_reorder_children.yml +36 -0
- data/spec/fixtures/cassettes/rubygems_v1_api_search_single.yml +41 -0
- data/spec/fixtures/cassettes/zip_file.yml +101 -0
- data/spec/fixtures/dummy.zip +0 -0
- data/spec/fixtures/dummy/README +1 -0
- data/spec/fixtures/dummy/Rakefile +109 -0
- data/spec/fixtures/dummy/config/initializers/radiant_config.rb +3 -0
- data/spec/fixtures/dummy/config/locales/en.yml +3 -0
- data/spec/fixtures/dummy/config/routes.rb +5 -0
- data/spec/fixtures/dummy/dummy_extension.rb +21 -0
- data/spec/fixtures/dummy/lib/radiant-dummy-extension.rb +8 -0
- data/spec/fixtures/dummy/lib/tasks/dummy_extension_tasks.rake +47 -0
- data/spec/fixtures/dummy/public/stylesheets/extensions/dummy/dummy.css +0 -0
- data/spec/fixtures/dummy/radiant-dummy-extension.gemspec +29 -0
- data/spec/ray/cli_spec.rb +56 -0
- data/spec/ray/extension/gem_spec.rb +214 -0
- data/spec/ray/extension/git_spec.rb +216 -0
- data/spec/ray/extension/zip_spec.rb +239 -0
- data/spec/ray/search/cache_spec.rb +74 -0
- data/spec/ray/search/github_spec.rb +137 -0
- data/spec/ray/search/rubygems_spec.rb +127 -0
- data/spec/ray/string_spec.rb +30 -0
- data/spec/spec_helper.rb +27 -0
- metadata +205 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# Friendly extension management for Radiant CMS
|
2
|
+
module Ray
|
3
|
+
|
4
|
+
VERSION = "3.0.0.alpha"
|
5
|
+
|
6
|
+
RAY = File.expand_path "~/.ray"
|
7
|
+
CACHE = "#{RAY}/cache.yml"
|
8
|
+
|
9
|
+
ROOT = File.expand_path Dir.pwd
|
10
|
+
GEMFILE = "#{ROOT}/Gemfile"
|
11
|
+
EXT_DIR = "#{ROOT}/vendor/extensions"
|
12
|
+
TMP_DIR = "#{ROOT}/tmp/ray"
|
13
|
+
RG_V1_API = "http://rubygems.org/api/v1"
|
14
|
+
GH_V2_API = "http://github.com/api/v2/json"
|
15
|
+
GH_V3_API = "https://api.github.com"
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "open-uri"
|
3
|
+
require "rake"
|
4
|
+
require "ray/string"
|
5
|
+
|
6
|
+
module Extension
|
7
|
+
|
8
|
+
attr_accessor :author,
|
9
|
+
:description,
|
10
|
+
:homepage,
|
11
|
+
:name,
|
12
|
+
:uri,
|
13
|
+
:version
|
14
|
+
|
15
|
+
def initialize options = {}
|
16
|
+
@author = options[:author]
|
17
|
+
@description = options[:description]
|
18
|
+
@homepage = options[:homepage]
|
19
|
+
@name = options[:name].to_s.to_extension_name
|
20
|
+
@uri = options[:uri]
|
21
|
+
@version = options[:version]
|
22
|
+
end
|
23
|
+
|
24
|
+
def disable
|
25
|
+
unless File.exist? "#{Ray::EXT_DIR}/#{@name}"
|
26
|
+
raise "The #{@name} extension is not installed"
|
27
|
+
end
|
28
|
+
|
29
|
+
FileUtils.mkdir_p "#{Ray::EXT_DIR}/.disabled"
|
30
|
+
FileUtils.mv "#{Ray::EXT_DIR}/#{@name}", "#{Ray::EXT_DIR}/.disabled/#{@name}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def enable
|
34
|
+
unless File.exist? "#{Ray::EXT_DIR}/.disabled/#{@name}"
|
35
|
+
raise "The #{@name} extension is not disabled"
|
36
|
+
end
|
37
|
+
|
38
|
+
FileUtils.mv "#{Ray::EXT_DIR}/.disabled/#{@name}", "#{Ray::EXT_DIR}/#{@name}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def uninstall
|
42
|
+
unless File.exist? "#{Ray::EXT_DIR}/#{@name}"
|
43
|
+
raise "The #{@name} extension is not installed"
|
44
|
+
end
|
45
|
+
|
46
|
+
run_tasks({
|
47
|
+
:migrate => "VERSION=0",
|
48
|
+
:update => :psa
|
49
|
+
})
|
50
|
+
FileUtils.rm_rf "#{Ray::EXT_DIR}/#{@name}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def download
|
54
|
+
raise "The extension name is required" unless @name
|
55
|
+
raise "The extension URI is required" unless @uri
|
56
|
+
|
57
|
+
puts "#{@name} => Downloading..."
|
58
|
+
FileUtils.mkdir_p Ray::TMP_DIR
|
59
|
+
tmpfile = open(@uri).path
|
60
|
+
FileUtils.cp tmpfile, "#{Ray::TMP_DIR}/#{@uri.split('/').last}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def vendor
|
64
|
+
puts "#{@name} => Vendoring..."
|
65
|
+
directory = Dir.glob("#{Ray::TMP_DIR}/*").first
|
66
|
+
FileUtils.mv directory, "#{Ray::EXT_DIR}/#{@name}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def run_tasks options = { :migrate => "", :update => "" }
|
70
|
+
tasks = load_tasks
|
71
|
+
tasks.each do |task|
|
72
|
+
case task
|
73
|
+
when "radiant:extensions:#{@name}:install"
|
74
|
+
run_task "install"
|
75
|
+
break
|
76
|
+
when "radiant:extensions:#{@name}:migrate"
|
77
|
+
run_task "migrate", options[:migrate]
|
78
|
+
when "radiant:extensions:#{@name}:update"
|
79
|
+
run_task "update", options[:update]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def run_task task, options = {}
|
85
|
+
puts "#{@name} => Running #{task} task..."
|
86
|
+
if task == "update" and options == :psa
|
87
|
+
public_service_announcement
|
88
|
+
else
|
89
|
+
`rake radiant:extensions:#{@name}:#{task} #{options}`
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_tasks
|
94
|
+
puts "#{@name} => Loading tasks..."
|
95
|
+
rake_file = "#{Ray::ROOT}/vendor/extensions/#{@name}/lib/tasks/#{@name}_extension_tasks.rake"
|
96
|
+
load rake_file if File.exist? rake_file
|
97
|
+
Rake.application.tasks.map(&:name)
|
98
|
+
end
|
99
|
+
|
100
|
+
def cleanup
|
101
|
+
puts "#{@name} => Removing temporary files..."
|
102
|
+
FileUtils.rm_rf Ray::TMP_DIR
|
103
|
+
end
|
104
|
+
|
105
|
+
def public_service_announcement path = nil
|
106
|
+
path ||= "#{Ray::EXT_DIR}/#{@name}"
|
107
|
+
Dir.glob("#{path}/public/**/*.*").each do |f|
|
108
|
+
FileUtils.rm_rf File.expand_path(f.sub! /#{path}\//, "")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def name= name
|
113
|
+
@name = name.to_extension_name
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
require "ray/extension"
|
3
|
+
|
4
|
+
module Ray
|
5
|
+
|
6
|
+
class Gem
|
7
|
+
|
8
|
+
include Extension
|
9
|
+
|
10
|
+
def initialize options = {}
|
11
|
+
@author = options[:author]
|
12
|
+
@description = options[:description]
|
13
|
+
@homepage = options[:homepage]
|
14
|
+
@name = options[:name].to_s.to_extension_name
|
15
|
+
@uri = options[:uri]
|
16
|
+
@version = options[:version] || version
|
17
|
+
end
|
18
|
+
|
19
|
+
def install
|
20
|
+
unless @name
|
21
|
+
raise "The extension name is required"
|
22
|
+
end
|
23
|
+
|
24
|
+
add_gem
|
25
|
+
bundle
|
26
|
+
copy_tasks
|
27
|
+
run_tasks
|
28
|
+
end
|
29
|
+
alias enable install
|
30
|
+
|
31
|
+
def add_gem
|
32
|
+
puts "#{@name} => Adding to Gemfile..."
|
33
|
+
File.open GEMFILE, "a" do |gemfile|
|
34
|
+
gemfile.puts "gem \"radiant-#{@name}-extension\", \"~> #{@version}\""
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def version
|
39
|
+
return 0 unless @name
|
40
|
+
uri = "#{RG_V1_API}/gems/radiant-#{@name}-extension.json"
|
41
|
+
response = open(uri).read
|
42
|
+
MultiJson.decode(response)["version"]
|
43
|
+
end
|
44
|
+
|
45
|
+
def bundle
|
46
|
+
puts "#{@name} => Bundling..."
|
47
|
+
FileUtils.rm "#{Ray::GEMFILE}.lock"
|
48
|
+
`bundle update`
|
49
|
+
end
|
50
|
+
|
51
|
+
def copy_tasks
|
52
|
+
puts "#{@name} => Copying tasks..."
|
53
|
+
path = `bundle show radiant-#{@name}-extension`.chomp
|
54
|
+
tasks = "#{path}/lib/tasks/#{@name}_extension_tasks.rake"
|
55
|
+
if File.exist? tasks
|
56
|
+
FileUtils.cp tasks, "#{Ray::ROOT}/lib/tasks/"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_tasks
|
61
|
+
puts "#{@name} => Loading tasks..."
|
62
|
+
rake_file = "#{Ray::ROOT}/lib/tasks/#{@name}_extension_tasks.rake"
|
63
|
+
load rake_file if File.exist? rake_file
|
64
|
+
Rake.application.tasks.map(&:name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def disable
|
68
|
+
puts "#{@name} => Removing from Gemfile..."
|
69
|
+
current_gemfile = File.read GEMFILE
|
70
|
+
updated_gemfile = current_gemfile.sub /gem "radiant-#{@name}-extension".+\n/, ""
|
71
|
+
File.open GEMFILE, "w" do |gemfile|
|
72
|
+
gemfile.puts updated_gemfile
|
73
|
+
end
|
74
|
+
bundle
|
75
|
+
end
|
76
|
+
|
77
|
+
def uninstall
|
78
|
+
run_tasks({
|
79
|
+
:migrate => "VERSION=0",
|
80
|
+
:update => :psa
|
81
|
+
})
|
82
|
+
disable
|
83
|
+
end
|
84
|
+
|
85
|
+
def run_task task, options = ""
|
86
|
+
puts "#{@name} => Running #{task} task..."
|
87
|
+
if task == "update" and options == :psa
|
88
|
+
public_service_announcement `bundle show radiant-#{@name}-extension`.chop
|
89
|
+
else
|
90
|
+
`rake radiant:extensions:#{@name}:#{task} #{options}`
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "ray/extension"
|
2
|
+
|
3
|
+
module Ray
|
4
|
+
|
5
|
+
class Git
|
6
|
+
|
7
|
+
include Extension
|
8
|
+
|
9
|
+
def install
|
10
|
+
if File.exist? "#{Ray::EXT_DIR}/#{@name}"
|
11
|
+
raise "The #{@name} extension is already installed"
|
12
|
+
end
|
13
|
+
|
14
|
+
clone
|
15
|
+
vendor
|
16
|
+
run_tasks
|
17
|
+
cleanup
|
18
|
+
end
|
19
|
+
|
20
|
+
def clone
|
21
|
+
puts "#{@name} => Cloning..."
|
22
|
+
raise "The extension name is required" unless @name
|
23
|
+
raise "The repository URI is required" unless @uri
|
24
|
+
`git clone --depth=1 --quiet #{@uri} #{Ray::TMP_DIR}/#{@name}`
|
25
|
+
FileUtils.rm_rf "#{Ray::TMP_DIR}/#{@name}/.git"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "zip"
|
2
|
+
require "ray/extension"
|
3
|
+
|
4
|
+
# set StringMax to 0 so open-uri always creates a tmp file
|
5
|
+
OpenURI::Buffer.send :remove_const, "StringMax"
|
6
|
+
OpenURI::Buffer.const_set "StringMax", 0
|
7
|
+
|
8
|
+
module Ray
|
9
|
+
|
10
|
+
class Zip
|
11
|
+
|
12
|
+
include Extension
|
13
|
+
|
14
|
+
def install
|
15
|
+
if File.exist? "#{Ray::EXT_DIR}/#{@name}"
|
16
|
+
raise "The #{@name} extension is already installed"
|
17
|
+
end
|
18
|
+
|
19
|
+
download
|
20
|
+
extract
|
21
|
+
vendor
|
22
|
+
run_tasks
|
23
|
+
cleanup
|
24
|
+
end
|
25
|
+
|
26
|
+
def extract
|
27
|
+
if Dir.glob("#{Ray::TMP_DIR}/*").size != 1
|
28
|
+
raise "The file does not exist"
|
29
|
+
end
|
30
|
+
|
31
|
+
archive = Dir.glob("#{Ray::TMP_DIR}/*").first
|
32
|
+
::Zip::ZipFile.open archive do |zip_file|
|
33
|
+
zip_file.each do |f|
|
34
|
+
f_path = File.join "#{Ray::TMP_DIR}", f.name
|
35
|
+
FileUtils.mkdir_p File.dirname f_path
|
36
|
+
zip_file.extract f, f_path unless File.exist? f_path
|
37
|
+
end
|
38
|
+
end
|
39
|
+
FileUtils.rm archive
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/lib/ray/search.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "multi_json"
|
3
|
+
require "open-uri"
|
4
|
+
require "ray/string"
|
5
|
+
require "yaml"
|
6
|
+
|
7
|
+
module Search
|
8
|
+
|
9
|
+
def search
|
10
|
+
normalize open(@uri).read
|
11
|
+
end
|
12
|
+
|
13
|
+
def cache
|
14
|
+
if File.exist? Ray::CACHE
|
15
|
+
cache = YAML.load_file Ray::CACHE
|
16
|
+
else
|
17
|
+
FileUtils.mkdir_p Ray::RAY
|
18
|
+
FileUtils.touch Ray::CACHE
|
19
|
+
cache = {}
|
20
|
+
end
|
21
|
+
File.open Ray::CACHE, "w" do |f|
|
22
|
+
f.write cache.merge(@results).to_yaml
|
23
|
+
end
|
24
|
+
return self
|
25
|
+
end
|
26
|
+
|
27
|
+
def output
|
28
|
+
output = ""
|
29
|
+
if @results.empty?
|
30
|
+
output += %Q{
|
31
|
+
No extensions matched: #{@query}
|
32
|
+
# URI: #{@uri}
|
33
|
+
}.lstrip
|
34
|
+
else
|
35
|
+
@results.each do |extension|
|
36
|
+
name = extension.first.to_extension_name
|
37
|
+
info = extension.last
|
38
|
+
output += %Q{
|
39
|
+
#{"-" * 80}
|
40
|
+
#{name} (#{info[:version]}) by #{info[:author][0..(78 - " #{name} (#{info[:version]}) by ".size)]}
|
41
|
+
#{info[:description].wrap(78, 2)}
|
42
|
+
#{info[:homepage]}
|
43
|
+
ray install #{name}\n
|
44
|
+
}.lstrip
|
45
|
+
end
|
46
|
+
return output
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def multiple_choice
|
51
|
+
puts output
|
52
|
+
print "Which extension do you want to install? "
|
53
|
+
choice = STDIN.gets.chomp
|
54
|
+
@results[choice]
|
55
|
+
end
|
56
|
+
|
57
|
+
def merge other
|
58
|
+
self.results.merge! other.results
|
59
|
+
return self
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "ray/search"
|
3
|
+
require "ray/string"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
module Ray
|
7
|
+
|
8
|
+
class Cache
|
9
|
+
|
10
|
+
include Search
|
11
|
+
|
12
|
+
attr_reader :query, :uri
|
13
|
+
attr_accessor :results
|
14
|
+
|
15
|
+
def initialize query
|
16
|
+
@query = query
|
17
|
+
@results = search
|
18
|
+
@uri = Ray::CACHE
|
19
|
+
end
|
20
|
+
|
21
|
+
def search
|
22
|
+
return {} unless File.exist? Ray::CACHE
|
23
|
+
cache = YAML.load_file Ray::CACHE
|
24
|
+
results = {}
|
25
|
+
cache.each do |extension|
|
26
|
+
name = extension.first
|
27
|
+
info = extension.last
|
28
|
+
if match? name, info[:description]
|
29
|
+
results[name] = {
|
30
|
+
:author => info[:author],
|
31
|
+
:description => info[:description],
|
32
|
+
:homepage => info[:homepage],
|
33
|
+
:name => name,
|
34
|
+
:uri => info[:uri],
|
35
|
+
:version => info[:version]
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
return results
|
40
|
+
end
|
41
|
+
|
42
|
+
def match? name, description
|
43
|
+
if "#{name} #{description}".include?(@query)
|
44
|
+
return true
|
45
|
+
elsif name.include?(@query.to_extension_name)
|
46
|
+
return true
|
47
|
+
end
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.clear
|
52
|
+
FileUtils.rm Ray::CACHE
|
53
|
+
end
|
54
|
+
|
55
|
+
def cache
|
56
|
+
return self
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "ray/search"
|
2
|
+
|
3
|
+
module Ray
|
4
|
+
|
5
|
+
class GitHub
|
6
|
+
|
7
|
+
include Search
|
8
|
+
|
9
|
+
attr_reader :query, :results, :uri
|
10
|
+
|
11
|
+
def initialize query
|
12
|
+
@query = query
|
13
|
+
@uri = "#{Ray::GH_V2_API}/repos/search/radiant+#{@query}"
|
14
|
+
@results = search
|
15
|
+
end
|
16
|
+
|
17
|
+
def normalize response
|
18
|
+
response = MultiJson.decode response
|
19
|
+
results = {}
|
20
|
+
response["repositories"].each do |extension|
|
21
|
+
results[extension["name"].to_extension_name] = {
|
22
|
+
:author => real_name(extension["owner"]),
|
23
|
+
:description => extension["description"],
|
24
|
+
:homepage => extension["url"],
|
25
|
+
:name => extension["name"].to_extension_name,
|
26
|
+
:uri => extension["url"],
|
27
|
+
:version => "latest"
|
28
|
+
}
|
29
|
+
end
|
30
|
+
return results
|
31
|
+
end
|
32
|
+
|
33
|
+
def real_name owner
|
34
|
+
response = open("#{GH_V3_API}/users/#{owner}").read
|
35
|
+
MultiJson.decode(response)["name"]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|