voog-kit 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.markdown +142 -0
- data/Rakefile +1 -0
- data/bin/kit +212 -0
- data/lib/voog/dtk/filemanager.rb +784 -0
- data/lib/voog/dtk/guard.rb +147 -0
- data/lib/voog/dtk/notifier.rb +34 -0
- data/lib/voog/dtk/version.rb +5 -0
- data/lib/voog/dtk.rb +131 -0
- data/spec/fixtures/.DS_Store +0 -0
- data/spec/fixtures/.voog +3 -0
- data/spec/fixtures/.voog2 +7 -0
- data/spec/fixtures/images/bullet.png +0 -0
- data/spec/fixtures/layout.json +12 -0
- data/spec/fixtures/layout_asset.json +15 -0
- data/spec/fixtures/layout_assets.json +7 -0
- data/spec/fixtures/layouts.json +9 -0
- data/spec/fixtures/manifest.json +17 -0
- data/spec/models/dtk/config_spec.rb +82 -0
- data/spec/models/dtk/filemanager_spec.rb +524 -0
- data/spec/spec_helper.rb +38 -0
- data/voog-kit.gemspec +34 -0
- metadata +238 -0
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/guard'
|
3
|
+
require 'guard/plugin'
|
4
|
+
|
5
|
+
module Guard
|
6
|
+
class Shell < Guard
|
7
|
+
VERSION = '0.5.2'
|
8
|
+
|
9
|
+
# Calls #run_all if the :all_on_start option is present.
|
10
|
+
def start
|
11
|
+
run_all if options[:all_on_start]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Call #run_on_change for all files which match this guard.
|
15
|
+
def run_all
|
16
|
+
run_on_modifications(Watcher.match_files(self, Dir.glob('{,**/}*{,.*}').uniq))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Print the result of the command(s), if there are results to be printed.
|
20
|
+
def run_on_modifications(res)
|
21
|
+
puts res if res
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Voog::Dtk
|
27
|
+
class ::Guard::Watchman < ::Guard::Plugin
|
28
|
+
attr_accessor :options, :filemanager
|
29
|
+
|
30
|
+
# Initializes a Guard plugin.
|
31
|
+
# Don't do any work here, especially as Guard plugins get initialized even if they are not in an active group!
|
32
|
+
#
|
33
|
+
# @param [Hash] options the custom Guard plugin options
|
34
|
+
# @option options [Array<Guard::Watcher>] watchers the Guard plugin file watchers
|
35
|
+
# @option options [Symbol] group the group this Guard plugin belongs to
|
36
|
+
# @option options [Boolean] any_return allow any object to be returned from a watcher
|
37
|
+
#
|
38
|
+
def initialize(options = {})
|
39
|
+
super
|
40
|
+
@options = options
|
41
|
+
end
|
42
|
+
|
43
|
+
# Called once when Guard starts. Please override initialize method to init stuff.
|
44
|
+
#
|
45
|
+
# @raise [:task_has_failed] when start has failed
|
46
|
+
# @return [Object] the task result
|
47
|
+
#
|
48
|
+
def start
|
49
|
+
::Guard::UI.info 'Guard::Voog is running'
|
50
|
+
# run_all
|
51
|
+
end
|
52
|
+
|
53
|
+
# Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard quits).
|
54
|
+
#
|
55
|
+
# @raise [:task_has_failed] when stop has failed
|
56
|
+
# @return [Object] the task result
|
57
|
+
#
|
58
|
+
def stop
|
59
|
+
::Guard::UI.info 'Guard::Voog stopped'
|
60
|
+
end
|
61
|
+
|
62
|
+
# Called when `reload|r|z + enter` is pressed.
|
63
|
+
# This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
|
64
|
+
#
|
65
|
+
# @raise [:task_has_failed] when reload has failed
|
66
|
+
# @return [Object] the task result
|
67
|
+
#
|
68
|
+
# def reload
|
69
|
+
# end
|
70
|
+
|
71
|
+
# Called when just `enter` is pressed
|
72
|
+
# This method should be principally used for long action like running all specs/tests/...
|
73
|
+
#
|
74
|
+
# @raise [:task_has_failed] when run_all has failed
|
75
|
+
# @return [Object] the task result
|
76
|
+
#
|
77
|
+
# def run_all
|
78
|
+
# end
|
79
|
+
|
80
|
+
# Default behaviour on file(s) changes that the Guard plugin watches.
|
81
|
+
# @param [Array<String>] paths the changes files or paths
|
82
|
+
# @raise [:task_has_failed] when run_on_change has failed
|
83
|
+
# @return [Object] the task result
|
84
|
+
#
|
85
|
+
# def run_on_changes(paths)
|
86
|
+
# end
|
87
|
+
|
88
|
+
# Called on file(s) additions that the Guard plugin watches.
|
89
|
+
#
|
90
|
+
# @param [Array<String>] paths the changes files or paths
|
91
|
+
# @raise [:task_has_failed] when run_on_additions has failed
|
92
|
+
# @return [Object] the task result
|
93
|
+
#
|
94
|
+
def run_on_additions(paths)
|
95
|
+
@filemanager.add_to_manifest paths
|
96
|
+
@filemanager.upload_files paths
|
97
|
+
rescue => e
|
98
|
+
@filemanager.notifier.newline
|
99
|
+
Voog::Dtk.handle_exception e, @filemanager.notifier
|
100
|
+
end
|
101
|
+
|
102
|
+
# Called on file(s) removals that the Guard plugin watches.
|
103
|
+
#
|
104
|
+
# @param [Array<String>] paths the changes files or paths
|
105
|
+
# @raise [:task_has_failed] when run_on_removals has failed
|
106
|
+
# @return [Object] the task result
|
107
|
+
#
|
108
|
+
def run_on_removals(paths)
|
109
|
+
@filemanager.remove_from_manifest paths
|
110
|
+
# @filemanager.delete_remote_files paths
|
111
|
+
rescue => e
|
112
|
+
@filemanager.notifier.newline
|
113
|
+
Voog::Dtk.handle_exception e, @filemanager.notifier
|
114
|
+
end
|
115
|
+
|
116
|
+
# Called on file(s) modifications that the Guard plugin watches.
|
117
|
+
#
|
118
|
+
# @param [Array<String>] paths the changes files or paths
|
119
|
+
# @raise [:task_has_failed] when run_on_modifications has failed
|
120
|
+
# @return [Object] the task result
|
121
|
+
#
|
122
|
+
def run_on_modifications(paths)
|
123
|
+
@filemanager.upload_files paths
|
124
|
+
@filemanager.notifier.newline
|
125
|
+
rescue => e
|
126
|
+
@filemanager.notifier.newline
|
127
|
+
Voog::Dtk.handle_exception e, @filemanager.notifier
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class Guuard
|
132
|
+
def initialize(filemanager)
|
133
|
+
@filemanager = filemanager
|
134
|
+
end
|
135
|
+
|
136
|
+
def run
|
137
|
+
guardfile = <<-EOF
|
138
|
+
guard 'watchman' do
|
139
|
+
watch(%r{^(layout|component|image|asset|javascript|stylesheet)s/.*})
|
140
|
+
end
|
141
|
+
EOF
|
142
|
+
|
143
|
+
::Guard.start(guardfile_contents: guardfile)
|
144
|
+
::Guard.guards('watchman').first.filemanager = @filemanager
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
|
3
|
+
module Voog::Dtk
|
4
|
+
class Notifier
|
5
|
+
def initialize(output=$stderr, silent=false)
|
6
|
+
@output = output
|
7
|
+
@silent = silent
|
8
|
+
end
|
9
|
+
|
10
|
+
def normal(message)
|
11
|
+
@output.print(message) unless @silent
|
12
|
+
end
|
13
|
+
|
14
|
+
def info(message)
|
15
|
+
@output.print(message.white + ' ') unless @silent
|
16
|
+
end
|
17
|
+
|
18
|
+
def success(message)
|
19
|
+
@output.print(message.green) unless @silent
|
20
|
+
end
|
21
|
+
|
22
|
+
def error(message)
|
23
|
+
@output.print(message.red) unless @silent
|
24
|
+
end
|
25
|
+
|
26
|
+
def warning(message)
|
27
|
+
@output.print(message.yellow) unless @silent
|
28
|
+
end
|
29
|
+
|
30
|
+
def newline
|
31
|
+
@output.print("\n") unless @silent
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/voog/dtk.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'voog/dtk/version'
|
2
|
+
require 'parseconfig'
|
3
|
+
require 'prettyprint'
|
4
|
+
|
5
|
+
module Voog
|
6
|
+
module Dtk
|
7
|
+
|
8
|
+
CONFIG_FILENAME = '.voog'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def config_exists?(filename=CONFIG_FILENAME)
|
12
|
+
filename && !filename.empty? && File.exists?(filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def global_config_exists?(filename=CONFIG_FILENAME)
|
16
|
+
filename && !filename.empty? && File.exists?([ENV['HOME'], filename].join('/'))
|
17
|
+
end
|
18
|
+
|
19
|
+
def read_config(block = nil, file = CONFIG_FILENAME)
|
20
|
+
config = {
|
21
|
+
:host => nil,
|
22
|
+
:api_token => nil
|
23
|
+
}
|
24
|
+
local_config = config_exists?(file) ? ParseConfig.new(File.expand_path(file)).params : {}
|
25
|
+
global_config = global_config_exists?(file) ? ParseConfig.new(File.expand_path([ENV['HOME'], file].join('/'))).params : {}
|
26
|
+
|
27
|
+
options = global_config.merge(local_config)
|
28
|
+
|
29
|
+
unless options.empty?
|
30
|
+
@block = if block.nil?
|
31
|
+
options.keys.first
|
32
|
+
else
|
33
|
+
if options.key?(block)
|
34
|
+
block
|
35
|
+
else
|
36
|
+
fail "Site '#{block}' not found in the configuration file!".red
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
config[:host] = options[@block].fetch("host")
|
41
|
+
config[:api_token] = options[@block].fetch("api_token")
|
42
|
+
end
|
43
|
+
config
|
44
|
+
end
|
45
|
+
|
46
|
+
def write_config(host, api_token, block, silent=false)
|
47
|
+
@file = if config_exists?
|
48
|
+
CONFIG_FILENAME
|
49
|
+
elsif global_config_exists?
|
50
|
+
[ENV['HOME'], CONFIG_FILENAME].join('/')
|
51
|
+
else
|
52
|
+
File.new(CONFIG_FILENAME)
|
53
|
+
CONFIG_FILENAME
|
54
|
+
end
|
55
|
+
|
56
|
+
options = ParseConfig.new(File.expand_path(@file))
|
57
|
+
|
58
|
+
if options.params.key?(block)
|
59
|
+
puts "Writing new configuration options to existing config block.".white unless silent
|
60
|
+
options.params[block]['host'] = host unless host.empty?
|
61
|
+
options.params[block]['api_token'] = api_token unless api_token.empty?
|
62
|
+
else
|
63
|
+
puts "Writing configuration options to new config block.".white unless silent
|
64
|
+
options.params[block] = {
|
65
|
+
'host' => host,
|
66
|
+
'api_token' => api_token
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
File.open(@file, 'w+') do |file|
|
71
|
+
file.truncate(0)
|
72
|
+
file << "\n"
|
73
|
+
options.params.each do |param|
|
74
|
+
file << "[#{param[0]}]\n"
|
75
|
+
param[1].keys.each do |key|
|
76
|
+
file << " #{key}=#{param[1][key]}\n"
|
77
|
+
end
|
78
|
+
file << "\n"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def is_api_error?(exception)
|
84
|
+
[
|
85
|
+
Faraday::ClientError,
|
86
|
+
Faraday::ConnectionFailed,
|
87
|
+
Faraday::ParsingError,
|
88
|
+
Faraday::TimeoutError,
|
89
|
+
Faraday::ResourceNotFound
|
90
|
+
].include? exception.class
|
91
|
+
end
|
92
|
+
|
93
|
+
def print_debug_info(exception)
|
94
|
+
puts
|
95
|
+
puts "Exception: #{exception.class}"
|
96
|
+
if is_api_error?(exception) && exception.respond_to?(:response) && exception.response
|
97
|
+
pp exception.response
|
98
|
+
end
|
99
|
+
puts exception.backtrace
|
100
|
+
end
|
101
|
+
|
102
|
+
def handle_exception(exception, debug, notifier=nil)
|
103
|
+
error_msg = if is_api_error?(exception)
|
104
|
+
if exception.respond_to?(:response) && exception.response
|
105
|
+
if exception.response.fetch(:headers, {}).fetch(:content_type, '') =~ /application\/json/
|
106
|
+
body = JSON.parse(exception.response.fetch(:body))
|
107
|
+
"#{body.fetch('message', '')} #{("Errors: " + body.fetch('errors', '').inspect) if body.fetch('errors', nil)}".red
|
108
|
+
else
|
109
|
+
exception.response.fetch(:body)
|
110
|
+
end + "(error code #{exception.response[:status]})".red
|
111
|
+
else
|
112
|
+
"#{exception}"
|
113
|
+
end
|
114
|
+
else
|
115
|
+
"#{exception}"
|
116
|
+
end
|
117
|
+
|
118
|
+
if notifier
|
119
|
+
notifier.newline
|
120
|
+
notifier.error error_msg
|
121
|
+
notifier.newline
|
122
|
+
else
|
123
|
+
puts error_msg
|
124
|
+
end
|
125
|
+
print_debug_info(exception) if debug
|
126
|
+
rescue => e
|
127
|
+
handle_exception e, debug, notifier
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
Binary file
|
data/spec/fixtures/.voog
ADDED
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"id": 14,
|
3
|
+
"parent_id": null,
|
4
|
+
"title": "Test",
|
5
|
+
"layout_name": "component",
|
6
|
+
"content_type": "component",
|
7
|
+
"component": true,
|
8
|
+
"url": "http://voog.local/admin/api/layouts/14",
|
9
|
+
"created_at": "2010-09-09 14:24:43 UTC",
|
10
|
+
"updated_at": "2010-09-14 14:49:51 UTC",
|
11
|
+
"body": "test body"
|
12
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"id": 22,
|
3
|
+
"filename": "test.css",
|
4
|
+
"asset_type": "stylesheet",
|
5
|
+
"content_type": "text/css",
|
6
|
+
"size": 180,
|
7
|
+
"width": null,
|
8
|
+
"height": null,
|
9
|
+
"editable": true,
|
10
|
+
"url": "http://voog.local/admin/api/layout_assets/22",
|
11
|
+
"public_url": "http://localhost/stylesheets/test.css",
|
12
|
+
"created_at": "2010-09-09 15:03:06 UTC",
|
13
|
+
"updated_at": "2010-09-16 14:19:28 UTC",
|
14
|
+
"data": "test data"
|
15
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"layouts": [
|
3
|
+
{
|
4
|
+
"component": true,
|
5
|
+
"content_type": "component",
|
6
|
+
"file": "test_component.tpl",
|
7
|
+
"layout_name": "test_component",
|
8
|
+
"title": "test_component"
|
9
|
+
}
|
10
|
+
],
|
11
|
+
"assets": [{
|
12
|
+
"content_type": "application/javascript",
|
13
|
+
"kind": "javascripts",
|
14
|
+
"file": "javascripts/test.js",
|
15
|
+
"filename": "test.js"
|
16
|
+
}]
|
17
|
+
}
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Voog::Dtk do
|
4
|
+
|
5
|
+
describe '.read_config' do
|
6
|
+
|
7
|
+
context 'when a config file is provided' do
|
8
|
+
|
9
|
+
let(:config) { Voog::Dtk.read_config nil, 'spec/fixtures/.voog' }
|
10
|
+
|
11
|
+
it 'api_token should be exactly as configured' do
|
12
|
+
expect(config[:api_token]).to eq('afcf30182aecfc8155d390d7d4552d14')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'host should be exactly as configured' do
|
16
|
+
expect(config[:host]).to eq('voog.local')
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when there are multiple blocks' do
|
20
|
+
let(:block1) { Voog::Dtk.read_config nil, 'spec/fixtures/.voog2' }
|
21
|
+
let(:block2) { Voog::Dtk.read_config 'testblock', 'spec/fixtures/.voog2' }
|
22
|
+
|
23
|
+
it 'should default to the first one if block is not provided' do
|
24
|
+
expect(block1[:host]).to eq('voog.local')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should read the correct options when a block is provided' do
|
28
|
+
expect(block2[:api_token]).to eq('123')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should fail when a non-existant block is provided' do
|
32
|
+
expect{
|
33
|
+
block3 = Voog::Dtk.read_config 'wrongname', 'spec/fixtures/.voog2'
|
34
|
+
}.to raise_error
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when the provided filename is empty' do
|
41
|
+
|
42
|
+
let(:config) { Voog::Dtk.read_config nil, '' }
|
43
|
+
|
44
|
+
it 'api_token should be nil' do
|
45
|
+
expect(config[:api_token]).to eq(nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'host should be nil' do
|
49
|
+
expect(config[:host]).to eq(nil)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when a filename is not provided' do
|
55
|
+
|
56
|
+
let(:config) { Voog::Dtk.read_config nil, nil }
|
57
|
+
|
58
|
+
it 'api_token should be nil' do
|
59
|
+
expect(config[:api_token]).to eq(nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'host should be nil' do
|
63
|
+
expect(config[:host]).to eq(nil)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when the provided filename is invalid' do
|
69
|
+
|
70
|
+
let(:config) { Voog::Dtk.read_config nil, 'foo.bar' }
|
71
|
+
|
72
|
+
it 'api_token should be nil' do
|
73
|
+
expect(config[:api_token]).to eq(nil)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'host should be nil' do
|
77
|
+
expect(config[:host]).to eq(nil)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|