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.
@@ -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
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ config.yml
19
+ *.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in opencode_theme.gemspec
4
+ gemspec
@@ -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.
@@ -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
@@ -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
@@ -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,3 @@
1
+ module OpencodeTheme
2
+ VERSION = "0.0.5"
3
+ 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
@@ -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: []