batali 0.4.10 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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