batali 0.0.1 → 0.1.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
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: