opencode_theme 0.0.5
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +13 -0
- data/bin/opencode +22 -0
- data/lib/opencode_theme.rb +74 -0
- data/lib/opencode_theme/base_service.rb +69 -0
- data/lib/opencode_theme/cli.rb +319 -0
- data/lib/opencode_theme/version.rb +3 -0
- data/opencode_theme.gemspec +35 -0
- data/spec/functional/functional_spec.rb +153 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/unit/cli_double.rb +65 -0
- data/spec/unit/cli_spec.rb +24 -0
- metadata +215 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3e2995bdcd55b2874d519fb2f4653ddac6441471
|
4
|
+
data.tar.gz: 7ac1b792ea2f5f8b5bbe589def50a308781430ba
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7fc3f4a94ba2841bd2b9401e8c932d50872de8e5bf569b614e2f40c357e4648e00b104f78a1ffe9cb1ef0423d1a12a75ed3a7a5231b428e0424d523a951ae4a8
|
7
|
+
data.tar.gz: 83c17ca7ea25b31c3c74fa63f25e6d2137fd95976b438168c961b5f7ce31ba21a870c3769e82f3b3df79d7134f97bde14a893aadd7a6a15b452dbf10dacf2f3e
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Rafael Takashi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# OpencodeTheme
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'opencode_theme'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install opencode_theme
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
task :default => [:spec]
|
6
|
+
|
7
|
+
Rake::TestTask.new 'spec' do |t|
|
8
|
+
ENV['test'] = 'true'
|
9
|
+
t.libs = ['lib', 'spec']
|
10
|
+
t.ruby_opts << '-rubygems'
|
11
|
+
t.verbose = true
|
12
|
+
t.test_files = FileList['spec/**/*_spec.rb']
|
13
|
+
end
|
data/bin/opencode
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# This allows opencode_theme to run easily from a git checkout without install.
|
4
|
+
# Hat tip to chriseppstein of Compass fame for the code for this
|
5
|
+
def fallback_load_path(path)
|
6
|
+
retried = false
|
7
|
+
begin
|
8
|
+
yield
|
9
|
+
rescue LoadError
|
10
|
+
unless retried
|
11
|
+
$: << path
|
12
|
+
retried = true
|
13
|
+
retry
|
14
|
+
end
|
15
|
+
raise
|
16
|
+
end
|
17
|
+
end
|
18
|
+
fallback_load_path(File.join(File.dirname(__FILE__), '..', 'lib')) do
|
19
|
+
require 'opencode_theme'
|
20
|
+
require 'opencode_theme/cli'
|
21
|
+
end
|
22
|
+
OpencodeTheme::Cli.start(ARGV)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "opencode_theme/version"
|
2
|
+
require 'opencode_theme/base_service'
|
3
|
+
|
4
|
+
module OpencodeTheme
|
5
|
+
|
6
|
+
NOOPParser = Proc.new {|data, format| {} }
|
7
|
+
TIMER_RESET = 10
|
8
|
+
PERMIT_LOWER_LIMIT = 3
|
9
|
+
CONFIG_FILE = 'config.yml'
|
10
|
+
|
11
|
+
def self.test?
|
12
|
+
ENV['test']
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.critical_permits?
|
16
|
+
@@total_api_calls.to_i - @@current_api_call_count.to_i < PERMIT_LOWER_LIMIT
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.passed_api_refresh?
|
20
|
+
delta_seconds > TIMER_RESET
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.delta_seconds
|
24
|
+
Time.now.to_i - @@current_timer.to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.needs_sleep?
|
28
|
+
critical_permits? && !passed_api_refresh?
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.sleep
|
32
|
+
if needs_sleep?
|
33
|
+
Kernel.sleep(TIMER_RESET - delta_seconds)
|
34
|
+
@current_timer = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.config
|
39
|
+
@config ||= if File.exist? CONFIG_FILE
|
40
|
+
config = YAML.load(File.read(CONFIG_FILE))
|
41
|
+
config
|
42
|
+
else
|
43
|
+
puts "#{CONFIG_FILE} does not exist!" unless test?
|
44
|
+
{}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.config=(config)
|
49
|
+
@config = config
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def self.is_binary_data?(string)
|
54
|
+
if string.respond_to?(:encoding)
|
55
|
+
string.encoding == "US-ASCII"
|
56
|
+
else
|
57
|
+
( string.count( "^ -~", "^\r\n" ).fdiv(string.size) > 0.3 || string.index( "\x00" ) ) unless string.empty?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.path(type = nil)
|
62
|
+
@path ||= config[:theme_id] ? "/api/themes/#{config[:theme_id]}/assets" : "/api/themes/assets"
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def self.ignore_files
|
67
|
+
(config[:ignore_files] || []).compact.map { |r| Regexp.new(r) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.whitelist_files
|
71
|
+
(config[:whitelist_files] || []).compact
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
module OpencodeTheme
|
3
|
+
include HTTParty
|
4
|
+
default_options.update(verify: false)
|
5
|
+
@@current_api_call_count = 0
|
6
|
+
@@total_api_calls = 40
|
7
|
+
URL_API = "https://opencode.tray.com.br"
|
8
|
+
|
9
|
+
def self.api_usage
|
10
|
+
"[API Limit: #{@@current_api_call_count || "??"}/#{@@total_api_calls || "??"}]"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.check_config
|
14
|
+
response = opencode_theme.post("/api/check", :query => {:theme_id => config[:theme_id] })
|
15
|
+
return {success: response.success?, response: JSON.parse(response.body)}
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.list
|
19
|
+
response = opencode_theme.get("/api/list")
|
20
|
+
return {success: response.success?, response: JSON.parse(response.body)}
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.clean
|
24
|
+
response = opencode_theme.post("/api/clean_cache", :query => {:theme_id => config[:theme_id] })
|
25
|
+
return {success: response.success?, response: JSON.parse(response.body)}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.theme_delete(theme_id)
|
29
|
+
response = opencode_theme.delete("/api/themes/#{theme_id}", :parser => NOOPParser)
|
30
|
+
return {success: response.success?, response: JSON.parse(response.body)}
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.theme_new(theme_base, theme_name)
|
34
|
+
response = opencode_theme.post("/api/themes", :body => {:theme => {:theme_base => theme_name, :name => theme_name}}.to_json,
|
35
|
+
:headers => { 'Content-Type' => 'application/json'}, :parser => NOOPParser)
|
36
|
+
assets = response.code == 200 ? JSON.parse(response.body)["assets"] : {}
|
37
|
+
return {success: response.success?, assets: assets, response: JSON.parse(response.body)}
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.asset_list
|
41
|
+
response = opencode_theme.get(path, :parser => NOOPParser)
|
42
|
+
assets = response.code == 200 ? JSON.parse(response.body)["assets"].collect {|a| a['key'][1..a['key'].length] } : {}
|
43
|
+
assets
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.get_asset(asset)
|
47
|
+
response = opencode_theme.get(path, :query => {:key => "/#{asset}"}, :parser => NOOPParser)
|
48
|
+
asset = response.code == 200 ? JSON.parse(response.body) : ""
|
49
|
+
asset
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.send_asset(data)
|
53
|
+
response = opencode_theme.put(path, :body => data)
|
54
|
+
response
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.delete_asset(asset)
|
58
|
+
response = opencode_theme.delete(path, :body => {:key => "/#{asset}"})
|
59
|
+
response
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def self.opencode_theme
|
64
|
+
base_uri URL_API
|
65
|
+
headers "Authorization" => "Token token=#{config[:api_key]}_#{config[:password]}"
|
66
|
+
OpencodeTheme
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,319 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'thor'
|
3
|
+
require 'yaml'
|
4
|
+
YAML::ENGINE.yamler = 'syck' if defined? Syck
|
5
|
+
require 'abbrev'
|
6
|
+
require 'base64'
|
7
|
+
require 'fileutils'
|
8
|
+
require 'json'
|
9
|
+
require 'filewatcher'
|
10
|
+
require 'launchy'
|
11
|
+
require 'mimemagic'
|
12
|
+
MimeMagic.add('application/json', extensions: %w(json js), parents: 'text/plain')
|
13
|
+
MimeMagic.add('application/x-pointplus', extensions: %w(scss), parents: 'text/css')
|
14
|
+
MimeMagic.add('application/vnd.ms-fontobject', extensions: %w(eot), parents: 'font/opentype')
|
15
|
+
|
16
|
+
|
17
|
+
module OpencodeTheme
|
18
|
+
class Cli < Thor
|
19
|
+
include Thor::Actions
|
20
|
+
|
21
|
+
IGNORE = %w(config.yml)
|
22
|
+
DEFAULT_WHITELIST = %w(configs/ css/ elements/ img/ layouts/ pages/ js/)
|
23
|
+
TIMEFORMAT = "%H:%M:%S"
|
24
|
+
|
25
|
+
tasks.keys.abbrev.each do |shortcut, command|
|
26
|
+
map shortcut => command.to_sym
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "configure API_KEY PASSWORD THEME_ID", "Configura o tema que sera modificado"
|
30
|
+
def configure(api_key=nil, password=nil, theme_id=nil)
|
31
|
+
config = {:api_key => api_key, :password => password, :theme_id => theme_id}
|
32
|
+
OpencodeTheme.config = config
|
33
|
+
response = OpencodeTheme.check_config
|
34
|
+
if response[:success]
|
35
|
+
config.merge!(:preview_url => response[:response]['preview'])
|
36
|
+
create_file('config.yml', config.to_yaml, :force => true)
|
37
|
+
say("Configuration [OK]", :green)
|
38
|
+
else
|
39
|
+
say("Configuration [FAIL]", :red)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "list", "Lista todos os temas da loja"
|
44
|
+
def list
|
45
|
+
config = OpencodeTheme.config
|
46
|
+
response = OpencodeTheme.list
|
47
|
+
if response[:success]
|
48
|
+
say("\n")
|
49
|
+
response[:response]["themes"].each do |theme|
|
50
|
+
color = theme['published'] == "1" ? :green : :red
|
51
|
+
say("Theme name: ", color)
|
52
|
+
say("#{theme['name']}\n", color)
|
53
|
+
say("Theme ID: ", color)
|
54
|
+
say("#{theme['id']}\n", color)
|
55
|
+
say("Theme status: ", color)
|
56
|
+
say("#{(theme['published'])}\n\n", color)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
report_error(Time.now, "Could not list now", response[:response])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "clean", "Limpa o cache de arquivos estáticos"
|
64
|
+
def clean
|
65
|
+
config = OpencodeTheme.config
|
66
|
+
response = OpencodeTheme.clean
|
67
|
+
if response[:success]
|
68
|
+
say("Clean cache [OK]\n", :green)
|
69
|
+
else
|
70
|
+
say("Clean cache [FAIL]", :red)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
desc "bootstrap API_KEY PASSWORD THEME_NAME THEME_BASE", "Cria um novo tema com o nome informado"
|
75
|
+
method_option :master, :type => :boolean, :default => false
|
76
|
+
def bootstrap(api_key=nil, password=nil, theme_name='default', theme_base='default')
|
77
|
+
OpencodeTheme.config = {:api_key => api_key, :password => password}
|
78
|
+
|
79
|
+
check_config = OpencodeTheme.check_config
|
80
|
+
|
81
|
+
if check_config[:success]
|
82
|
+
say("Configuration [OK]", :green)
|
83
|
+
else
|
84
|
+
report_error(Time.now, "Configuration [FAIL]", check_config[:response])
|
85
|
+
return
|
86
|
+
end
|
87
|
+
|
88
|
+
response = OpencodeTheme.theme_new(theme_base, theme_name)
|
89
|
+
|
90
|
+
if response[:success]
|
91
|
+
say("Create #{theme_name} theme on store", :green)
|
92
|
+
else
|
93
|
+
report_error(Time.now, "Could not create a new theme", response[:response])
|
94
|
+
return
|
95
|
+
end
|
96
|
+
|
97
|
+
say("Creating directory named #{theme_name}", :green)
|
98
|
+
empty_directory(theme_name)
|
99
|
+
|
100
|
+
say("Saving configuration to #{theme_name}", :green)
|
101
|
+
OpencodeTheme.config.merge!(theme_id: response[:response]['theme_id'], preview_url: response[:response]['preview'])
|
102
|
+
create_file("#{theme_name}/config.yml", OpencodeTheme.config.to_yaml)
|
103
|
+
|
104
|
+
say("Downloading #{theme_name} assets from Opencode")
|
105
|
+
Dir.chdir(theme_name)
|
106
|
+
download()
|
107
|
+
end
|
108
|
+
|
109
|
+
desc "open", "Abre a loja no navegador"
|
110
|
+
def open(*keys)
|
111
|
+
if Launchy.open opencode_theme_url
|
112
|
+
say("Done.", :green)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
desc "download FILE", "Baixa o arquivo informado ou todos se FILE for omitido"
|
117
|
+
method_option :quiet, :type => :boolean, :default => false
|
118
|
+
method_option :exclude
|
119
|
+
def download(*keys)
|
120
|
+
assets = keys.empty? ? OpencodeTheme.asset_list : keys
|
121
|
+
if options['exclude']
|
122
|
+
assets = assets.delete_if { |asset| asset =~ Regexp.new(options['exclude']) }
|
123
|
+
end
|
124
|
+
|
125
|
+
assets.each do |asset|
|
126
|
+
asset = URI.decode(asset)
|
127
|
+
download_asset(asset)
|
128
|
+
say("#{OpencodeTheme.api_usage} Downloaded: #{asset}", :green) unless options['quiet']
|
129
|
+
end
|
130
|
+
say("Done.", :green) unless options['quiet']
|
131
|
+
end
|
132
|
+
|
133
|
+
desc "upload FILE", "Sobe o arquivo informado ou todos se FILE for omitido"
|
134
|
+
method_option :quiet, :type => :boolean, :default => false
|
135
|
+
def upload(*keys)
|
136
|
+
assets = keys.empty? ? local_assets_list : keys
|
137
|
+
assets.each do |asset|
|
138
|
+
send_asset("#{asset}", options['quiet'])
|
139
|
+
end
|
140
|
+
say("Done.", :green) unless options['quiet']
|
141
|
+
end
|
142
|
+
|
143
|
+
desc "remove FILE", "Remove um arquivo do tema (apenas se o tema nao estiver publicado)"
|
144
|
+
method_option :quiet, :type => :boolean, :default => false
|
145
|
+
def remove(*keys)
|
146
|
+
keys.each do |key|
|
147
|
+
delete_asset(key, options['quiet'])
|
148
|
+
end
|
149
|
+
say("Done.", :green) unless options['quiet']
|
150
|
+
end
|
151
|
+
|
152
|
+
desc "watch", "Baixa e sobe um arquivo sempre que ele for salvo"
|
153
|
+
method_option :quiet, :type => :boolean, :default => false
|
154
|
+
method_option :keep_files, :type => :boolean, :default => false
|
155
|
+
def watch
|
156
|
+
watcher do |filename, event|
|
157
|
+
filename = filename.gsub("#{Dir.pwd}/", '')
|
158
|
+
unless local_assets_list.include?(filename)
|
159
|
+
say("Unknown file [#{filename}]", :red)
|
160
|
+
next
|
161
|
+
end
|
162
|
+
action = if [:changed, :new].include?(event)
|
163
|
+
:send_asset
|
164
|
+
elsif event == :delete
|
165
|
+
:delete_asset
|
166
|
+
else
|
167
|
+
raise NotImplementedError, "Unknown event -- #{event} -- #{filename}"
|
168
|
+
end
|
169
|
+
send(action, filename, options['quiet'])
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
desc "systeminfo", "Mostra informacoes do sistema"
|
174
|
+
def systeminfo
|
175
|
+
ruby_version = "#{RUBY_VERSION}"
|
176
|
+
ruby_version += "-p#{RUBY_PATCHLEVEL}" if RUBY_PATCHLEVEL
|
177
|
+
puts "Ruby: v#{ruby_version}"
|
178
|
+
puts "Operating System: #{RUBY_PLATFORM}"
|
179
|
+
%w(Listen HTTParty Launchy).each do |lib|
|
180
|
+
require "#{lib.downcase}/version"
|
181
|
+
puts "#{lib}: v" + Kernel.const_get("#{lib}::VERSION")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
protected
|
187
|
+
|
188
|
+
def config
|
189
|
+
@config ||= YAML.load_file 'config.yml'
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
|
194
|
+
def notify_and_sleep(message)
|
195
|
+
say(message, :red)
|
196
|
+
OpencodeTheme.sleep
|
197
|
+
end
|
198
|
+
|
199
|
+
def binary_file?(path)
|
200
|
+
!MimeMagic.by_path(path).text?
|
201
|
+
end
|
202
|
+
|
203
|
+
def opencode_theme_url
|
204
|
+
config[:preview_url]
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
def send_asset(asset, quiet = false)
|
209
|
+
if valid_name?(asset)
|
210
|
+
return unless valid?(asset)
|
211
|
+
data = { key: "/#{asset}" }
|
212
|
+
content = File.read("#{asset}")
|
213
|
+
if binary_file?(asset) || OpencodeTheme.is_binary_data?(content)
|
214
|
+
content = File.open("#{asset}", "rb") { |io| io.read }
|
215
|
+
data.merge!(attachment: Base64.encode64(content))
|
216
|
+
else
|
217
|
+
data.merge!(value: Base64.encode64(content))
|
218
|
+
end
|
219
|
+
response = show_during("[#{timestamp}] Uploading: #{asset}", quiet) do
|
220
|
+
OpencodeTheme.send_asset(data)
|
221
|
+
end
|
222
|
+
if response.success?
|
223
|
+
say("[#{timestamp}] Uploaded: #{asset}", :green) unless quiet
|
224
|
+
else
|
225
|
+
report_error(Time.now, "Could not upload #{asset}", response)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def delete_asset(key, quiet=false)
|
231
|
+
return unless valid?(key)
|
232
|
+
response = show_during("[#{timestamp}] Removing: #{key}", quiet) do
|
233
|
+
OpencodeTheme.delete_asset(key)
|
234
|
+
end
|
235
|
+
if response.success?
|
236
|
+
say("[#{timestamp}] Removed: #{key}", :green) unless quiet
|
237
|
+
else
|
238
|
+
report_error(Time.now, "Could not remove #{key}", response)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def watcher
|
243
|
+
FileWatcher.new(Dir.pwd).watch() do |filename, event|
|
244
|
+
yield("#{filename}", event)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def local_assets_list
|
249
|
+
local_files.reject do |p|
|
250
|
+
@permitted_files ||= (DEFAULT_WHITELIST | OpencodeTheme.whitelist_files).map{|pattern| Regexp.new(pattern)}
|
251
|
+
@permitted_files.none? { |regex| regex =~ p } || OpencodeTheme.ignore_files.any? { |regex| regex =~ p }
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def local_files
|
256
|
+
Dir.glob(File.join('**', '*')).reject do |f|
|
257
|
+
File.directory?(f)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def valid?(key)
|
262
|
+
return true
|
263
|
+
#return true if DEFAULT_WHITELIST.include?(key.split('/').first + "/")
|
264
|
+
# say("'#{key}' is not in a valid file for theme uploads", :yellow)
|
265
|
+
# say("Files need to be in one of the following subdirectories: #{DEFAULT_WHITELIST.join(' ')}", :yellow)
|
266
|
+
# false
|
267
|
+
end
|
268
|
+
|
269
|
+
def timestamp(time = Time.now)
|
270
|
+
time.strftime(TIMEFORMAT)
|
271
|
+
end
|
272
|
+
|
273
|
+
def valid_name?(key)
|
274
|
+
name = key.split("/").last
|
275
|
+
if name =~ /^[0-9a-zA-Z\-_.]+\.(ttf|eot|svg|woff|css|scss|html|js|jpg|gif|png|json|TTF|EOT|SVG|WOFF|CSS|SCSS|HTML|JS|PNG|GIF|JPG|JSON)$/
|
276
|
+
valid = true
|
277
|
+
else
|
278
|
+
report_error(Time.now, "INVALID NAME #{name}", key)
|
279
|
+
end
|
280
|
+
valid
|
281
|
+
end
|
282
|
+
|
283
|
+
def download_asset(key)
|
284
|
+
if valid_name?(key)
|
285
|
+
return unless valid?(key)
|
286
|
+
notify_and_sleep("Approaching limit of API permits. Naptime until more permits become available!") if OpencodeTheme.needs_sleep?
|
287
|
+
asset = OpencodeTheme.get_asset(URI.encode(key))
|
288
|
+
unless asset['key']
|
289
|
+
report_error(Time.now, "Could not download #{key}", asset)
|
290
|
+
return
|
291
|
+
end
|
292
|
+
if asset['content']
|
293
|
+
content = Base64.decode64(asset['content'])
|
294
|
+
content = content.force_encoding("UTF-8")
|
295
|
+
format = "w+b:ISO-8859-1"
|
296
|
+
elsif asset['attachment']
|
297
|
+
content = Base64.decode64(asset['attachment'])
|
298
|
+
format = "w+b"
|
299
|
+
end
|
300
|
+
FileUtils.mkdir_p(File.dirname(URI.decode(key)))
|
301
|
+
File.open(key, format) {|f| f.write content} if content
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def show_during(message = '', quiet = false, &block)
|
306
|
+
print(message) unless quiet
|
307
|
+
result = yield
|
308
|
+
print("\r#{' ' * message.length}\r") unless quiet
|
309
|
+
result
|
310
|
+
end
|
311
|
+
|
312
|
+
def report_error(time, message, response)
|
313
|
+
say("[#{timestamp(time)}] Error: #{message}", :red)
|
314
|
+
say("Error Details: #{response}", :yellow)
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|
318
|
+
|
319
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'opencode_theme/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "opencode_theme"
|
8
|
+
spec.version = OpencodeTheme::VERSION
|
9
|
+
spec.authors = ["Rafael Takashi Tanaka"]
|
10
|
+
spec.email = ["rtanaka@tray.net.br"]
|
11
|
+
spec.description = %q{Command Line tool for developing themes in Tray E-commerce}
|
12
|
+
spec.summary = %q{Provides simple commands to upload and donwload files from a themes}
|
13
|
+
spec.homepage = "http://tray-tecnologia.github.io/theme-template/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.add_dependency('thor', '>= 0.14.4')
|
17
|
+
spec.add_dependency('httparty', '~> 0.13.0')
|
18
|
+
spec.add_dependency('json', '~> 1.8.0')
|
19
|
+
spec.add_dependency('mimemagic')
|
20
|
+
spec.add_dependency('filewatcher')
|
21
|
+
spec.add_dependency('launchy')
|
22
|
+
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'rspec'
|
25
|
+
spec.add_development_dependency 'pry'
|
26
|
+
spec.add_development_dependency 'http_logger'
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
29
|
+
|
30
|
+
|
31
|
+
spec.files = `git ls-files`.split("\n")
|
32
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
33
|
+
spec.executables << 'opencode'
|
34
|
+
spec.require_paths = ['lib']
|
35
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe OpencodeTheme::Cli, :functional do
|
4
|
+
|
5
|
+
STORE_ID = '430692'
|
6
|
+
FILE_NAME = 'layouts/default.html'
|
7
|
+
API_KEY = '11451c354c1f95fe60f80d7672bf184a'
|
8
|
+
PASSWORD = '14ae838d9e971465af45b35803b8f0a4'
|
9
|
+
|
10
|
+
after(:all) do
|
11
|
+
# clearing generated and downloaded files
|
12
|
+
FileUtils.rm 'config.yml'
|
13
|
+
FileUtils.rm_rf 'default'
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'Invalid or Inexistent Configuration' do
|
17
|
+
it 'does not list when the config is invalid' do
|
18
|
+
output = capture(:stdout) { subject.list }
|
19
|
+
expect(File.exists? 'config.yml').to eq false
|
20
|
+
expect(output).to include 'config.yml does not exist!'
|
21
|
+
expect(output).to include 'Error: Could not list now'
|
22
|
+
expect(output).to include 'Error Details: {"authentication"=>false}'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'does not clean cache when the config is invalid' do
|
26
|
+
output = capture(:stdout) { subject.clean }
|
27
|
+
expect(File.exists? 'config.yml').to eq false
|
28
|
+
expect(output).to include 'Clean cache [FAIL]'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'does not upload any file when the config is invalid' do
|
32
|
+
output = capture(:stdout) { subject.upload }
|
33
|
+
expect(output).not_to include 'Uploaded'
|
34
|
+
expect(output).to include 'Done.'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'Configure' do
|
39
|
+
it 'fails to create config.yml file when called with no arguments' do
|
40
|
+
output = capture(:stdout) { subject.configure }
|
41
|
+
expect(output).to include 'Configuration [FAIL]'
|
42
|
+
expect(File.exists? 'config.yml').to eq false
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'creates config.yml when called with parameters' do
|
46
|
+
output = capture(:stdout) { subject.configure API_KEY, PASSWORD }
|
47
|
+
expect(output).to include 'Configuration [OK]'
|
48
|
+
expect(File.exists? 'config.yml').to eq true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'Bootstrap' do
|
53
|
+
it 'create new theme' do
|
54
|
+
output = capture(:stdout) { subject.bootstrap API_KEY, PASSWORD }
|
55
|
+
FileUtils.cd '..'
|
56
|
+
expect(output).to include 'Configuration [OK]'
|
57
|
+
expect(output).to include 'Create default theme on store'
|
58
|
+
expect(output).to include 'Saving configuration to default'
|
59
|
+
expect(output).to include 'Downloading default assets from Opencode'
|
60
|
+
expect(output).to include "Downloaded: #{ FILE_NAME }"
|
61
|
+
expect(output).to include 'Done.'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'List' do
|
66
|
+
it 'lists all the themes from the store' do
|
67
|
+
output = capture(:stdout) { subject.list }
|
68
|
+
expect(output).to include 'Theme name:'
|
69
|
+
expect(output).to include 'Theme ID:'
|
70
|
+
expect(output).to include 'Theme status:'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'Cleaning cache' do
|
75
|
+
it 'cleans the cache' do
|
76
|
+
FileUtils.cd 'default'
|
77
|
+
output = capture(:stdout) { subject.clean }
|
78
|
+
FileUtils.cd '..'
|
79
|
+
expect(output).to include 'Clean cache [OK]'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'Download' do
|
84
|
+
it 'downloads all files' do
|
85
|
+
FileUtils.cd 'default'
|
86
|
+
output = capture(:stdout) { subject.download }
|
87
|
+
FileUtils.cd '..'
|
88
|
+
expect(output).to include 'Downloaded'
|
89
|
+
expect(output).to include "Downloaded: #{ FILE_NAME }"
|
90
|
+
expect(output).not_to include 'Error'
|
91
|
+
expect(output).to include 'Done.'
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'downloads a single file' do
|
95
|
+
FileUtils.cd 'default'
|
96
|
+
output = capture(:stdout) { subject.download FILE_NAME }
|
97
|
+
FileUtils.cd '..'
|
98
|
+
expect(output).to include "Downloaded: #{ FILE_NAME }"
|
99
|
+
expect(output).to include 'Done.'
|
100
|
+
expect(output).not_to include 'Error'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'Upload' do
|
105
|
+
it 'uploads all files' do
|
106
|
+
FileUtils.cd 'default'
|
107
|
+
output = capture(:stdout) { subject.upload }
|
108
|
+
FileUtils.cd '..'
|
109
|
+
expect(output).to include 'Uploaded'
|
110
|
+
expect(output).to include "Uploaded: #{ FILE_NAME }"
|
111
|
+
expect(output).not_to include 'Error'
|
112
|
+
expect(output).to include 'Done.'
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'uploads a single file' do
|
116
|
+
FileUtils.cd 'default'
|
117
|
+
output = capture(:stdout) { subject.upload FILE_NAME }
|
118
|
+
FileUtils.cd '..'
|
119
|
+
expect(output).to include "Uploaded: #{ FILE_NAME }"
|
120
|
+
expect(output).to include 'Done.'
|
121
|
+
expect(output).not_to include 'Error'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'System Information' do
|
126
|
+
let(:output) { capture(:stdout) { subject.systeminfo } }
|
127
|
+
|
128
|
+
it 'displays system information' do
|
129
|
+
pending 'redmine issue 37576'
|
130
|
+
expect(output).not_to be_nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'Help' do
|
135
|
+
let(:output) { capture(:stdout) { subject.help } }
|
136
|
+
|
137
|
+
it 'displays help about each command' do
|
138
|
+
expect(output).to include 'Commands:'
|
139
|
+
expect(output).to include 'bootstrap API_KEY PASSWORD THEME_NAME THEME_BASE'
|
140
|
+
expect(output).to include 'clean'
|
141
|
+
expect(output).to include 'configure API_KEY PASSWORD THEME_ID'
|
142
|
+
expect(output).to include 'download FILE'
|
143
|
+
expect(output).to include 'help [COMMAND]'
|
144
|
+
expect(output).to include 'list'
|
145
|
+
expect(output).to include 'open'
|
146
|
+
expect(output).to include 'remove FILE'
|
147
|
+
expect(output).to include 'systeminfo'
|
148
|
+
expect(output).to include 'upload FILE'
|
149
|
+
expect(output).to include 'watch'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'opencode_theme'
|
3
|
+
require 'opencode_theme/cli'
|
4
|
+
|
5
|
+
def capture(stream)
|
6
|
+
begin
|
7
|
+
stream = stream.to_s
|
8
|
+
eval "$#{stream} = StringIO.new"
|
9
|
+
yield
|
10
|
+
result = eval("$#{stream}").string
|
11
|
+
ensure
|
12
|
+
eval("$#{stream} = #{stream.upcase}")
|
13
|
+
end
|
14
|
+
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'logger'
|
19
|
+
require 'http_logger'
|
20
|
+
|
21
|
+
File.truncate('http.log', 0) if File.exists? 'http.log'
|
22
|
+
HttpLogger.logger = Logger.new 'http.log'
|
23
|
+
HttpLogger.colorize = false
|
24
|
+
HttpLogger.log_headers = true
|
25
|
+
HttpLogger.log_request_body = true
|
26
|
+
HttpLogger.log_response_body = true
|
27
|
+
HttpLogger.level = :info
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module OpencodeTheme
|
2
|
+
class CliDouble < Cli
|
3
|
+
attr_writer :local_files, :mock_config
|
4
|
+
|
5
|
+
def configure(api_key=nil, password=nil, theme_id=nil)
|
6
|
+
super(api_key, password, theme_id)
|
7
|
+
end
|
8
|
+
|
9
|
+
def list
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def clean
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def bootstrap
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def open
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def download
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def upload
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def watch
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def systeminfo
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
##########################################
|
46
|
+
|
47
|
+
no_commands do
|
48
|
+
def config
|
49
|
+
@mock_config || super
|
50
|
+
end
|
51
|
+
|
52
|
+
def opencode_theme_url
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def binary_file?(file)
|
57
|
+
super
|
58
|
+
end
|
59
|
+
|
60
|
+
def local_files
|
61
|
+
@local_files
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require_relative 'cli_double'
|
3
|
+
|
4
|
+
describe 'Cli' do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@cli = OpencodeTheme::CliDouble.new
|
8
|
+
OpencodeTheme.config = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should report binary files as binary' do
|
12
|
+
extensions = %w(png gif jpg jpeg eot ttf woff otf swf ico pdf)
|
13
|
+
extensions.each do |ext|
|
14
|
+
expect(@cli.binary_file? "hello.#{ext}").to eq(true), ext
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should not report text based files as binary' do
|
19
|
+
expect(@cli.binary_file? 'style.css').to eq false
|
20
|
+
expect(@cli.binary_file? 'application.js').to eq false
|
21
|
+
expect(@cli.binary_file? 'settings_data.json').to eq false
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opencode_theme
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rafael Takashi Tanaka
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.14.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.14.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httparty
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.13.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.13.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.8.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.8.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mimemagic
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: filewatcher
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: launchy
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: http_logger
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: bundler
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '1.3'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '1.3'
|
167
|
+
description: Command Line tool for developing themes in Tray E-commerce
|
168
|
+
email:
|
169
|
+
- rtanaka@tray.net.br
|
170
|
+
executables:
|
171
|
+
- opencode
|
172
|
+
extensions: []
|
173
|
+
extra_rdoc_files: []
|
174
|
+
files:
|
175
|
+
- ".gitignore"
|
176
|
+
- ".rspec"
|
177
|
+
- Gemfile
|
178
|
+
- LICENSE.txt
|
179
|
+
- README.md
|
180
|
+
- Rakefile
|
181
|
+
- bin/opencode
|
182
|
+
- lib/opencode_theme.rb
|
183
|
+
- lib/opencode_theme/base_service.rb
|
184
|
+
- lib/opencode_theme/cli.rb
|
185
|
+
- lib/opencode_theme/version.rb
|
186
|
+
- opencode_theme.gemspec
|
187
|
+
- spec/functional/functional_spec.rb
|
188
|
+
- spec/spec_helper.rb
|
189
|
+
- spec/unit/cli_double.rb
|
190
|
+
- spec/unit/cli_spec.rb
|
191
|
+
homepage: http://tray-tecnologia.github.io/theme-template/
|
192
|
+
licenses:
|
193
|
+
- MIT
|
194
|
+
metadata: {}
|
195
|
+
post_install_message:
|
196
|
+
rdoc_options: []
|
197
|
+
require_paths:
|
198
|
+
- lib
|
199
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
requirements: []
|
210
|
+
rubyforge_project:
|
211
|
+
rubygems_version: 2.2.5
|
212
|
+
signing_key:
|
213
|
+
specification_version: 4
|
214
|
+
summary: Provides simple commands to upload and donwload files from a themes
|
215
|
+
test_files: []
|