batali 0.0.1 → 0.1.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
2
  SHA1:
3
- metadata.gz: dc4ffb55cfc9404110a31d84080917bd03fe57c5
4
- data.tar.gz: a90b9dbf07e2aeb1aa793ab3ae1bc747ecd320fb
3
+ metadata.gz: 12ae5060ad51ee573081c34f077e1242908dddd7
4
+ data.tar.gz: b569cf195a11b93a1b7c1ddf87df063c63df1693
5
5
  SHA512:
6
- metadata.gz: 3289b9038b99b8d76f8ad18f30a7c3faa472d6586979b6a861d60f10119d2c9ce6bc38059c3cd9f6bea929bdf3bc06b8e156e0be44dfe0a4fe4a90011fb17c4c
7
- data.tar.gz: a6aaa1cb5819cac5d4c26840e200e379398f0da606a6f7198947158ac2855ad6e45784594a211cb4c3a7cbe6a521c7aa5bb9bc2a98e26f6238f98658f4742f11
6
+ metadata.gz: 909cfbcd842a0f2187efab1e4bf9453bc15234e38a0de13317b6ae1a5cf02b222cf499b4caf8ef6da814aa12c1cb74f2dbbde92089645ac9410e230f63f0d1e5
7
+ data.tar.gz: 1523d71a2af4dd85a487effeeb1bc967160f1093fec75925019afee3f3b128d0e32f3d07d983740d08f754e3732838ba909d672d2c565456466fbc660a333642
data/CHANGELOG.md CHANGED
@@ -1,2 +1,2 @@
1
1
  # v0.1.0
2
- * Initial commit
2
+ * Initial release
data/README.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # Batali
2
2
 
3
- ## Info
3
+ Batali is a light weight cookbook resolver. It is currently
4
+ in an alpha state and should not be used with anything you
5
+ care about or love. There is a high chance it will burn it
6
+ all to the ground, and laugh.
7
+
8
+ ## Usage
9
+
10
+ Provide a `Batali` file:
11
+
12
+ ```ruby
13
+ Batali.define do
14
+ source 'https://supermarket.chef.io'
15
+ cookbook 'postgresql'
16
+ end
17
+ ```
18
+
19
+ and then run:
20
+
21
+ ```
22
+ $ batali update
23
+ ```
24
+
25
+ in the same directory. It will destroy your `cookbooks` directory
26
+ by default.
27
+
28
+ _IT WILL DESTROY YOUR COOKBOOKS DIRECTORY BY DEFAULT_
29
+
30
+ There is other cool stuff too, to be documented later. Currently
31
+ only site sources can be defined (no path, or git, or anything else).
32
+
33
+
34
+ # Info
4
35
 
5
36
  * Repository: https://github.com/hw-labs/batali
data/batali.gemspec CHANGED
@@ -10,7 +10,13 @@ Gem::Specification.new do |s|
10
10
  s.description = 'Magic'
11
11
  s.require_path = 'lib'
12
12
  s.license = 'Apache 2.0'
13
+ s.add_runtime_dependency 'grimoire', '>= 0.1.2'
14
+ s.add_runtime_dependency 'bogo', '>= 0.1.12'
15
+ s.add_runtime_dependency 'bogo-cli', '>= 0.1.8'
16
+ s.add_runtime_dependency 'bogo-config', '>= 0.1.10'
17
+ s.add_runtime_dependency 'http'
13
18
  s.add_development_dependency 'minitest'
14
19
  s.add_development_dependency 'pry'
