batali 0.4.10 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f4553dc89e46b84385924f5bb91aa2be8ef25f1a
4
- data.tar.gz: 2002e75fc05c7b841f3152131ca66076969a1f26
2
+ SHA256:
3
+ metadata.gz: 36c2b3a73af2cda00310d325b11c45528b6ce1e73053733bec57aecda740691d
4
+ data.tar.gz: 859df3d565d6e7d0e010a75d06e6de75db33fef921d0b60472aee9c4f9675c8c
5
5
  SHA512:
6
- metadata.gz: 6c03e18e0c2ac2854ae223245b63134c5dc742ac2b3d1e439d248bb1e1ac5dad704b422ff4d0d1c168a66532da8981ba99606f28ec38396fcefbfe86c9986d15
7
- data.tar.gz: 1ad3695558546faefb03819e2192ce5541dfc22e232c98b628fd99f58b2098a5f26286f05437d961e48da4ff780bdd314f3570d0dc75e31a60b044074dcc4c1b
6
+ metadata.gz: 82f4762ba5bac43cf341c94fd3f158be89b34b2de70a47b2bae4bbf7fc1cd8ab176a7609d6abe34e9b4d4ccf0724e3a084aaa55c4f0780fda1bdb6cd5f2b884b
7
+ data.tar.gz: 6256dc382f21a894ef7532b71e89a8f0885b5eb5b3172441f654612c88586bd67580e464506fb90d988eb1b79d4f516eae84bd6cfd250680cc6f60c5d7e5386d
@@ -1,3 +1,8 @@
1
+ # v0.5.0
2
+ * [enhancement] Use UNC style paths on Windows (#95)
3
+ * [enhancement] Use LOCALAPPDATA on Windows (#90)
4
+ * [fix] Fix metadata loading when JSON file (#86)
5
+
1
6
  # v0.4.10
2
7
  * [fix] Cookbook installation errors on windows (#82)
3
8
 
@@ -12,7 +12,7 @@ The develop branch is the current edge of development.
12
12
 
13
13
  ## Pull requests
14
14
 
15
- * https://github.com/hw-labs/batali
15
+ * https://github.com/spox/batali
16
16
 
17
17
  Please base all pull requests of the `develop` branch. Merges to
18
18
  `master` only occur through the `develop` branch. Pull requests
@@ -22,4 +22,4 @@ based on `master` will likely be cherry picked.
22
22
 
23
23
  Need to report an issue? Use the github issues:
24
24
 
25
- * https://github.com/hw-labs/batali
25
+ * https://github.com/spox/batali
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2015 Chris Roberts
1
+ Copyright 2018 Chris Roberts
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -1,9 +1,10 @@
1
+ [![Travis status](https://api.travis-ci.org/spox/batali.svg?branch=develop)](https://travis-ci.org/spox/batali) [![Appveyor status](https://ci.appveyor.com/api/projects/status/bua5vb1f2jvpuu90?svg=true)](https://ci.appveyor.com/project/chrisroberts/batali)
2
+
1
3
  ![Batali](img/batali-logo.png)
2
4
 
3
5
  # Batali
4
6
 
5
- Batali is a light weight cookbook resolver. It is now in
6
- a beta state, moving quickly towards a proper stable release.
7
+ Batali is a light weight cookbook resolver.
7
8
 
8
9
  ## What is Batali?
9
10
 
@@ -400,7 +401,7 @@ end
400
401
 
401
402
  Batali can be used with [Test Kitchen](https://github.com/test-kitchen/test-kitchen):
402
403
 
403
- * https://github.com/hw-labs/batali-tk
404
+ * https://github.com/spox/batali-tk
404
405
 
405
406
  ## ChefSpec
406
407
 
@@ -452,7 +453,7 @@ $ batali supermarket --remote-supermarket-url="http://supermarket.example.com"
452
453
 
453
454
  # Info
454
455
 
455
- * Repository: https://github.com/hw-labs/batali
456
+ * Repository: https://github.com/spox/batali
456
457
 
457
458
  [1]: https://rubygems.org/gems/librarian "A Framework for Bundlers"
458
- [2]: https://rubygems.org/gems/chef "A systems integration framework"
459
+ [2]: https://rubygems.org/gems/chef "A systems integration framework"
@@ -1,28 +1,29 @@
1
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) + '/lib/'
2
- require 'batali/version'
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) + "/lib/"
2
+ require "batali/version"
3
3
  Gem::Specification.new do |s|
4
- s.name = 'batali'
4
+ s.name = "batali"
5
5
  s.version = Batali::VERSION.version
6
- s.summary = 'Magic'
7
- s.author = 'Chris Roberts'
8
- s.email = 'code@chrisroberts.org'
9
- s.homepage = 'https://github.com/hw-labs/batali'
10
- s.description = 'Magic'
11
- s.require_path = 'lib'
12
- s.license = 'Apache 2.0'
13
- s.add_runtime_dependency 'attribute_struct', '>= 0.2.14', '< 0.5'
14
- s.add_runtime_dependency 'grimoire', '>= 0.2.14', '< 0.4'
15
- s.add_runtime_dependency 'bogo', '>= 0.1.20', '< 0.4'
16
- s.add_runtime_dependency 'bogo-cli', '>= 0.1.23', '< 0.4'
17
- s.add_runtime_dependency 'bogo-config', '>= 0.1.10', '< 0.4'
18
- s.add_runtime_dependency 'bogo-ui', '>= 0.1.6', '< 0.4'
19
- s.add_runtime_dependency 'http', '>= 0.8.2', '< 1.0.0'
20
- s.add_runtime_dependency 'git'
21
- s.add_development_dependency 'rake'
22
- s.add_development_dependency 'rubocop', '0.35.1'
23
- s.add_development_dependency 'minitest'
24
- s.add_development_dependency 'pry'
25
- s.add_development_dependency 'chef'
26
- s.executables << 'batali'
27
- s.files = Dir['{lib,bin}/**/**/*'] + %w(batali.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
6
+ s.summary = "Magic"
7
+ s.author = "Chris Roberts"
8
+ s.email = "code@chrisroberts.org"
9
+ s.homepage = "https://github.com/hw-labs/batali"
10
+ s.description = "Magic"
11
+ s.require_path = "lib"
12
+ s.license = "Apache 2.0"
13
+ s.add_runtime_dependency "attribute_struct", ">= 0.2.14", "< 0.5"
14
+ s.add_runtime_dependency "grimoire", ">= 0.2.14", "< 0.4"
15
+ s.add_runtime_dependency "bogo", ">= 0.1.20", "< 0.4"
16
+ s.add_runtime_dependency "bogo-cli", ">= 0.2.12", "< 0.4"
17
+ s.add_runtime_dependency "bogo-config", ">= 0.1.10", "< 0.4"
18
+ s.add_runtime_dependency "bogo-ui", ">= 0.1.6", "< 0.4"
19
+ s.add_runtime_dependency "http", ">= 0.8.2", "< 1.0.0"
20
+ s.add_runtime_dependency "git"
21
+ s.add_development_dependency "rake"
22
+ s.add_development_dependency "minitest"
23
+ s.add_development_dependency "rufo", "~> 0.3.0"
24
+ s.add_development_dependency "rspec", "~> 3.5"
25
+ s.add_development_dependency "pry"
26
+ s.add_development_dependency "chef"
27
+ s.executables << "batali"
28
+ s.files = Dir["{lib,bin}/**/**/*"] + %w(batali.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
28
29
  end
data/bin/batali CHANGED
@@ -15,6 +15,7 @@ Bogo::Cli::Setup.define do
15
15
  on :V, :verbose, 'Enable verbose output'
16
16
  on :D, :debug, 'Enable debug mode'
17
17
  on :f, :file=, 'Path to Batali file'
18
+ on :y, :yes, 'Answer yes to interactive prompts'
18
19
  end
19
20
 
20
21
  command 'display' do
@@ -1,25 +1,24 @@
1
- require 'bogo-cli'
2
- require 'grimoire'
3
- require 'batali/monkey'
1
+ require "bogo-cli"
2
+ require "grimoire"
3
+ require "batali/monkey"
4
4
 
5
5
  # Batali namespace
6
6
  module Batali
7
-
8
- autoload :BFile, 'batali/b_file'
9
- autoload :Command, 'batali/command'
10
- autoload :Config, 'batali/config'
11
- autoload :Git, 'batali/git'
12
- autoload :Manifest, 'batali/manifest'
13
- autoload :Origin, 'batali/origin'
14
- autoload :RequirementList, 'batali/requirement_list'
15
- autoload :ScoreKeeper, 'batali/score_keeper'
16
- autoload :Source, 'batali/source'
17
- autoload :Struct, 'batali/b_file'
18
- autoload :Unit, 'batali/unit'
19
- autoload :UnitLoader, 'batali/unit_loader'
20
- autoload :Utility, 'batali/utility'
21
-
22
- autoload :TAG_LINES, 'batali/tag_lines'
7
+ autoload :BFile, "batali/b_file"
8
+ autoload :Command, "batali/command"
9
+ autoload :Config, "batali/config"
10
+ autoload :Git, "batali/git"
11
+ autoload :Manifest, "batali/manifest"
12
+ autoload :Origin, "batali/origin"
13
+ autoload :RequirementList, "batali/requirement_list"
14
+ autoload :ScoreKeeper, "batali/score_keeper"
15
+ autoload :Source, "batali/source"
16
+ autoload :Struct, "batali/b_file"
17
+ autoload :Unit, "batali/unit"
18
+ autoload :UnitLoader, "batali/unit_loader"
19
+ autoload :Utility, "batali/utility"
20
+
21
+ autoload :TAG_LINES, "batali/tag_lines"
23
22
 
24
23
  class << self
25
24
  # @return [Bogo::Ui]
@@ -30,7 +29,7 @@ module Batali
30
29
  # @param ui [Bogo::Ui]
31
30
  # @return [Bogo::Ui]
32
31
  def ui=(ui)
33
- unless(ui.respond_to?(:verbose) && ui.respond_to?(:debug))
32
+ unless ui.respond_to?(:verbose) && ui.respond_to?(:debug)
34
33
  raise TypeError.new "Expecting type `Bogo::Ui` but received `#{ui.class}`"
35
34
  end
36
35
  @ui = Grimoire.ui = ui
@@ -38,21 +37,19 @@ module Batali
38
37
 
39
38
  # Write verbose message
40
39
  def verbose(*args)
41
- if(ui)
40
+ if ui
42
41
  ui.verbose(*args)
43
42
  end
44
43
  end
45
44
 
46
45
  # Write debug message
47
46
  def debug(*args)
48
- if(ui)
47
+ if ui
49
48
  ui.debug(*args)
50
49
  end
51
50
  end
52
-
53
51
  end
54
-
55
52
  end
56
53
 
57
- require 'batali/b_file'
58
- require 'batali/version'
54
+ require "batali/b_file"
55
+ require "batali/version"
@@ -1,14 +1,13 @@
1
- require 'batali'
2
- require 'pathname'
1
+ require "batali"
2
+ require "pathname"
3
3
 
4
4
  # Batali namespace
5
5
  module Batali
6
6
 
7
7
  # Custom struct class for file processing
8
8
  class Struct < AttributeStruct
9
-
10
9
  def cookbook(*args)
11
- unless(self[:cookbook])
10
+ unless self[:cookbook]
12
11
  set!(:cookbook, ::AttributeStruct::CollapseArray.new.push(args))
13
12
  else
14
13
  self[:cookbook].push(args)
@@ -17,7 +16,7 @@ module Batali
17
16
  end
18
17
 
19
18
  def source(*args)
20
- unless(self[:source])
19
+ unless self[:source]
21
20
  set!(:source, ::AttributeStruct::CollapseArray.new.push(args))
22
21
  else
23
22
  self[:source].push(args)
@@ -26,7 +25,7 @@ module Batali
26
25
  end
27
26
 
28
27
  def chef_server(*args)
29
- unless(self[:chef_server])
28
+ unless self[:chef_server]
30
29
  set!(:chef_server, ::AttributeStruct::CollapseArray.new.push(args))
31
30
  else
32
31
  self[:chef_server].push(args)
@@ -35,7 +34,7 @@ module Batali
35
34
  end
36
35
 
37
36
  def restrict(*args)
38
- unless(self[:restrict])
37
+ unless self[:restrict]
39
38
  set!(:restrict, ::AttributeStruct::CollapseArray.new.push(args))
40
39
  else
41
40
  self[:restrict].push(args)
@@ -49,7 +48,7 @@ module Batali
49
48
 
50
49
  def _dump(*_)
51
50
  _keys.each do |k|
52
- if(_data[k].nil? && _data[k].is_a?(::AttributeStruct))
51
+ if _data[k].nil? && _data[k].is_a?(::AttributeStruct)
53
52
  _data[k] = true
54
53
  end
55
54
  end
@@ -57,7 +56,17 @@ module Batali
57
56
  end
58
57
 
59
58
  ::Object.constants.each do |const_name|
60
- next if const_name == :Config || const_name == :TimeoutError
59
+ deprecated_constants = [
60
+ :Config,
61
+ :Data,
62
+ :TimeoutError,
63
+ :Fixnum,
64
+ :Bignum,
65
+ :NIL,
66
+ :TRUE,
67
+ :FALSE,
68
+ ]
69
+ next if deprecated_constants.include?(const_name)
61
70
  const_set(const_name, ::Object.const_get(const_name))
62
71
  end
63
72
 
@@ -66,14 +75,23 @@ module Batali
66
75
  instance_exec do
67
76
  class << self
68
77
  ::Object.constants.each do |const_name|
69
- next if const_name == :Config || const_name == :TimeoutError
78
+ deprecated_constants = [
79
+ :Config,
80
+ :Data,
81
+ :TimeoutError,
82
+ :Fixnum,
83
+ :Bignum,
84
+ :NIL,
85
+ :TRUE,
86
+ :FALSE,
87
+ ]
88
+ next if deprecated_constants.include?(const_name)
70
89
  const_set(const_name, ::Object.const_get(const_name))
71
90
  end
72
91
  end
73
92
  end
74
93
  result
75
94
  end
76
-
77
95
  end
78
96
 
79
97
  # Create a new file
@@ -99,6 +117,7 @@ module Batali
99
117
  # @param cache_path [String] path to cache directory
100
118
  # @return [self]
101
119
  def initialize(b_file, cache_path)
120
+ b_file = Utility.clean_path(b_file)
102
121
  @cache = cache_path
103
122
  super(b_file)
104
123
  end
@@ -107,13 +126,13 @@ module Batali
107
126
  def self.cookbook_coerce
108
127
  proc do |v|
109
128
  v = [v].flatten.compact
110
- if(v.size == 1 && v.first.is_a?(Hash))
129
+ if v.size == 1 && v.first.is_a?(Hash)
111
130
  Cookbook.new(v.first)
112
131
  else
113
132
  name, args = v.first, v.slice(1, v.size)
114
- if(args.empty?)
133
+ if args.empty?
115
134
  args = Smash.new
116
- elsif(args.size == 1 && args.first.is_a?(Hash))
135
+ elsif args.size == 1 && args.first.is_a?(Hash)
117
136
  args = args.first
118
137
  else
119
138
  args = Smash.new(:constraint => args.map(&:to_s))
@@ -146,67 +165,67 @@ module Batali
146
165
  end
147
166
 
148
167
  attribute :discover, [TrueClass, FalseClass], :required => true, :default => false
149
- attribute :restrict, Restriction, :multiple => true, :coerce => lambda{|v|
150
- if(v.is_a?(Hash))
151
- Restriction.new(v)
152
- else
153
- Restriction.new(:cookbook => v.first, :source => v.last.to_smash[:source])
154
- end
155
- }
156
- attribute :source, Origin::RemoteSite, :multiple => true, :default => [], :coerce => lambda{|v, b_file|
157
- if(v.is_a?(Hash))
158
- args = v
159
- else
160
- args = Smash.new(:endpoint => v.first)
161
- if(v.last.is_a?(Hash))
162
- args.merge!(v.last)
163
- end
164
- end
165
- Origin::RemoteSite.new(args.merge(:cache_path => b_file.cache))
166
- }
167
- attribute :chef_server, Origin::ChefServer, :multiple => true, :default => [], :coerce => lambda{|v, b_file|
168
- if(v.is_a?(Hash))
169
- args = v
170
- else
171
- args = Smash.new(:endpoint => v.first)
172
- if(v.last.is_a?(Hash))
173
- args.merge!(v.last)
174
- end
175
- end
176
- Origin::ChefServer.new(args.merge(:cache_path => b_file.cache))
177
- }
178
- attribute :group, Group, :multiple => true, :coerce => lambda{|v| Group.new(v)}
168
+ attribute :restrict, Restriction, :multiple => true, :coerce => lambda { |v|
169
+ if v.is_a?(Hash)
170
+ Restriction.new(v)
171
+ else
172
+ Restriction.new(:cookbook => v.first, :source => v.last.to_smash[:source])
173
+ end
174
+ }
175
+ attribute :source, Origin::RemoteSite, :multiple => true, :default => [], :coerce => lambda { |v, b_file|
176
+ if v.is_a?(Hash)
177
+ args = v
178
+ else
179
+ args = Smash.new(:endpoint => v.first)
180
+ if v.last.is_a?(Hash)
181
+ args.merge!(v.last)
182
+ end
183
+ end
184
+ Origin::RemoteSite.new(args.merge(:cache_path => b_file.cache))
185
+ }
186
+ attribute :chef_server, Origin::ChefServer, :multiple => true, :default => [], :coerce => lambda { |v, b_file|
187
+ if v.is_a?(Hash)
188
+ args = v
189
+ else
190
+ args = Smash.new(:endpoint => v.first)
191
+ if v.last.is_a?(Hash)
192
+ args.merge!(v.last)
193
+ end
194
+ end
195
+ Origin::ChefServer.new(args.merge(:cache_path => b_file.cache))
196
+ }
197
+ attribute :group, Group, :multiple => true, :coerce => lambda { |v| Group.new(v) }
179
198
  attribute :cookbook, Cookbook, :multiple => true, :coerce => BFile.cookbook_coerce, :default => []
180
- attribute :metadata, Cookbook, :coerce => lambda{ |v, b_file|
181
- if(v.is_a?(Hash))
182
- ckbk = Cookbook.new(v)
183
- else
184
- dir = Pathname.new(File.dirname(b_file.path)).relative_path_from(Pathname.new(Dir.pwd)).to_path
185
- m_unit = Origin::Path.new(:name => 'metadata', :path => dir, :cache_path => b_file.cache).units.first
186
- ckbk = Cookbook.new(:name => m_unit.name, :version => m_unit.version, :path => dir)
187
- end
188
- unless(b_file.cookbook.map(&:name).include?(ckbk.name))
189
- b_file.cookbook.push ckbk
190
- end
191
- ckbk
192
- }
199
+ attribute :metadata, Cookbook, :coerce => lambda { |v, b_file|
200
+ if v.is_a?(Hash)
201
+ ckbk = Cookbook.new(v)
202
+ else
203
+ dir = Pathname.new(File.dirname(b_file.path)).relative_path_from(Pathname.new(Utility.clean_path(Dir.pwd))).to_path
204
+ m_unit = Origin::Path.new(:name => "metadata", :path => dir, :cache_path => b_file.cache).units.first
205
+ ckbk = Cookbook.new(:name => m_unit.name, :version => m_unit.version, :path => dir)
206
+ end
207
+ unless b_file.cookbook.map(&:name).include?(ckbk.name)
208
+ b_file.cookbook.push ckbk
209
+ end
210
+ ckbk
211
+ }
193
212
 
194
213
  # Search environments for cookbooks and restraints
195
214
  #
196
215
  # @return [TrueClass]
197
- def auto_discover!(environment=nil)
198
- debug 'Starting cookbook auto-discovery'
199
- unless(discover)
200
- raise 'Attempting to perform auto-discovery but auto-discovery is not enabled!'
216
+ def auto_discover!(environment = nil)
217
+ debug "Starting cookbook auto-discovery"
218
+ unless discover
219
+ raise "Attempting to perform auto-discovery but auto-discovery is not enabled!"
201
220
  end
202
- environment_items = Dir.glob(File.join(File.dirname(path), 'environments', '*.{json,rb}')).map do |e_path|
221
+ environment_items = Dir.glob(Utility.join_path(File.dirname(path), "environments", "*.{json,rb}")).map do |e_path|
203
222
  result = parse_environment(e_path)
204
- if(result[:name] && result[:cookbooks])
223
+ if result[:name] && result[:cookbooks]
205
224
  Smash.new(
206
- result[:name] => result[:cookbooks]
225
+ result[:name] => result[:cookbooks],
207
226
  )
208
227
  end
209
- end.compact.inject(Smash.new){|m, n| m.merge(n)}
228
+ end.compact.inject(Smash.new) { |m, n| m.merge(n) }
210
229
  environment_items.each do |e_name, items|
211
230
  next if environment && e_name != environment
212
231
  debug "Discovery processing of environment: #{e_name}"
@@ -214,8 +233,8 @@ module Batali
214
233
  ckbk = cookbook.detect do |c|
215
234
  c.name == ckbk_name
216
235
  end
217
- if(ckbk)
218
- unless(ckbk.constraint)
236
+ if ckbk
237
+ unless ckbk.constraint
219
238
  debug "Skipping constraint merging due to lack of original constraints: #{ckbk.inspect}"
220
239
  next
221
240
  end
@@ -230,13 +249,13 @@ module Batali
230
249
  cookbook.push(
231
250
  Cookbook.new(
232
251
  :name => ckbk_name,
233
- :constraint => constraints
252
+ :constraint => constraints,
234
253
  )
235
254
  )
236
255
  end
237
256
  end
238
257
  end
239
- debug 'Completed cookbook auto-discovery'
258
+ debug "Completed cookbook auto-discovery"
240
259
  true
241
260
  end
242
261
 
@@ -247,8 +266,8 @@ module Batali
247
266
  # @param constraint [String]
248
267
  # @param [Array<String>]
249
268
  def convert_constraint(constraint)
250
- comp, ver = constraint.split(' ', 2).map(&:strip)
251
- if(comp == '~>')
269
+ comp, ver = constraint.split(" ", 2).map(&:strip)
270
+ if comp == "~>"
252
271
  ver = UnitVersion.new(ver)
253
272
  [">= #{ver}", "< #{ver.bump}"]
254
273
  else
@@ -268,40 +287,40 @@ module Batali
268
287
  grouped = Smash[
269
288
  grouped.map do |comp, items|
270
289
  versions = items.map(&:last)
271
- if(comp.start_with?('>'))
290
+ if comp.start_with?(">")
272
291
  [comp, [versions.min]]
273
- elsif(comp.start_with?('<'))
292
+ elsif comp.start_with?("<")
274
293
  [comp, [versions.max]]
275
294
  else
276
295
  [comp, versions]
277
296
  end
278
297
  end
279
298
  ]
280
- if(grouped['='])
281
- grouped['>='] ||= []
282
- grouped['<='] ||= []
283
- grouped['='].each do |ver|
284
- grouped['>='] << ver
285
- grouped['<='] << ver
299
+ if grouped["="]
300
+ grouped[">="] ||= []
301
+ grouped["<="] ||= []
302
+ grouped["="].each do |ver|
303
+ grouped[">="] << ver
304
+ grouped["<="] << ver
286
305
  end
287
- grouped.delete('=')
306
+ grouped.delete("=")
288
307
  end
289
- if(grouped['>'] || grouped['>='])
290
- if(grouped['>='] && (grouped['>'].nil? || grouped['>='].min <= grouped['>'].min))
291
- grouped['>='] = [grouped['>='].min]
292
- grouped.delete('>')
308
+ if grouped[">"] || grouped[">="]
309
+ if grouped[">="] && (grouped[">"].nil? || grouped[">="].min <= grouped[">"].min)
310
+ grouped[">="] = [grouped[">="].min]
311
+ grouped.delete(">")
293
312
  else
294
- grouped['>'] = [grouped['>'].min]
295
- grouped.delete('>=')
313
+ grouped[">"] = [grouped[">"].min]
314
+ grouped.delete(">=")
296
315
  end
297
316
  end
298
- if(grouped['<'] || grouped['<='])
299
- if(grouped['<='] && (grouped['<'].nil? || grouped['<='].max >= grouped['<'].max))
300
- grouped['<='] = [grouped['<='].max]
301
- grouped.delete('<')
317
+ if grouped["<"] || grouped["<="]
318
+ if grouped["<="] && (grouped["<"].nil? || grouped["<="].max >= grouped["<"].max)
319
+ grouped["<="] = [grouped["<="].max]
320
+ grouped.delete("<")
302
321
  else
303
- grouped['<'] = [grouped['<'].max]
304
- grouped.delete('<=')
322
+ grouped["<"] = [grouped["<"].max]
323
+ grouped.delete("<=")
305
324
  end
306
325
  end
307
326
  grouped.map do |comp, vers|
@@ -316,12 +335,13 @@ module Batali
316
335
  # @param path [String] path to environment
317
336
  # @return [Smash]
318
337
  def parse_environment(path)
338
+ path = Utility.clean_path(path)
319
339
  case File.extname(path)
320
- when '.json'
340
+ when ".json"
321
341
  env = MultiJson.load(
322
342
  File.read(path)
323
343
  ).to_smash
324
- when '.rb'
344
+ when ".rb"
325
345
  struct = Struct.new
326
346
  struct.set_state!(:value_collapse => true)
327
347
  struct.instance_eval(File.read(path), path, 1)
@@ -335,8 +355,8 @@ module Batali
335
355
  env.fetch(
336
356
  :cookbook_versions,
337
357
  Smash.new
338
- ).map{|k, v| [k, v.to_s.split(',')]}
339
- ]
358
+ ).map { |k, v| [k, v.to_s.split(",")] }
359
+ ],
340
360
  )
341
361
  end
342
362
 
@@ -344,7 +364,5 @@ module Batali
344
364
  def debug(s)
345
365
  Batali.debug(s)
346
366
  end
347
-
348
367
  end
349
-
350
368
  end