stove 2.0.0 → 3.0.0
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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +6 -1
- data/CHANGELOG.md +20 -0
- data/README.md +34 -80
- data/Rakefile +9 -1
- data/bin/bake +2 -0
- data/bin/stove +4 -0
- data/features/plugins/community.feature +11 -26
- data/features/plugins/git.feature +17 -6
- data/features/step_definitions/community_steps.rb +3 -1
- data/features/step_definitions/config_steps.rb +4 -21
- data/features/step_definitions/git_steps.rb +38 -1
- data/features/support/env.rb +17 -11
- data/features/support/stove/git.rb +28 -8
- data/lib/stove/cli.rb +72 -53
- data/lib/stove/community.rb +16 -67
- data/lib/stove/config.rb +55 -46
- data/lib/stove/cookbook/metadata.rb +3 -5
- data/lib/stove/cookbook.rb +2 -41
- data/lib/stove/error.rb +37 -8
- data/lib/stove/filter.rb +2 -1
- data/lib/stove/mixins/instanceable.rb +3 -2
- data/lib/stove/mixins/validatable.rb +5 -1
- data/lib/stove/packager.rb +11 -3
- data/lib/stove/plugins/base.rb +26 -13
- data/lib/stove/plugins/community.rb +3 -7
- data/lib/stove/plugins/git.rb +27 -30
- data/lib/stove/rake_task.rb +3 -63
- data/lib/stove/runner.rb +16 -65
- data/lib/stove/validator.rb +7 -6
- data/lib/stove/version.rb +1 -1
- data/lib/stove.rb +3 -21
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/error_spec.rb +148 -0
- data/stove.gemspec +10 -14
- data/templates/errors/abstract_method.erb +5 -0
- data/templates/errors/community_category_validation_failed.erb +5 -0
- data/templates/errors/community_key_validation_failed.erb +3 -0
- data/templates/errors/community_username_validation_failed.erb +3 -0
- data/templates/errors/git_clean_validation_failed.erb +1 -0
- data/templates/errors/git_failed.erb +5 -0
- data/templates/errors/git_repository_validation_failed.erb +3 -0
- data/templates/errors/git_up_to_date_validation_failed.erb +7 -0
- data/templates/errors/metadata_not_found.erb +1 -0
- data/templates/errors/server_unavailable.erb +1 -0
- data/templates/errors/stove_error.erb +1 -0
- metadata +32 -114
- data/features/actions/bump.feature +0 -22
- data/features/actions/changelog.feature +0 -52
- data/features/actions/dev.feature +0 -18
- data/features/actions/upload.feature +0 -26
- data/features/rake.feature +0 -15
- data/features/step_definitions/cli_steps.rb +0 -3
- data/lib/stove/actions/base.rb +0 -21
- data/lib/stove/actions/bump.rb +0 -25
- data/lib/stove/actions/changelog.rb +0 -71
- data/lib/stove/actions/dev.rb +0 -22
- data/lib/stove/actions/finish.rb +0 -8
- data/lib/stove/actions/start.rb +0 -7
- data/lib/stove/actions/upload.rb +0 -11
- data/lib/stove/jira.rb +0 -88
- data/lib/stove/middlewares/chef_authentication.rb +0 -60
- data/lib/stove/middlewares/exceptions.rb +0 -17
- data/lib/stove/mixins/filterable.rb +0 -11
- data/lib/stove/plugins/github.rb +0 -107
- data/lib/stove/plugins/jira.rb +0 -72
- data/locales/en.yml +0 -230
data/lib/stove/cli.rb
CHANGED
@@ -15,6 +15,29 @@ module Stove
|
|
15
15
|
# Parse the options hash
|
16
16
|
option_parser.parse!(@argv)
|
17
17
|
|
18
|
+
# Stupid special use cases
|
19
|
+
if @argv.first == 'login'
|
20
|
+
if options[:username].nil? || options[:username].to_s.strip.empty?
|
21
|
+
raise "Missing argument `--username'!"
|
22
|
+
end
|
23
|
+
|
24
|
+
if options[:key].nil? || options[:key].to_s.strip.empty?
|
25
|
+
raise "Missing argument `--key'!"
|
26
|
+
end
|
27
|
+
|
28
|
+
Config.username = options[:username]
|
29
|
+
Config.key = options[:key]
|
30
|
+
Config.save
|
31
|
+
|
32
|
+
@stdout.puts "Successfully saved config to `#{Config.__path__}'!"
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
36
|
+
# Override configs
|
37
|
+
Config.endpoint = options[:endpoint] if options[:endpoint]
|
38
|
+
Config.username = options[:username] if options[:username]
|
39
|
+
Config.key = options[:key] if options[:key]
|
40
|
+
|
18
41
|
# Set the log level
|
19
42
|
Stove.log_level = options[:log_level]
|
20
43
|
|
@@ -26,12 +49,6 @@ module Stove
|
|
26
49
|
log.info("Options: #{options.inspect}")
|
27
50
|
log.info("ARGV: #{@argv.inspect}")
|
28
51
|
|
29
|
-
# Unless the user specified --no-bump, version is a required argument, so
|
30
|
-
# blow up if we don't get it or if it's not a nice version string
|
31
|
-
if options[:bump]
|
32
|
-
raise OptionParser::MissingArgument.new(:version) unless options[:version]
|
33
|
-
end
|
34
|
-
|
35
52
|
# Make a new cookbook object - this will raise an exception if there is
|
36
53
|
# no cookbook at the given path
|
37
54
|
cookbook = Cookbook.new(options[:path])
|
@@ -42,7 +59,8 @@ module Stove
|
|
42
59
|
end
|
43
60
|
|
44
61
|
# Now execute the actual runners (validations and errors might occur)
|
45
|
-
Runner.
|
62
|
+
runner = Runner.new(cookbook, options)
|
63
|
+
runner.run
|
46
64
|
|
47
65
|
# If we got this far, everything was successful :)
|
48
66
|
@kernel.exit(0)
|
@@ -66,55 +84,60 @@ module Stove
|
|
66
84
|
#
|
67
85
|
def option_parser
|
68
86
|
@option_parser ||= OptionParser.new do |opts|
|
69
|
-
opts.banner = 'Usage:
|
87
|
+
opts.banner = 'Usage: stove [OPTIONS]'
|
70
88
|
|
71
89
|
opts.separator ''
|
72
|
-
opts.separator '
|
90
|
+
opts.separator 'Plugins:'
|
73
91
|
|
74
|
-
|
75
|
-
|
76
|
-
opts.on("--[no-]#{action.id}", action.description) do |v|
|
77
|
-
options[action.id.to_sym] = v
|
78
|
-
end
|
92
|
+
opts.on('--no-git', 'Do not use the git plugin') do
|
93
|
+
options[:no_git] = true
|
79
94
|
end
|
80
95
|
|
81
96
|
opts.separator ''
|
82
|
-
opts.separator '
|
97
|
+
opts.separator 'Upload Options:'
|
83
98
|
|
84
|
-
|
85
|
-
|
86
|
-
opts.on("--[no-]#{plugin.id}", plugin.description) do |v|
|
87
|
-
options[plugin.id.to_sym] = v
|
88
|
-
end
|
99
|
+
opts.on('--endpoint [URL]', 'Upload URL endpoint') do |v|
|
100
|
+
options[:endpoint] = v
|
89
101
|
end
|
90
102
|
|
91
|
-
opts.
|
92
|
-
|
93
|
-
|
94
|
-
opts.on('--locale [LANGUAGE]', 'Change the language to output messages') do |locale|
|
95
|
-
I18n.locale = locale
|
103
|
+
opts.on('--username [USERNAME]', 'Username to authenticate with') do |v|
|
104
|
+
options[:username] = v
|
96
105
|
end
|
97
106
|
|
98
|
-
opts.on('--
|
99
|
-
options[:
|
107
|
+
opts.on('--key [PATH]', 'Path to the private key on disk') do |v|
|
108
|
+
options[:key] = v
|
100
109
|
end
|
101
110
|
|
102
|
-
opts.on('--category [CATEGORY]', '
|
111
|
+
opts.on('--category [CATEGORY]', 'Category for the cookbook') do |v|
|
103
112
|
options[:category] = v
|
104
113
|
end
|
105
114
|
|
106
|
-
opts.
|
107
|
-
|
108
|
-
end
|
115
|
+
opts.separator ''
|
116
|
+
opts.separator 'Git Options:'
|
109
117
|
|
110
|
-
opts.on('--remote [REMOTE]', '
|
118
|
+
opts.on('--remote [REMOTE]', 'Name of the git remote') do |v|
|
111
119
|
options[:remote] = v
|
112
120
|
end
|
113
121
|
|
114
|
-
opts.on('--branch [BRANCH]', '
|
122
|
+
opts.on('--branch [BRANCH]', 'Name of the git branch') do |v|
|
115
123
|
options[:branch] = v
|
116
124
|
end
|
117
125
|
|
126
|
+
opts.on('--sign', 'Sign git tags') do
|
127
|
+
options[:sign] = true
|
128
|
+
end
|
129
|
+
|
130
|
+
opts.separator ''
|
131
|
+
opts.separator 'Global Options:'
|
132
|
+
|
133
|
+
opts.on('--log-level [LEVEL]', 'Set the log verbosity') do |v|
|
134
|
+
options[:log_level] = v
|
135
|
+
end
|
136
|
+
|
137
|
+
opts.on('--path [PATH]', 'Change the path to a cookbook') do |v|
|
138
|
+
options[:path] = v
|
139
|
+
end
|
140
|
+
|
118
141
|
opts.on_tail('-h', '--help', 'Show this message') do
|
119
142
|
puts opts
|
120
143
|
exit
|
@@ -132,26 +155,22 @@ module Stove
|
|
132
155
|
#
|
133
156
|
# @return [Hash]
|
134
157
|
def options
|
135
|
-
@options ||=
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
!!(ENV['CLI_DEFAULT'] =~ /^(true|t|yes|y|1)$/i)
|
152
|
-
else
|
153
|
-
true
|
154
|
-
end
|
158
|
+
@options ||= {
|
159
|
+
# Upload options
|
160
|
+
:endpoint => nil,
|
161
|
+
:username => Config.username,
|
162
|
+
:key => Config.key,
|
163
|
+
:category => nil,
|
164
|
+
|
165
|
+
# Git options
|
166
|
+
:remote => 'origin',
|
167
|
+
:branch => 'master',
|
168
|
+
:sign => false,
|
169
|
+
|
170
|
+
# Global options
|
171
|
+
:log_level => :warn,
|
172
|
+
:path => Dir.pwd,
|
173
|
+
}
|
155
174
|
end
|
156
175
|
end
|
157
176
|
end
|
data/lib/stove/community.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
require '
|
2
|
-
require 'faraday_middleware'
|
1
|
+
require 'chef-api'
|
3
2
|
|
4
3
|
module Stove
|
5
4
|
class Community
|
6
5
|
include Mixin::Instanceable
|
7
6
|
include Mixin::Optionable
|
8
|
-
include Logify
|
9
7
|
|
10
|
-
|
11
|
-
|
8
|
+
#
|
9
|
+
# The default endpoint where the community site lives.
|
10
|
+
#
|
11
|
+
# @return [String]
|
12
|
+
#
|
13
|
+
DEFAULT_ENDPOINT = 'https://supermarket.getchef.com/api/v1'
|
12
14
|
|
13
15
|
#
|
14
16
|
# Get and cache a community cookbook's JSON response from the given name
|
@@ -36,9 +38,9 @@ module Stove
|
|
36
38
|
#
|
37
39
|
def cookbook(name, version = nil)
|
38
40
|
if version.nil?
|
39
|
-
connection.get("cookbooks/#{name}")
|
41
|
+
connection.get("cookbooks/#{name}")
|
40
42
|
else
|
41
|
-
connection.get("cookbooks/#{name}/versions/#{Util.version_for_url(version)}")
|
43
|
+
connection.get("cookbooks/#{name}/versions/#{Util.version_for_url(version)}")
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
@@ -50,75 +52,22 @@ module Stove
|
|
50
52
|
#
|
51
53
|
def upload(cookbook)
|
52
54
|
connection.post('cookbooks', {
|
53
|
-
tarball
|
54
|
-
cookbook
|
55
|
+
'tarball' => File.open(cookbook.tarball, 'rb'),
|
56
|
+
'cookbook' => { 'category' => cookbook.category }.to_json,
|
55
57
|
})
|
56
58
|
end
|
57
59
|
|
58
60
|
private
|
59
61
|
|
60
62
|
#
|
61
|
-
# The
|
63
|
+
# The ChefAPI connection object with lots of pretty middleware.
|
62
64
|
#
|
63
65
|
def connection
|
64
|
-
@connection ||=
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# Encode request bodies as JSON
|
70
|
-
builder.request :json
|
71
|
-
|
72
|
-
# Add Mixlib authentication headers
|
73
|
-
builder.use Stove::Middleware::ChefAuthentication, client, key
|
74
|
-
|
75
|
-
# Handle any common errors
|
76
|
-
builder.use Stove::Middleware::Exceptions
|
77
|
-
|
78
|
-
# Decode responses as JSON if the Content-Type is json
|
79
|
-
builder.response :json
|
80
|
-
builder.response :json_fix
|
81
|
-
|
82
|
-
# Allow up to 3 redirects
|
83
|
-
builder.response :follow_redirects, limit: 3
|
84
|
-
|
85
|
-
# Log all requests and responses (useful for development)
|
86
|
-
builder.response :logger, log
|
87
|
-
|
88
|
-
# Raise errors on 40x and 50x responses
|
89
|
-
builder.response :raise_error
|
90
|
-
|
91
|
-
# Use the default adapter (Net::HTTP)
|
92
|
-
builder.adapter :net_http
|
93
|
-
|
94
|
-
# Set the User-Agent header for logging purposes
|
95
|
-
builder.headers[:user_agent] = Stove::USER_AGENT
|
96
|
-
|
97
|
-
# Set some options, such as timeouts
|
98
|
-
builder.options[:timeout] = 30
|
99
|
-
builder.options[:open_timeout] = 30
|
66
|
+
@connection ||= ChefAPI::Connection.new do |conn|
|
67
|
+
conn.endpoint = ENV['STOVE_ENDPOINT'] || Config.endpoint || DEFAULT_ENDPOINT
|
68
|
+
conn.client = ENV['STOVE_USERNAME'] || Config.username
|
69
|
+
conn.key = ENV['STOVE_KEY'] || Config.key
|
100
70
|
end
|
101
71
|
end
|
102
|
-
|
103
|
-
#
|
104
|
-
# The name of the client to use (by default, this is the username).
|
105
|
-
#
|
106
|
-
# @return [String]
|
107
|
-
#
|
108
|
-
def client
|
109
|
-
Config[:community][:username]
|
110
|
-
end
|
111
|
-
|
112
|
-
#
|
113
|
-
# The path to the key on disk for authentication with the community site.
|
114
|
-
# If a relative path is given, it is expanded relative to the configuration
|
115
|
-
# file on disk.
|
116
|
-
#
|
117
|
-
# @return [String]
|
118
|
-
# the path to the key on disk
|
119
|
-
#
|
120
|
-
def key
|
121
|
-
File.expand_path(Config[:community][:key], Config.__path__)
|
122
|
-
end
|
123
72
|
end
|
124
73
|
end
|
data/lib/stove/config.rb
CHANGED
@@ -1,67 +1,76 @@
|
|
1
|
+
require 'fileutils'
|
1
2
|
require 'json'
|
2
3
|
|
3
4
|
module Stove
|
4
5
|
class Config
|
5
|
-
include Mixin::Instanceable
|
6
6
|
include Logify
|
7
|
+
include Mixin::Instanceable
|
8
|
+
|
9
|
+
def method_missing(m, *args, &block)
|
10
|
+
if m.to_s.end_with?('=')
|
11
|
+
__set__(m.to_s.chomp('='), args.first)
|
12
|
+
else
|
13
|
+
__get__(m)
|
14
|
+
end
|
15
|
+
end
|
7
16
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# hash as the data structure.
|
12
|
-
#
|
13
|
-
def initialize
|
14
|
-
log.debug("Reading from config at `#{__path__}'")
|
17
|
+
def respond_to_missing?(m, include_private = false)
|
18
|
+
__has__?(m) || super
|
19
|
+
end
|
15
20
|
|
16
|
-
|
17
|
-
|
21
|
+
def save
|
22
|
+
FileUtils.mkdir_p(File.dirname(__path__))
|
23
|
+
File.open(__path__, 'w') do |f|
|
24
|
+
f.write(JSON.fast_generate(__raw__))
|
25
|
+
end
|
26
|
+
end
|
18
27
|
|
19
|
-
|
28
|
+
def to_s
|
29
|
+
"#<#{self.class.name} #{__raw__.to_s}>"
|
30
|
+
end
|
20
31
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
No Stove configuration file found at `#{__path__}'. Stove will assume an
|
25
|
-
empty configuration, which may cause problems with some plugins. It is
|
26
|
-
recommended that you create a Stove configuration file as documented:
|
32
|
+
def inspect
|
33
|
+
"#<#{self.class.name} #{__raw__.inspect}>"
|
34
|
+
end
|
27
35
|
|
28
|
-
|
29
|
-
|
36
|
+
def __get__(key)
|
37
|
+
__raw__[key.to_sym]
|
38
|
+
end
|
30
39
|
|
31
|
-
|
40
|
+
def __has__?(key)
|
41
|
+
__raw__.key?(key.to_sym)
|
42
|
+
end
|
43
|
+
|
44
|
+
def __set__(key, value)
|
45
|
+
__raw__[key.to_sym] = value
|
46
|
+
end
|
47
|
+
|
48
|
+
def __unset__(key)
|
49
|
+
__raw__.delete(key.to_sym)
|
32
50
|
end
|
33
51
|
|
34
|
-
#
|
35
|
-
# This is a special key that tells me where stove lives. If you actually
|
36
|
-
# have a key in your config called +__path__+, then it sucks to be you.
|
37
|
-
#
|
38
|
-
# @return [String]
|
39
|
-
#
|
40
52
|
def __path__
|
41
53
|
@path ||= File.expand_path(ENV['STOVE_CONFIG'] || '~/.stove')
|
42
54
|
end
|
43
55
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
56
|
+
def __raw__
|
57
|
+
return @__raw__ if @__raw__
|
58
|
+
|
59
|
+
@__raw__ = JSON.parse(File.read(__path__), symbolize_names: true)
|
60
|
+
|
61
|
+
if @__raw__.key?(:community)
|
62
|
+
$stderr.puts "Detected old Stove configuration file, converting..."
|
63
|
+
|
64
|
+
@__raw__ = {
|
65
|
+
:username => @__raw__[:community][:username],
|
66
|
+
:key => @__raw__[:community][:key],
|
67
|
+
}
|
68
|
+
end
|
50
69
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
if value.is_a?(Hash)
|
56
|
-
[key, sanitize(value)]
|
57
|
-
else
|
58
|
-
if key =~ /access|token|password/
|
59
|
-
[key, '[FILTERED]']
|
60
|
-
else
|
61
|
-
[key, value]
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end.flatten(1)]
|
70
|
+
@__raw__
|
71
|
+
rescue Errno::ENOENT => e
|
72
|
+
log.warn { "No config file found at `#{__path__}'!" }
|
73
|
+
@__raw__ = {}
|
65
74
|
end
|
66
75
|
end
|
67
76
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'json'
|
2
|
-
require 'solve'
|
3
2
|
|
4
3
|
module Stove
|
5
4
|
class Cookbook
|
@@ -41,7 +40,7 @@ module Stove
|
|
41
40
|
class_eval <<-EOM, __FILE__, __LINE__ + 1
|
42
41
|
def #{field}(thing, *args)
|
43
42
|
version = args.first
|
44
|
-
@#{instance_variable}[thing] =
|
43
|
+
@#{instance_variable}[thing] = version.to_s
|
45
44
|
@#{instance_variable}[thing]
|
46
45
|
end
|
47
46
|
EOM
|
@@ -146,10 +145,9 @@ module Stove
|
|
146
145
|
|
147
146
|
def version(arg = UNSET_VALUE)
|
148
147
|
if arg == UNSET_VALUE
|
149
|
-
@version
|
148
|
+
@version
|
150
149
|
else
|
151
|
-
@version =
|
152
|
-
@version.to_s
|
150
|
+
@version = arg.to_s
|
153
151
|
end
|
154
152
|
end
|
155
153
|
|
data/lib/stove/cookbook.rb
CHANGED
@@ -72,20 +72,11 @@ module Stove
|
|
72
72
|
#
|
73
73
|
def category
|
74
74
|
@category ||= Community.cookbook(name)['category']
|
75
|
-
rescue
|
75
|
+
rescue ChefAPI::Error::HTTPError
|
76
76
|
log.warn("Cookbook `#{name}' not found on the Chef community site")
|
77
77
|
nil
|
78
78
|
end
|
79
79
|
|
80
|
-
#
|
81
|
-
# The URL for the cookbook on the Community Site.
|
82
|
-
#
|
83
|
-
# @return [String]
|
84
|
-
#
|
85
|
-
def url
|
86
|
-
URI.join(Community.base_url, 'cookbooks', name)
|
87
|
-
end
|
88
|
-
|
89
80
|
#
|
90
81
|
# The tag version. This is just the current version prefixed with the
|
91
82
|
# letter "v".
|
@@ -113,18 +104,10 @@ module Stove
|
|
113
104
|
def released?
|
114
105
|
Community.cookbook(name, version)
|
115
106
|
true
|
116
|
-
rescue
|
107
|
+
rescue ChefAPI::Error::HTTPNotFound
|
117
108
|
false
|
118
109
|
end
|
119
110
|
|
120
|
-
#
|
121
|
-
def release!
|
122
|
-
if options[:changelog]
|
123
|
-
log.info('Updating changelog')
|
124
|
-
update_changelog
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
111
|
#
|
129
112
|
# So there's this really really crazy bug that the tmp directory could
|
130
113
|
# be deleted mid-request...
|
@@ -140,28 +123,6 @@ module Stove
|
|
140
123
|
@tarball
|
141
124
|
end
|
142
125
|
|
143
|
-
#
|
144
|
-
# Bump the version in the metdata.rb to the specified
|
145
|
-
# parameter.
|
146
|
-
#
|
147
|
-
# @param [String] new_version
|
148
|
-
# the version to bump to
|
149
|
-
#
|
150
|
-
# @return [String]
|
151
|
-
# the new version string
|
152
|
-
#
|
153
|
-
def bump(new_version)
|
154
|
-
return true if new_version.to_s == version.to_s
|
155
|
-
|
156
|
-
metadata_path = path.join('metadata.rb')
|
157
|
-
contents = File.read(metadata_path)
|
158
|
-
|
159
|
-
contents.sub!(/^version(\s+)('|")#{version}('|")/, "version\\1\\2#{new_version}\\3")
|
160
|
-
|
161
|
-
File.open(metadata_path, 'w') { |f| f.write(contents) }
|
162
|
-
reload_metadata!
|
163
|
-
end
|
164
|
-
|
165
126
|
private
|
166
127
|
# Load the metadata and set the @metadata instance variable.
|
167
128
|
#
|
data/lib/stove/error.rb
CHANGED
@@ -1,24 +1,53 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
1
3
|
module Stove
|
2
4
|
module Error
|
5
|
+
class ErrorBinding
|
6
|
+
def initialize(options = {})
|
7
|
+
options.each do |key, value|
|
8
|
+
instance_variable_set(:"@#{key}", value)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_binding
|
13
|
+
binding
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
3
17
|
class StoveError < StandardError
|
4
18
|
def initialize(options = {})
|
5
|
-
|
19
|
+
@options = options
|
20
|
+
@filename = options.delete(:_template)
|
6
21
|
|
7
|
-
|
8
|
-
|
22
|
+
super()
|
23
|
+
end
|
9
24
|
|
10
|
-
|
25
|
+
def message
|
26
|
+
erb = ERB.new(File.read(template))
|
27
|
+
erb.result(ErrorBinding.new(@options).get_binding)
|
11
28
|
end
|
12
|
-
|
29
|
+
alias_method :to_s, :message
|
13
30
|
|
14
|
-
|
15
|
-
|
16
|
-
|
31
|
+
private
|
32
|
+
|
33
|
+
def template
|
34
|
+
class_name = self.class.to_s.split('::').last
|
35
|
+
filename = @filename || Util.underscore(class_name)
|
36
|
+
Stove.root.join('templates', 'errors', "#{filename}.erb")
|
17
37
|
end
|
18
38
|
end
|
19
39
|
|
20
40
|
class GitFailed < StoveError; end
|
21
41
|
class MetadataNotFound < StoveError; end
|
22
42
|
class ServerUnavailable < StoveError; end
|
43
|
+
|
44
|
+
# Validations
|
45
|
+
class ValidationFailed < StoveError; end
|
46
|
+
class CommunityCategoryValidationFailed < ValidationFailed; end
|
47
|
+
class CommunityKeyValidationFailed < ValidationFailed; end
|
48
|
+
class CommunityUsernameValidationFailed < ValidationFailed; end
|
49
|
+
class GitCleanValidationFailed < ValidationFailed; end
|
50
|
+
class GitRepositoryValidationFailed < ValidationFailed; end
|
51
|
+
class GitUpToDateValidationFailed < ValidationFailed; end
|
23
52
|
end
|
24
53
|
end
|
data/lib/stove/filter.rb
CHANGED
@@ -4,17 +4,18 @@ module Stove
|
|
4
4
|
module Mixin::Instanceable
|
5
5
|
def self.included(base)
|
6
6
|
base.send(:include, Singleton)
|
7
|
-
base.send(:undef_method, :inspect, :to_s)
|
8
7
|
base.send(:extend, ClassMethods)
|
9
8
|
end
|
10
9
|
|
11
10
|
def self.extended(base)
|
12
11
|
base.send(:include, Singleton)
|
13
|
-
base.send(:undef_method, :inspect, :to_s)
|
14
12
|
base.send(:extend, ClassMethods)
|
15
13
|
end
|
16
14
|
|
17
15
|
module ClassMethods
|
16
|
+
def to_s; instance.to_s; end
|
17
|
+
def inspect; instance.inspect; end
|
18
|
+
|
18
19
|
def method_missing(m, *args, &block)
|
19
20
|
instance.send(m, *args, &block)
|
20
21
|
end
|
data/lib/stove/packager.rb
CHANGED
@@ -18,7 +18,14 @@ module Stove
|
|
18
18
|
'recipes',
|
19
19
|
'resources',
|
20
20
|
'templates',
|
21
|
-
]
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
ACCEPTABLE_FILES_LIST = ACCEPTABLE_FILES.join(',').freeze
|
24
|
+
|
25
|
+
TMP_FILES = [
|
26
|
+
/^(?:.*[\\\/])?\.[^\\\/]+\.sw[p-z]$/,
|
27
|
+
/~$/,
|
28
|
+
].freeze
|
22
29
|
|
23
30
|
# The cookbook to package.
|
24
31
|
#
|
@@ -38,7 +45,8 @@ module Stove
|
|
38
45
|
# @return [Array]
|
39
46
|
# the array of file paths
|
40
47
|
def cookbook_files
|
41
|
-
|
48
|
+
path = File.expand_path("#{cookbook.path}/{#{ACCEPTABLE_FILES_LIST}}")
|
49
|
+
Dir[path].reject { |f| TMP_FILES.any? { |regex| f.match(regex) } }
|
42
50
|
end
|
43
51
|
|
44
52
|
# The path to the tar.gz package in the temporary directory.
|
@@ -51,7 +59,7 @@ module Stove
|
|
51
59
|
private
|
52
60
|
|
53
61
|
def pack!
|
54
|
-
destination = Tempfile.new(cookbook.name).path
|
62
|
+
destination = Tempfile.new([cookbook.name, '.tar.gz']).path
|
55
63
|
|
56
64
|
# Sandbox
|
57
65
|
sandbox = Dir.mktmpdir
|