20
+ s.executables << 'batali'
15
21
  s.files = Dir['{lib,bin}/**/**/*'] + %w(batali.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
16
22
  end
data/bin/batali ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'batali'
4
+
5
+ Bogo::Cli::Setup.define do
6
+
7
+ on :v, :version, 'Print version' do
8
+ puts "batali - Cookbook Collection Manager - [Version: #{Batali::VERSION}]"
9
+ exit
10
+ end
11
+
12
+ global_opts = lambda do
13
+ on :c, :config, 'Configuration file path'
14
+ on :V, :verbose, 'Enable verbose output'
15
+ on :D, :debug, 'Enable debug mode'
16
+ on :f, :file, 'Path to Batali file'
17
+ end
18
+
19
+ command 'install' do
20
+ description 'Install cookbooks from manifest'
21
+ self.instance_exec(&global_opts)
22
+ on :d, 'dry-run', 'Print changes'
23
+ on :p, 'path', 'Cookbook install path'
24
+ run do |opts, args|
25
+ Batali::Command::Install.new({:install => opts.to_hash}, args).execute!
26
+ end
27
+ end
28
+
29
+ command 'update' do
30
+ description 'Update cookbooks manifest'
31
+ self.instance_exec(&global_opts)
32
+ on :d, 'dry-run', 'Print changes'
33
+ on :l, 'least-impact', 'Update cookbooks with minimal version impact', :default => true
34
+ on :i, 'install', 'Install cookbooks after update', :default => true
35
+
36
+ run do |opts, args|
37
+ Batali::Command::Update.new({:update => opts.to_hash}, args).execute!
38
+ end
39
+ end
40
+
41
+ command 'resolve' do
42
+ description 'Build the cookbook manifest'
43
+ self.instance_exec(&global_opts)
44
+ on :d, 'dry-run', 'Print changes'
45
+ on :l, 'least-impact', 'Update cookbooks with minimal version impact', :default => true
46
+
47
+ run do |opts, args|
48
+ Batali::Command::Resolve.new({:resolve => opts.to_hash}, args).execute!
49
+ end
50
+ end
51
+
52
+ command 'configure' do
53
+ self.instance_exec(&global_opts)
54
+ run do |opts, args|
55
+ Batali::Command::Configure.new(opts, args).execute!
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,61 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+
5
+ class Struct < AttributeStruct
6
+
7
+ def cookbook(*args)
8
+ set!(:cookbook, args)
9
+ self
10
+ end
11
+
12
+ end
13
+
14
+ # Create a new file
15
+ #
16
+ # @param block [Proc]
17
+ # @return [AttributeStruct]
18
+ def self.define(&block)
19
+ struct = Struct.new
20
+ struct.set_state!(:value_collapse => true)
21
+ struct.build!(&block)
22
+ struct
23
+ end
24
+
25
+ class BFile < Bogo::Config
26
+
27
+ class Cookbook < Grimoire::Utility
28
+ attribute :name, String, :required => true
29
+ attribute :constraint, String, :multiple => true
30
+ attribute :git, Smash, :coerce => lambda{|v| v.to_smash}
31
+ attribute :path, String
32
+ end
33
+
34
+ attribute :source, RemoteSite, :multiple => true, :coerce => lambda{|v| RemoteSite.new(:endpoint => v)}
35
+ attribute :cookbook, Cookbook, :multiple => true, :coerce => lambda{|v|
36
+ case v
37
+ when Array
38
+ Cookbook.new(
39
+ :name => v.first,
40
+ :constraint => v.slice(1, v.size)
41
+ )
42
+ when String
43
+ Cookbook.new(:name => v)
44
+ when Hash
45
+ c_name = v.keys.first
46
+ constraints = v.values.first.to_a.flatten.find_all{|i| i.is_a?(String)}
47
+ Cookbook.new(
48
+ :name => c_name,
49
+ :constraint => constraints
50
+ )
51
+ else
52
+ raise ArgumentError.new "Unable to coerce given type `#{v.class}` to `Batali::BFile::Cookbook`!"
53
+ end
54
+ }
55
+
56
+ ## TODO: supported values still required
57
+ # attribute :restrict -- restrict cookbooks of name `x` to source named `y`
58
+ # attribute :group -- cookbook grouping (i.e. :integration)
59
+ end
60
+
61
+ end
@@ -0,0 +1,12 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ class Command
5
+
6
+ # Create/Update Batali configuration
7
+ class Configure < Batali::Command
8
+
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,45 @@
1
+ require 'batali'
2
+ require 'fileutils'
3
+
4
+ module Batali
5
+ class Command
6
+
7
+ # Install cookbooks based on manifest
8
+ class Install < Batali::Command
9
+
10
+ # Install cookbooks
11
+ def execute!
12
+ dry_run('Cookbook installation') do
13
+ install_path = opts.fetch(:path, 'cookbooks')
14
+ run_action('Readying installation destination') do
15
+ FileUtils.rm_rf(install_path)
16
+ FileUtils.mkdir_p(install_path)
17
+ nil
18
+ end
19
+ run_action('Installing cookbooks') do
20
+ manifest.cookbook.each do |unit|
21
+ asset_path = unit.source.asset
22
+ begin
23
+ FileUtils.mv(
24
+ File.join(
25
+ asset_path,
26
+ unit.name
27
+ ),
28
+ File.join(
29
+ install_path,
30
+ unit.name
31
+ )
32
+ )
33
+ ensure
34
+ FileUtils.rm_rf(asset_path)
35
+ end
36
+ end
37
+ nil
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,71 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ class Command
5
+
6
+ # Resolve cookbooks
7
+ class Resolve < Command
8
+
9
+ # Resolve dependencies and constraints. Output results to stdout
10
+ # and dump serialized manifest
11
+ def execute!
12
+ system = Grimoire::System.new
13
+ run_action 'Loading sources' do
14
+ batali_file.source.map(&:units).flatten.map do |unit|
15
+ system.add_unit(unit)
16
+ end
17
+ nil
18
+ end
19
+ requirements = Grimoire::RequirementList.new(
20
+ :name => :batali_resolv,
21
+ :requirements => batali_file.cookbook.map{ |ckbk|
22
+ [ckbk.name, *(ckbk.constraint.empty? ? ['> 0'] : ckbk.constraint)]
23
+ }
24
+ )
25
+ solv = Grimoire::Solver.new(
26
+ :requirements => requirements,
27
+ :system => system,
28
+ :score_keeper => score_keeper
29
+ )
30
+ results = []
31
+ run_action 'Resolving dependency constraints' do
32
+ results = solv.generate!
33
+ nil
34
+ end
35
+ if(results.empty?)
36
+ ui.error 'No solutions found defined requirements!'
37
+ else
38
+ ideal_solution = results.pop
39
+ dry_run('manifest file write') do
40
+ run_action 'Writing manifest' do
41
+ manifest = Manifest.new(:cookbook => ideal_solution.units)
42
+ File.open('batali.manifest', 'w') do |file|
43
+ file.write MultiJson.dump(manifest, :pretty => true)
44
+ end
45
+ nil
46
+ end
47
+ end
48
+ ui.info "Found #{results.size} solutions for defined requirements."
49
+ ui.info 'Ideal solution:'
50
+ ui.puts ideal_solution.units.sort_by(&:name).map{|u| "#{u.name}<#{u.version}>"}
51
+ end
52
+ end
53
+
54
+ # @return [ScoreKeeper]
55
+ def score_keeper
56
+ memoize(:score_keeper) do
57
+ sk_manifest = Manifest.new(:cookbook => manifest.cookbook)
58
+ unless(opts[:least_impact])
59
+ sk_manifest.cookbook.clear
60
+ end
61
+ sk_manifest.cookbook.delete_if do |unit|
62
+ arguments.include?(unit.name)
63
+ end
64
+ ScoreKeeper.new(:manifest => sk_manifest)
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,17 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ class Command
5
+
6
+ # Update cookbook manifest
7
+ class Update < Batali::Command
8
+
9
+ def execute!
10
+ Resolve.new({:resolve => opts}, arguments).execute!
11
+ Install.new({:install => opts}, arguments).execute!
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ # Customized command base for Batali
5
+ class Command < Bogo::Cli::Command
6
+
7
+ include Bogo::Memoization
8
+
9
+ autoload :Configure, 'batali/command/configure'
10
+ autoload :Install, 'batali/command/install'
11
+ autoload :Resolve, 'batali/command/resolve'
12
+ autoload :Update, 'batali/command/update'
13
+
14
+ # @return [BFile]
15
+ def batali_file
16
+ memoize(:batali_file) do
17
+ # TODO: Add directory traverse searching
18
+ BFile.new(opts.fetch(:file, File.join(Dir.pwd, 'Batali')))
19
+ end
20
+ end
21
+
22
+ # @return [Manifest]
23
+ def manifest
24
+ memoize(:manifest) do
25
+ Manifest.build(
26
+ File.join(
27
+ File.dirname(
28
+ opts.fetch(:file, File.join(Dir.pwd, 'batali.manifest'))
29
+ ), 'batali.manifest'
30
+ )
31
+ )
32
+ end
33
+ end
34
+
35
+ # Do not execute block if dry run
36
+ #
37
+ # @param action [String] action to be performed
38
+ # @yield block to execute
39
+ def dry_run(action)
40
+ if(opts[:dry_run])
41
+ ui.warn "Dry run disabled: #{action}"
42
+ else
43
+ yield
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ class Config < Bogo::Config
5
+
6
+ end
7
+ end
@@ -0,0 +1,42 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ # Collection of resolved units
5
+ class Manifest < Grimoire::Utility
6
+
7
+ include Bogo::Memoization
8
+
9
+ attribute :cookbook, Unit, :multiple => true, :coerce => lambda{|v| Unit.new(v)}
10
+
11
+ # Build manifest from given path. If no file exists, empty
12
+ # manifest will be provided.
13
+ #
14
+ # @param path [String] path to manifest
15
+ # @return [Manifest]
16
+ def self.build(path)
17
+ if(File.exists?(path))
18
+ self.new(Bogo::Config.new(path).data)
19
+ else
20
+ self.new
21
+ end
22
+ end
23
+
24
+ # Check for unit within manifest
25
+ #
26
+ # @param unit [Unit]
27
+ # @return [TrueClass, FalseClass]
28
+ def include?(unit)
29
+ memoize(unit.inspect) do
30
+ if(cookbook)
31
+ !!cookbook.detect do |ckbk|
32
+ ckbk.name == unit.name &&
33
+ ckbk.version == unit.version
34
+ end
35
+ else
36
+ false
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ # Simple stubs mostly for naming
5
+ class UnitVersion < Grimoire::VERSION_CLASS; end
6
+ class UnitRequirement < Grimoire::REQUIREMENT_CLASS; end
7
+ class UnitDependency < Grimoire::DEPENDENCY_CLASS
8
+ def to_json(*args)
9
+ result = [
10
+ name,
11
+ *requirement.requirements.map do |req|
12
+ req.join(' ')
13
+ end
14
+ ]
15
+ MultiJson.dump(result, *args)
16
+ end
17
+ end
18
+ end
19
+
20
+ Grimoire.send(:remove_const, :VERSION_CLASS)
21
+ Grimoire.send(:remove_const, :DEPENDENCY_CLASS)
22
+ Grimoire.send(:remove_const, :REQUIREMENT_CLASS)
23
+
24
+ Grimoire.const_set(:VERSION_CLASS, Batali::UnitVersion)
25
+ Grimoire.const_set(:DEPENDENCY_CLASS, Batali::UnitDependency)
26
+ Grimoire.const_set(:REQUIREMENT_CLASS, Batali::UnitRequirement)
@@ -0,0 +1,98 @@
1
+ require 'batali'
2
+ require 'digest/sha2'
3
+ require 'securerandom'
4
+ require 'http'
5
+ require 'fileutils'
6
+
7
+ module Batali
8
+ # Fetch unit information from remote site
9
+ class RemoteSite < Grimoire::Utility
10
+
11
+ # Site suffix for API endpoint
12
+ COOKBOOK_API_SUFFIX = 'api/v1/cookbooks'
13
+
14
+ include Bogo::Memoization
15
+
16
+ attribute :name, String
17
+ attribute :identifier, String
18
+ attribute :endpoint, String, :required => true
19
+ attribute :force_update, [TrueClass, FalseClass], :required => true, :default => false
20
+ attribute :update_interval, Integer, :required => true, :default => 10000 # NOTE: reset this default to 60/120 when ready
21
+ attribute :cache, String, :default => File.expand_path('~/.batali/cache/remote_site'), :required => true
22
+
23
+ def initialize(*_)
24
+ super
25
+ endpoint = URI.join(self.endpoint, COOKBOOK_API_SUFFIX).to_s
26
+ self.identifier = Digest::SHA256.hexdigest(endpoint)
27
+ unless(name?)
28
+ self.name = self.identifier
29
+ end
30
+ end
31
+
32
+ # @return [String] cache directory path
33
+ def cache_directory
34
+ memoize(:cache_directory) do
35
+ path = File.join(cache, identifier)
36
+ FileUtils.mkdir_p(path)
37
+ path
38
+ end
39
+ end
40
+
41
+ # @return [Array<Unit>] all units
42
+ def units
43
+ memoize(:units) do
44
+ items.map do |u_name, versions|
45
+ versions.map do |version, info|
46
+ Unit.new(
47
+ :name => u_name,
48
+ :version => version,
49
+ :dependencies => info[:dependencies].to_a,
50
+ :source => Smash.new(
51
+ :type => :site,
52
+ :url => info[:download_url],
53
+ :version => version,
54
+ :dependencies => info[:dependencies]
55
+ )
56
+ )
57
+ end
58
+ end.flatten
59
+ end
60
+ end
61
+
62
+ protected
63
+
64
+ # @return [Smash] all info
65
+ def items
66
+ memoize(:items) do
67
+ MultiJson.load(File.read(fetch)).to_smash
68
+ end
69
+ end
70
+
71
+ # Fetch the universe
72
+ #
73
+ # @return [String] path to universe file
74
+ def fetch
75
+ do_fetch = true
76
+ if(File.exists?(universe_path))
77
+ age = Time.now - File.mtime(universe_path)
78
+ if(age < update_interval)
79
+ do_fetch = false
80
+ end
81
+ end
82
+ if(do_fetch)
83
+ t_uni = "#{universe_path}.#{SecureRandom.urlsafe_base64}"
84
+ File.open(t_uni, 'w') do |file|
85
+ file.write HTTP.get(URI.join(endpoint, 'universe')).body.to_s
86
+ end
87
+ FileUtils.mv(t_uni, universe_path)
88
+ end
89
+ universe_path
90
+ end
91
+
92
+ # @return [String] path to universe file
93
+ def universe_path
94
+ File.join(cache_directory, 'universe.json')
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,18 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ # Provide scores for units
5
+ class ScoreKeeper < Grimoire::UnitScoreKeeper
6
+
7
+ attribute :manifest, Manifest, :required => true
8
+
9
+ # Provide score for given unit
10
+ #
11
+ # @param unit [Unit]
12
+ # @return [Numeric, NilClass]
13
+ def score_for(unit)
14
+ manifest.include?(unit) ? 0 : nil
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ require 'batali'
2
+ require 'fileutils'
3
+ require 'tmpdir'
4
+
5
+ module Batali
6
+ # Source of asset
7
+ class Source
8
+ # Path based source
9
+ class Path < Source
10
+
11
+ include Bogo::Memoization
12
+
13
+ attribute :path, String, :required => true
14
+
15
+ # @return [String] directory containing contents
16
+ def asset
17
+ memoize(:asset) do
18
+ dir = Dir.mktmpdir
19
+ FileUtils.cp_r(path, dir)
20
+ dir
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,70 @@
1
+ require 'batali'
2
+ require 'http'
3
+ require 'tmpdir'
4
+ require 'rubygems/package'
5
+ require 'zlib'
6
+
7
+ module Batali
8
+ class Source
9
+ # Site based source
10
+ class Site < Source
11
+
12
+ # @return [Array<Hash>] dependency strings
13
+ attr_reader :dependencies
14
+ # @return [String] version
15
+ attr_reader :version
16
+
17
+ attribute :url, String, :required => true
18
+ attribute :version, String, :required => true
19
+
20
+ # Extract extra info before allowing super to load data
21
+ #
22
+ # @param args [Hash]
23
+ # @return [self]
24
+ def initialize(args={})
25
+ @deps = args.delete(:dependencies) || {}
26
+ super
27
+ end
28
+
29
+ # @return [String]
30
+ def unit_version
31
+ version
32
+ end
33
+
34
+ # @return [Array<Array<name, constraints>>]
35
+ def unit_dependencies
36
+ deps.to_a
37
+ end
38
+
39
+ # @return [String] directory
40
+ def asset
41
+ path = Dir.mktmpdir('batali')
42
+ result = HTTP.get(url)
43
+ while(result.code == 302)
44
+ result = HTTP.get(result.headers['Location'])
45
+ end
46
+ File.open(a_path = File.join(path, 'asset'), 'w') do |file|
47
+ while(content = result.body.readpartial(2048))
48
+ file.write content
49
+ end
50
+ end
51
+ ext = Gem::Package::TarReader.new(
52
+ Zlib::GzipReader.open(a_path)
53
+ )
54
+ ext.rewind
55
+ ext.each do |entry|
56
+ next unless entry.file?
57
+ n_path = File.join(path, entry.full_name)
58
+ FileUtils.mkdir_p(File.dirname(n_path))
59
+ File.open(n_path, 'w') do |file|
60
+ while(content = entry.read(2048))
61
+ file.write(content)
62
+ end
63
+ end
64
+ end
65
+ path
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,45 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ # Source of asset
5
+ class Source < Grimoire::Utility
6
+
7
+ autoload :Path, 'batali/source/path'
8
+ autoload :Site, 'batali/source/site'
9
+ autoload :Git, 'batali/source/git'
10
+
11
+ attribute :type, String, :required => true, :default => lambda{ self.name }
12
+
13
+ # @return [String]
14
+ def unit_version
15
+ raise NotImplementedError.new 'Abstract class'
16
+ end
17
+
18
+ # @return [Array<Array<name, constraints>>]
19
+ def unit_dependencies
20
+ raise NotImplementedError.new 'Abstract class'
21
+ end
22
+
23
+ # @return [String] directory containing contents
24
+ def asset
25
+ raise NotImplementedError.new 'Abstract class'
26
+ end
27
+
28
+ # Build a source
29
+ #
30
+ # @param args [Hash]
31
+ # @return [Source]
32
+ # @note uses `:type` to build concrete source
33
+ def self.build(args)
34
+ type = args.delete(:type)
35
+ unless(type)
36
+ raise ArgumentError.new 'Missing required option `:type`!'
37
+ end
38
+ unless(type.to_s.include?('::'))
39
+ type = [self.name, Bogo::Utility.camel(type)].join('::')
40
+ end
41
+ Bogo::Utility.constantize(type).new(args.merge(:type => type))
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,8 @@
1
+ require 'batali'
2
+
3
+ module Batali
4
+ # Customized Unit
5
+ class Unit < Grimoire::Unit
6
+ attribute :source, Source, :required => true, :coerce => lambda{|v| Batali::Source.build(v)}
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module Batali
2
- VERSION = Gem::Version.new('0.0.1')
2
+ VERSION = Gem::Version.new('0.1.0')
3
3
  end
data/lib/batali.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'bogo-cli'
2
+ require 'grimoire'
3
+
4
+ module Batali
5
+
6
+ autoload :Command, 'batali/command'
7
+ autoload :Config, 'batali/config'
8
+ autoload :Manifest, 'batali/manifest'
9
+ autoload :RemoteSite, 'batali/remote_site'
10
+ autoload :ScoreKeeper, 'batali/score_keeper'
11
+ autoload :Source, 'batali/source'
12
+ autoload :Unit, 'batali/unit'
13
+
14
+ end
15
+
16
+ require 'batali/b_file'
17
+ require 'batali/monkey'
18
+ require 'batali/version'
metadata CHANGED
@@ -1,15 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: batali
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-26 00:00:00.000000000 Z
11
+ date: 2015-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: grimoire
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: bogo
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.12
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.12
41
+ - !ruby/object:Gem::Dependency
42
+ name: bogo-cli
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.8
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.8
55
+ - !ruby/object:Gem::Dependency
56
+ name: bogo-config
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.10
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.10
69
+ - !ruby/object:Gem::Dependency
70
+ name: http
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'
13
83
  - !ruby/object:Gem::Dependency
14
84
  name: minitest
15
85
  requirement: !ruby/object:Gem::Requirement
@@ -40,7 +110,8 @@ dependencies:
40
110
  version: '0'
41
111
  description: Magic
42
112
  email: code@chrisroberts.org
43
- executables: []
113
+ executables:
114
+ - batali
44
115
  extensions: []
45
116
  extra_rdoc_files: []
46
117
  files:
@@ -49,6 +120,23 @@ files:
49
120
  - LICENSE
50
121
  - README.md
51
122
  - batali.gemspec
123
+ - bin/batali
124
+ - lib/batali.rb
125
+ - lib/batali/b_file.rb
126
+ - lib/batali/command.rb
127
+ - lib/batali/command/configure.rb
128
+ - lib/batali/command/install.rb
129
+ - lib/batali/command/resolve.rb
130
+ - lib/batali/command/update.rb
131
+ - lib/batali/config.rb
132
+ - lib/batali/manifest.rb
133
+ - lib/batali/monkey.rb
134
+ - lib/batali/remote_site.rb
135
+ - lib/batali/score_keeper.rb
136
+ - lib/batali/source.rb
137
+ - lib/batali/source/path.rb
138
+ - lib/batali/source/site.rb
139
+ - lib/batali/unit.rb
52
140
  - lib/batali/version.rb
53
141
  homepage: https://github.com/hw-labs/batali
54
142
  licenses: