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.
Files changed (78) hide show
  1. data/LICENSE +19 -0
  2. data/README.markdown +30 -0
  3. data/Rakefile +26 -0
  4. data/bin/ray +5 -0
  5. data/doc/Extension.html +1189 -0
  6. data/doc/Ray.html +175 -0
  7. data/doc/Ray/CLI.html +585 -0
  8. data/doc/Ray/Cache.html +709 -0
  9. data/doc/Ray/Gem.html +760 -0
  10. data/doc/Ray/Git.html +278 -0
  11. data/doc/Ray/GitHub.html +553 -0
  12. data/doc/Ray/RubyGems.html +501 -0
  13. data/doc/Ray/Zip.html +300 -0
  14. data/doc/Search.html +433 -0
  15. data/doc/String.html +242 -0
  16. data/doc/_index.html +84 -0
  17. data/doc/class_list.html +47 -0
  18. data/doc/css/common.css +1 -0
  19. data/doc/css/full_list.css +55 -0
  20. data/doc/css/style.css +322 -0
  21. data/doc/file.LICENSE.html +85 -0
  22. data/doc/file.README.html +97 -0
  23. data/doc/file_list.html +46 -0
  24. data/doc/frames.html +13 -0
  25. data/doc/index.html +84 -0
  26. data/doc/js/app.js +205 -0
  27. data/doc/js/full_list.js +167 -0
  28. data/doc/js/jquery.js +16 -0
  29. data/doc/method_list.html +46 -0
  30. data/doc/top-level-namespace.html +105 -0
  31. data/lib/ray.rb +8 -0
  32. data/lib/ray/cli.rb +271 -0
  33. data/lib/ray/constants.rb +17 -0
  34. data/lib/ray/extension.rb +116 -0
  35. data/lib/ray/extension/gem.rb +96 -0
  36. data/lib/ray/extension/git.rb +30 -0
  37. data/lib/ray/extension/zip.rb +44 -0
  38. data/lib/ray/search.rb +62 -0
  39. data/lib/ray/search/cache.rb +61 -0
  40. data/lib/ray/search/github.rb +40 -0
  41. data/lib/ray/search/rubygems.rb +36 -0
  42. data/lib/ray/string.rb +18 -0
  43. data/ray.gemspec +31 -0
  44. data/spec/fixtures/Gemfile +4 -0
  45. data/spec/fixtures/cache_single.yml +8 -0
  46. data/spec/fixtures/cassettes/github_v2_api_no_matches.yml +38 -0
  47. data/spec/fixtures/cassettes/github_v2_api_search_no_matches.yml +38 -0
  48. data/spec/fixtures/cassettes/github_v2_api_search_reorder_children.yml +75 -0
  49. data/spec/fixtures/cassettes/github_v2_api_search_single.yml +74 -0
  50. data/spec/fixtures/cassettes/github_v3_api_owner_name.yml +75 -0
  51. data/spec/fixtures/cassettes/rubygems_v1_api_gem_info.yml +36 -0
  52. data/spec/fixtures/cassettes/rubygems_v1_api_no_matches.yml +34 -0
  53. data/spec/fixtures/cassettes/rubygems_v1_api_search_no_matches.yml +34 -0
  54. data/spec/fixtures/cassettes/rubygems_v1_api_search_reorder.yml +36 -0
  55. data/spec/fixtures/cassettes/rubygems_v1_api_search_reorder_children.yml +36 -0
  56. data/spec/fixtures/cassettes/rubygems_v1_api_search_single.yml +41 -0
  57. data/spec/fixtures/cassettes/zip_file.yml +101 -0
  58. data/spec/fixtures/dummy.zip +0 -0
  59. data/spec/fixtures/dummy/README +1 -0
  60. data/spec/fixtures/dummy/Rakefile +109 -0
  61. data/spec/fixtures/dummy/config/initializers/radiant_config.rb +3 -0
  62. data/spec/fixtures/dummy/config/locales/en.yml +3 -0
  63. data/spec/fixtures/dummy/config/routes.rb +5 -0
  64. data/spec/fixtures/dummy/dummy_extension.rb +21 -0
  65. data/spec/fixtures/dummy/lib/radiant-dummy-extension.rb +8 -0
  66. data/spec/fixtures/dummy/lib/tasks/dummy_extension_tasks.rake +47 -0
  67. data/spec/fixtures/dummy/public/stylesheets/extensions/dummy/dummy.css +0 -0
  68. data/spec/fixtures/dummy/radiant-dummy-extension.gemspec +29 -0
  69. data/spec/ray/cli_spec.rb +56 -0
  70. data/spec/ray/extension/gem_spec.rb +214 -0
  71. data/spec/ray/extension/git_spec.rb +216 -0
  72. data/spec/ray/extension/zip_spec.rb +239 -0
  73. data/spec/ray/search/cache_spec.rb +74 -0
  74. data/spec/ray/search/github_spec.rb +137 -0
  75. data/spec/ray/search/rubygems_spec.rb +127 -0
  76. data/spec/ray/string_spec.rb +30 -0
  77. data/spec/spec_helper.rb +27 -0
  78. 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
@@ -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