rubycut-babushka 0.10.6
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.
- data/Gemfile +8 -0
- data/Gemfile.lock +31 -0
- data/README.markdown +246 -0
- data/Rakefile +26 -0
- data/bin/babushka +11 -0
- data/deps/babushka.rb +101 -0
- data/deps/dev.rb +12 -0
- data/deps/fhs.rb +31 -0
- data/deps/git.rb +29 -0
- data/deps/homebrew.rb +30 -0
- data/deps/os_x.rb +33 -0
- data/deps/packages.rb +22 -0
- data/deps/pkg_managers.rb +110 -0
- data/deps/ruby.rb +23 -0
- data/deps/rubygems.rb +24 -0
- data/deps/system.rb +10 -0
- data/deps/templates/app.rb +68 -0
- data/deps/templates/external.rb +12 -0
- data/deps/templates/installer.rb +31 -0
- data/deps/templates/managed.rb +105 -0
- data/deps/templates/ppa.rb +24 -0
- data/deps/templates/src.rb +42 -0
- data/deps/templates/tmbundle.rb +15 -0
- data/lib/babushka.rb +28 -0
- data/lib/babushka/accepts_block_for.rb +72 -0
- data/lib/babushka/accepts_list_for.rb +49 -0
- data/lib/babushka/accepts_value_for.rb +24 -0
- data/lib/babushka/base.rb +78 -0
- data/lib/babushka/bug_reporter.rb +55 -0
- data/lib/babushka/cmdline.rb +133 -0
- data/lib/babushka/cmdline/handler.rb +41 -0
- data/lib/babushka/cmdline/helpers.rb +127 -0
- data/lib/babushka/cmdline/parser.rb +69 -0
- data/lib/babushka/colorizer.rb +59 -0
- data/lib/babushka/core_patches/array.rb +171 -0
- data/lib/babushka/core_patches/blank.rb +22 -0
- data/lib/babushka/core_patches/bytes.rb +52 -0
- data/lib/babushka/core_patches/hash.rb +107 -0
- data/lib/babushka/core_patches/hashish.rb +14 -0
- data/lib/babushka/core_patches/integer.rb +25 -0
- data/lib/babushka/core_patches/io.rb +8 -0
- data/lib/babushka/core_patches/numeric.rb +16 -0
- data/lib/babushka/core_patches/object.rb +27 -0
- data/lib/babushka/core_patches/string.rb +116 -0
- data/lib/babushka/core_patches/symbol.rb +12 -0
- data/lib/babushka/core_patches/try.rb +15 -0
- data/lib/babushka/core_patches/uri.rb +24 -0
- data/lib/babushka/dep.rb +470 -0
- data/lib/babushka/dep_context.rb +18 -0
- data/lib/babushka/dep_definer.rb +115 -0
- data/lib/babushka/dep_pool.rb +49 -0
- data/lib/babushka/dep_runner.rb +85 -0
- data/lib/babushka/dsl.rb +26 -0
- data/lib/babushka/git_repo.rb +185 -0
- data/lib/babushka/helpers/git_helpers.rb +32 -0
- data/lib/babushka/helpers/log_helpers.rb +176 -0
- data/lib/babushka/helpers/path_helpers.rb +34 -0
- data/lib/babushka/helpers/run_helpers.rb +145 -0
- data/lib/babushka/helpers/shell_helpers.rb +229 -0
- data/lib/babushka/helpers/suggest_helpers.rb +16 -0
- data/lib/babushka/helpers/uri_helpers.rb +36 -0
- data/lib/babushka/ip.rb +160 -0
- data/lib/babushka/lambda_chooser.rb +40 -0
- data/lib/babushka/levenshtein.rb +125 -0
- data/lib/babushka/meta_dep.rb +65 -0
- data/lib/babushka/meta_dep_context.rb +15 -0
- data/lib/babushka/parameter.rb +143 -0
- data/lib/babushka/pkg_helper.rb +81 -0
- data/lib/babushka/pkg_helpers/apt_helper.rb +61 -0
- data/lib/babushka/pkg_helpers/base_helper.rb +19 -0
- data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +48 -0
- data/lib/babushka/pkg_helpers/binports_helper.rb +34 -0
- data/lib/babushka/pkg_helpers/brew_helper.rb +110 -0
- data/lib/babushka/pkg_helpers/gem_helper.rb +120 -0
- data/lib/babushka/pkg_helpers/macports_helper.rb +22 -0
- data/lib/babushka/pkg_helpers/npm_helper.rb +45 -0
- data/lib/babushka/pkg_helpers/pacman_helper.rb +27 -0
- data/lib/babushka/pkg_helpers/pip_helper.rb +45 -0
- data/lib/babushka/pkg_helpers/src_helper.rb +16 -0
- data/lib/babushka/pkg_helpers/yum_helper.rb +25 -0
- data/lib/babushka/popen.rb +40 -0
- data/lib/babushka/prompt.rb +176 -0
- data/lib/babushka/renderable.rb +67 -0
- data/lib/babushka/resource.rb +215 -0
- data/lib/babushka/run_reporter.rb +60 -0
- data/lib/babushka/shell.rb +108 -0
- data/lib/babushka/source.rb +216 -0
- data/lib/babushka/source_pool.rb +146 -0
- data/lib/babushka/system_definitions.rb +97 -0
- data/lib/babushka/system_profile.rb +210 -0
- data/lib/babushka/task.rb +142 -0
- data/lib/babushka/vars.rb +108 -0
- data/lib/babushka/version_of.rb +65 -0
- data/lib/babushka/version_str.rb +57 -0
- data/lib/babushka/xml_string.rb +28 -0
- data/lib/components.rb +82 -0
- data/lib/fancypath/fancypath.rb +200 -0
- data/lib/inkan/inkan.rb +76 -0
- data/spec/acceptance/acceptance.rb +43 -0
- data/spec/acceptance_helper.rb +113 -0
- data/spec/archives/Blah.app.zip +0 -0
- data/spec/archives/archive.tar +0 -0
- data/spec/archives/archive.tar.bz2 +0 -0
- data/spec/archives/archive.tar.gz +0 -0
- data/spec/archives/archive.tbz2 +0 -0
- data/spec/archives/archive.tgz +0 -0
- data/spec/archives/archive.zip +0 -0
- data/spec/archives/content.txt +5 -0
- data/spec/archives/invalid_archive +5 -0
- data/spec/archives/nested archive/content.txt +5 -0
- data/spec/archives/nested_archive.tar +0 -0
- data/spec/archives/really_a_gzip.zip +0 -0
- data/spec/archives/test-0.3.1.tgz +0 -0
- data/spec/archives/tgz_archive +0 -0
- data/spec/archives/zip_without_extension +0 -0
- data/spec/babushka/accepts_for_spec.rb +174 -0
- data/spec/babushka/accepts_for_support.rb +72 -0
- data/spec/babushka/cmdline/console_spec.rb +11 -0
- data/spec/babushka/cmdline/help_spec.rb +61 -0
- data/spec/babushka/cmdline/version_spec.rb +10 -0
- data/spec/babushka/core_patches_spec.rb +171 -0
- data/spec/babushka/dep_context_spec.rb +58 -0
- data/spec/babushka/dep_definer_spec.rb +152 -0
- data/spec/babushka/dep_definer_support.rb +36 -0
- data/spec/babushka/dep_spec.rb +567 -0
- data/spec/babushka/dep_support.rb +29 -0
- data/spec/babushka/deps_spec.rb +113 -0
- data/spec/babushka/gem_helper_spec.rb +90 -0
- data/spec/babushka/git_repo_spec.rb +396 -0
- data/spec/babushka/ip_spec.rb +131 -0
- data/spec/babushka/lambda_chooser_spec.rb +115 -0
- data/spec/babushka/meta_dep_definer_spec.rb +127 -0
- data/spec/babushka/meta_dep_wrapper_spec.rb +32 -0
- data/spec/babushka/parameter_spec.rb +135 -0
- data/spec/babushka/path_helpers_spec.rb +102 -0
- data/spec/babushka/prompt_spec.rb +188 -0
- data/spec/babushka/renderable_spec.rb +100 -0
- data/spec/babushka/resource_spec.rb +141 -0
- data/spec/babushka/run_helpers_spec.rb +26 -0
- data/spec/babushka/shell_helpers_spec.rb +244 -0
- data/spec/babushka/shell_spec.rb +19 -0
- data/spec/babushka/source_pool_spec.rb +320 -0
- data/spec/babushka/source_pool_support.rb +31 -0
- data/spec/babushka/source_spec.rb +382 -0
- data/spec/babushka/source_support.rb +17 -0
- data/spec/babushka/system_profile_spec.rb +61 -0
- data/spec/babushka/task_spec.rb +141 -0
- data/spec/babushka/uri_spec.rb +13 -0
- data/spec/babushka/vars_spec.rb +59 -0
- data/spec/babushka/version_of_spec.rb +110 -0
- data/spec/babushka/version_str_spec.rb +130 -0
- data/spec/babushka/version_str_support.rb +37 -0
- data/spec/babushka/xml_string_spec.rb +98 -0
- data/spec/deps/bad/broken.rb +7 -0
- data/spec/deps/bad/working.rb +3 -0
- data/spec/deps/good/meta.rb +14 -0
- data/spec/deps/good/test.rb +11 -0
- data/spec/deps/outer/deps.rb +19 -0
- data/spec/deps/outer/more deps.rb +11 -0
- data/spec/deps/params/params.rb +10 -0
- data/spec/fancypath/fancypath_spec.rb +272 -0
- data/spec/fancypath_support.rb +10 -0
- data/spec/inkan/inkan_spec.rb +217 -0
- data/spec/renderable/different_example.conf.erb +4 -0
- data/spec/renderable/example.conf.erb +3 -0
- data/spec/renderable/example.sh +6 -0
- data/spec/renderable/with_binding.conf.erb +4 -0
- data/spec/renderable/xml_example.conf.erb +8 -0
- data/spec/repos/remote.git.tgz +0 -0
- data/spec/spec_helper.rb +87 -0
- metadata +238 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
dep 'python-software-properties.managed' do
|
|
2
|
+
provides 'add-apt-repository'
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
meta :ppa do
|
|
6
|
+
accepts_value_for :adds
|
|
7
|
+
template {
|
|
8
|
+
requires 'python-software-properties.managed'
|
|
9
|
+
met? {
|
|
10
|
+
Dir.glob("/etc/apt/sources.list.d/*").any? {|f|
|
|
11
|
+
f.p.read[Regexp.new('https?://' + adds.gsub(':', '.*') + '/ubuntu ')]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
before {
|
|
15
|
+
adds[/^\w+\:\w+/] or log_error("'#{adds}' doesn't look like 'ppa:something'.")
|
|
16
|
+
}
|
|
17
|
+
meet {
|
|
18
|
+
sudo "sudo add-apt-repository #{adds}"
|
|
19
|
+
}
|
|
20
|
+
after {
|
|
21
|
+
Babushka::Base.host.pkg_helper.update_pkg_lists "Updating apt lists to load #{adds}."
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
meta :src do
|
|
2
|
+
accepts_list_for :source
|
|
3
|
+
accepts_list_for :extra_source
|
|
4
|
+
accepts_list_for :provides, :basename
|
|
5
|
+
accepts_value_for :prefix, '/usr/local'
|
|
6
|
+
|
|
7
|
+
accepts_block_for(:preconfigure) {
|
|
8
|
+
if './configure'.p.exists?
|
|
9
|
+
true # No preconfigure needed
|
|
10
|
+
elsif !'./configure.in'.p.exists? && !'./configure.ac'.p.exists?
|
|
11
|
+
true # Not pre-configurable
|
|
12
|
+
else
|
|
13
|
+
log_shell "autoconf", "autoconf"
|
|
14
|
+
end
|
|
15
|
+
}
|
|
16
|
+
accepts_block_for(:configure) { log_shell "configure", default_configure_command }
|
|
17
|
+
accepts_list_for :configure_env
|
|
18
|
+
accepts_list_for :configure_args
|
|
19
|
+
|
|
20
|
+
accepts_block_for(:build) { log_shell "build", "make" }
|
|
21
|
+
accepts_block_for(:install) { Babushka::SrcHelper.install_src! 'make install' }
|
|
22
|
+
accepts_block_for(:postinstall)
|
|
23
|
+
|
|
24
|
+
accepts_block_for(:process_source) {
|
|
25
|
+
call_task(:preconfigure) and
|
|
26
|
+
call_task(:configure) and
|
|
27
|
+
call_task(:build) and
|
|
28
|
+
call_task(:install) and
|
|
29
|
+
call_task(:postinstall)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
def default_configure_command
|
|
33
|
+
"#{configure_env.map(&:to_s).join} ./configure --prefix=#{prefix} #{configure_args.map(&:to_s).join(' ')}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
template {
|
|
37
|
+
requires 'build tools', 'curl.managed'
|
|
38
|
+
prepare { setup_source_uris }
|
|
39
|
+
met? { in_path?(provides) }
|
|
40
|
+
meet { process_sources { call_task :process_source } }
|
|
41
|
+
}
|
|
42
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
meta :tmbundle, :for => :osx do
|
|
2
|
+
accepts_value_for :source
|
|
3
|
+
|
|
4
|
+
def path
|
|
5
|
+
'~/Library/Application Support/TextMate/Bundles' / name
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
template {
|
|
9
|
+
requires 'benhoskings:TextMate.app'
|
|
10
|
+
met? { path.dir? }
|
|
11
|
+
before { shell "mkdir -p '#{path.parent}'" }
|
|
12
|
+
meet { git source, :to => path }
|
|
13
|
+
after { log_shell "Telling TextMate to reload bundles", %Q{osascript -e 'tell app "TextMate" to reload bundles'} }
|
|
14
|
+
}
|
|
15
|
+
end
|
data/lib/babushka.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
VERSION = '0.10.6'
|
|
3
|
+
WorkingPrefix = '~/.babushka'
|
|
4
|
+
SourcePrefix = '~/.babushka/sources'
|
|
5
|
+
BuildPrefix = '~/.babushka/build'
|
|
6
|
+
DownloadPrefix = '~/.babushka/downloads'
|
|
7
|
+
LogPrefix = '~/.babushka/logs'
|
|
8
|
+
VarsPrefix = '~/.babushka/vars'
|
|
9
|
+
ReportPrefix = '~/.babushka/runs'
|
|
10
|
+
|
|
11
|
+
module Path
|
|
12
|
+
def self.binary() File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__ end
|
|
13
|
+
def self.bin() File.dirname(binary) end
|
|
14
|
+
# this is not correct in gem version
|
|
15
|
+
def self.path() File.dirname(bin) end
|
|
16
|
+
def self.lib() File.join(path, 'lib') end
|
|
17
|
+
def self.run_from_path?() ENV['PATH'].split(':').include? File.dirname($0) end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# First, load the component lists.
|
|
22
|
+
require File.join(Babushka::Path.path, 'lib', 'components')
|
|
23
|
+
|
|
24
|
+
# Load external components that babushka depends on.
|
|
25
|
+
Babushka::ExternalComponents.each {|c| require File.join(Babushka::Path.path, 'lib', c) }
|
|
26
|
+
|
|
27
|
+
# Next, load babushka itself.
|
|
28
|
+
Babushka::Components.each {|c| require File.join(Babushka::Path.path, 'lib/babushka', c) }
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
module AcceptsBlockFor
|
|
3
|
+
def self.included base
|
|
4
|
+
base.send :extend, ClassMethods
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def default_blocks
|
|
9
|
+
merged_default_blocks_for self
|
|
10
|
+
end
|
|
11
|
+
def merged_default_blocks_for klass
|
|
12
|
+
parent_values = klass == DepDefiner ? {} : merged_default_blocks_for(klass.superclass)
|
|
13
|
+
parent_values.merge(default_blocks_for(klass))
|
|
14
|
+
end
|
|
15
|
+
def default_blocks_for klass
|
|
16
|
+
(@@default_blocks ||= Hashish.hash)[klass]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def accepted_blocks
|
|
20
|
+
default_blocks.keys
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def accepts_block_for method_name, &default_block
|
|
24
|
+
default_blocks_for(self)[method_name] = default_block
|
|
25
|
+
class_eval %Q{
|
|
26
|
+
def #{method_name} *args, &block
|
|
27
|
+
payload[#{method_name.inspect}] ||= {}
|
|
28
|
+
if block.nil?
|
|
29
|
+
block_for #{method_name.inspect}
|
|
30
|
+
else
|
|
31
|
+
store_block_for #{method_name.inspect}, args, block
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def has_block? block_name
|
|
39
|
+
payload[block_name] ||= {}
|
|
40
|
+
!!specific_block_for(block_name)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def default_block_for block_name
|
|
44
|
+
differentiator = Base.host.differentiator_for payload[block_name].keys
|
|
45
|
+
L{
|
|
46
|
+
debug "#{block_name} not defined#{" for #{differentiator}" unless differentiator.nil?}."
|
|
47
|
+
true
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def default_blocks
|
|
52
|
+
self.class.default_blocks
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def store_block_for method_name, args, block
|
|
56
|
+
raise "#{method_name} only accepts args like :on => :linux (as well as a block arg)." unless args.empty? || args.first.is_a?(Hash)
|
|
57
|
+
|
|
58
|
+
payload[method_name] ||= {}
|
|
59
|
+
chosen_on = (args.first || {})[:on] || @current_platform || :all
|
|
60
|
+
payload[method_name][chosen_on] = block
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def block_for method_name
|
|
64
|
+
specific_block_for(method_name) or default_block_for(method_name)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def specific_block_for method_name
|
|
68
|
+
payload[method_name][(Base.host.match_list & payload[method_name].keys).first] ||
|
|
69
|
+
default_blocks[method_name]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
module AcceptsListFor
|
|
3
|
+
def self.included base
|
|
4
|
+
base.send :extend, ClassMethods
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def accepts_list_for method_name, *args
|
|
9
|
+
opts = {:type => 'list'}.merge args.extract_options!
|
|
10
|
+
default = args.shift
|
|
11
|
+
|
|
12
|
+
file, line = caller.first.split(':', 2)
|
|
13
|
+
line = line.to_i
|
|
14
|
+
|
|
15
|
+
module_eval <<-LOL, file, line
|
|
16
|
+
def #{method_name} *args, &block
|
|
17
|
+
if !args.empty? && !block.nil?
|
|
18
|
+
raise ArgumentError, "You can supply arguments or a block, but not both."
|
|
19
|
+
elsif args.empty? && block.nil?
|
|
20
|
+
#{opts[:type]}_for #{method_name.inspect}, #{default.inspect}
|
|
21
|
+
else
|
|
22
|
+
store_#{opts[:type]}_for #{method_name.inspect}, block || [*args].flatten, #{opts[:choose_with].inspect}
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
LOL
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def store_list_for method_name, data, choose_with
|
|
31
|
+
if data.respond_to? :call
|
|
32
|
+
store_list_for method_name, LambdaChooser.new(self, *chooser_choices, &data).choose(chooser, choose_with), choose_with
|
|
33
|
+
else
|
|
34
|
+
(payload[method_name] ||= []).concat(data || [])
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def list_for method_name, default
|
|
39
|
+
if payload.has_key? method_name
|
|
40
|
+
payload[method_name].map {|i| i.respond_to?(:call) ? i.call : i }.compact
|
|
41
|
+
else
|
|
42
|
+
# Splatting on expressions instead of just a single token seems
|
|
43
|
+
# to break the result in rubinius. https://gist.github.com/1173301
|
|
44
|
+
values = default.is_a?(Symbol) ? send(default) : (default || [])
|
|
45
|
+
[*values]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
module AcceptsValueFor
|
|
3
|
+
def self.included base
|
|
4
|
+
base.send :extend, ClassMethods
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def accepts_value_for method_name, *args
|
|
9
|
+
opts = args.extract_options!
|
|
10
|
+
accepts_list_for method_name, *args.push(opts.merge(:type => 'value'))
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def store_value_for method_name, data, choose_with
|
|
15
|
+
raise "Multiple values for #{method_name}" if data.respond_to?(:length) && data.length > 1
|
|
16
|
+
payload.delete(method_name) # otherwise new values would be #concat'ed and ignored.
|
|
17
|
+
store_list_for method_name, data, choose_with
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def value_for method_name, default
|
|
21
|
+
list_for(method_name, default).first
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class Base
|
|
3
|
+
class << self
|
|
4
|
+
|
|
5
|
+
# +task+ represents the overall job that is being run, and the parts that
|
|
6
|
+
# are external to running the corresponding dep tree itself - logging, and
|
|
7
|
+
# var loading and saving in particular.
|
|
8
|
+
def task
|
|
9
|
+
Task.instance
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# +cmdline+ is an instance of +Cmdline::Parser+ that represents the arguments
|
|
13
|
+
# that were passed via the commandline. It handles parsing those arguments,
|
|
14
|
+
# and choosing the task to perform based on the 'verb' supplied - e.g. 'meet',
|
|
15
|
+
# 'list', etc.
|
|
16
|
+
def cmdline
|
|
17
|
+
@cmdline ||= Cmdline::Parser.for(ARGV)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# +host+ is an instance of Babushka::SystemProfile for the system the command
|
|
21
|
+
# was invoked on.
|
|
22
|
+
# If the current system isn't supported, SystemProfile.for_host will return
|
|
23
|
+
# +nil+, and Base.run will fail early. If the system is known but the
|
|
24
|
+
# flavour isn't (e.g. an unknown Linux variant), a generic SystemProfile
|
|
25
|
+
# will be used, which should work for most operations but will fail on deps
|
|
26
|
+
# that attempt to use the package manager, etc.
|
|
27
|
+
def host
|
|
28
|
+
@host ||= Babushka::SystemProfile.for_host
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# +sources+ is an instance of Babushka::SourcePool, contains all the
|
|
32
|
+
# sources that babushka can currently load deps from. This means all the sources
|
|
33
|
+
# found in ~/.babushka/sources, plus the default sources:
|
|
34
|
+
# - anonymous (no source file; i.e. deps defined in an +irb+ session,
|
|
35
|
+
# or similar)
|
|
36
|
+
# - core (the builtin deps that babushka uses to install itself)
|
|
37
|
+
# - current dir (the contents of ./babushka-deps)
|
|
38
|
+
# - personal (the contents of ~/.babushka/deps)
|
|
39
|
+
def sources
|
|
40
|
+
SourcePool.instance
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def threads
|
|
44
|
+
@threads ||= []
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def in_thread &block
|
|
48
|
+
threads.push Thread.new(&block)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# The top-level entry point for babushka runs invoked at the command line.
|
|
52
|
+
# When the `babushka` command is run, bin/babushka.rb first triggers a load
|
|
53
|
+
# via lib/babushka.rb, and then calls this method.
|
|
54
|
+
def run
|
|
55
|
+
cmdline.run
|
|
56
|
+
ensure
|
|
57
|
+
threads.each(&:join)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def exit_on_interrupt!
|
|
61
|
+
if $stdin.tty?
|
|
62
|
+
stty_save = `stty -g`.chomp
|
|
63
|
+
trap("INT") {
|
|
64
|
+
system "stty", stty_save
|
|
65
|
+
unless Base.task.callstack.empty?
|
|
66
|
+
puts "\n#{Logging.closing_log_message("#{Base.task.callstack.first.contextual_name} (cancelled)", false, :closing_status => true)}"
|
|
67
|
+
end
|
|
68
|
+
exit false
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def program_name
|
|
74
|
+
@program_name ||= ENV['PATH'].split(':').include?(File.dirname($0)) ? File.basename($0) : $0
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class BugReporter
|
|
3
|
+
extend LogHelpers
|
|
4
|
+
extend ShellHelpers
|
|
5
|
+
|
|
6
|
+
# This method creates a bug report for +dep+, by reading the debug log and
|
|
7
|
+
# vars associated with it and posting them as a gist. If the github user is
|
|
8
|
+
# set in the git config, it's marked as from that user, otherwise it's
|
|
9
|
+
# anonymous.
|
|
10
|
+
def self.report dep
|
|
11
|
+
Prompt.confirm "I can file a bug report for that now, if you like.", :default => 'n', :otherwise => "OK, you're on your own :)" do
|
|
12
|
+
post_report dep,
|
|
13
|
+
(which('git') && shell('git config github.user')) || 'anonymous',
|
|
14
|
+
Base.task.var_path_for(dep).read,
|
|
15
|
+
Base.task.log_path_for(dep).read
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
# gist.github.com API example at http://gist.github.com/4277
|
|
23
|
+
def self.post_report dep, user, vars, log
|
|
24
|
+
require 'net/http'
|
|
25
|
+
require 'uri'
|
|
26
|
+
|
|
27
|
+
Net::HTTP.post_form(
|
|
28
|
+
URI.parse('http://gist.github.com/api/v1/xml/new'), {
|
|
29
|
+
"files[from]" => user,
|
|
30
|
+
"files[vars.yml]" => vars,
|
|
31
|
+
"files[#{dep.contextual_name}.log]" => log.decolorize
|
|
32
|
+
}
|
|
33
|
+
).tap {|response|
|
|
34
|
+
report_report_result dep, response
|
|
35
|
+
}.is_a? Net::HTTPSuccess
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.report_report_result dep, response
|
|
39
|
+
if response.is_a? Net::HTTPSuccess
|
|
40
|
+
gist_id = response.body.scan(/<repo>(\d+)<\/repo>/).flatten.first
|
|
41
|
+
if gist_id.nil?
|
|
42
|
+
log "Done, but the report's URL couldn't be parsed. Here's some info:"
|
|
43
|
+
log response.body
|
|
44
|
+
else
|
|
45
|
+
log "You can view the report at http://gist.github.com/#{gist_id} - thanks :)"
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
log "Deary me, the bug report couldn't be submitted! Would you mind emailing these two files:"
|
|
49
|
+
log ' ' + Base.task.var_path_for(dep)
|
|
50
|
+
log ' ' + Base.task.log_path_for(dep)
|
|
51
|
+
log "to ben@hoskings.net? Thanks."
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
module Babushka
|
|
4
|
+
module Cmdline
|
|
5
|
+
extend LogHelpers
|
|
6
|
+
|
|
7
|
+
handle('global', "Options that are valid for any handler") {
|
|
8
|
+
opt '-v', '--version', "Print the current version"
|
|
9
|
+
opt '-h', '--help', "Show this information"
|
|
10
|
+
opt '-d', '--debug', "Show more verbose logging, and realtime shell command output"
|
|
11
|
+
opt '--[no-]color',
|
|
12
|
+
'--[no-]colour', "Disable color in the output"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
handle('help', "Print usage information").run {|cmd|
|
|
16
|
+
Helpers.print_version :full => true
|
|
17
|
+
if cmd.argv.empty?
|
|
18
|
+
Helpers.print_usage
|
|
19
|
+
Helpers.print_handlers
|
|
20
|
+
Helpers.print_notes
|
|
21
|
+
elsif (handler = Handler.for(cmd.argv.first)).nil?
|
|
22
|
+
Helpers.log "#{cmd.argv.first.capitalize}? I have honestly never heard of that."
|
|
23
|
+
else
|
|
24
|
+
Helpers.log "\n#{handler.name} - #{handler.description}"
|
|
25
|
+
cmd.parse(&handler.opt_definer)
|
|
26
|
+
cmd.print_usage
|
|
27
|
+
end
|
|
28
|
+
Helpers.log "\n"
|
|
29
|
+
true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
handle('version', "Print the current version").run {
|
|
33
|
+
Helpers.print_version
|
|
34
|
+
true
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
handle('list', "List the available deps") {
|
|
38
|
+
opt '-t', '--templates', "List templates instead of deps"
|
|
39
|
+
}.run {|cmd|
|
|
40
|
+
Base.sources.local_only {
|
|
41
|
+
Helpers.generate_list_for(cmd.opts[:templates] ? :templates : :deps, cmd.argv.first)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
handle('meet', 'The main one: run a dep and all its dependencies.') {
|
|
46
|
+
opt '-n', '--dry-run', "Discover the curent state without making any changes"
|
|
47
|
+
opt '-y', '--defaults', "Assume the default value for all vars without prompting, where possible"
|
|
48
|
+
opt '--show-args', "Show the arguments being passed between deps as they're run"
|
|
49
|
+
opt '--track-blocks', "Track deps' blocks in TextMate as they're run"
|
|
50
|
+
}.run {|cmd|
|
|
51
|
+
# TODO: spec var parsing
|
|
52
|
+
dep_names, vars = cmd.argv.partition {|arg| arg['='].nil? }
|
|
53
|
+
if !(bad_var = vars.detect {|var| var[/^\w+=/].nil? }).nil?
|
|
54
|
+
fail_with "'#{bad_var}' looks like a var but it doesn't make sense."
|
|
55
|
+
elsif dep_names.empty?
|
|
56
|
+
fail_with "Nothing to do."
|
|
57
|
+
elsif cmd.opts[:track_blocks] && !which('mate')
|
|
58
|
+
fail_with "The --track-blocks option requires TextMate, and the `mate` helper.\nOn a Mac, you can install them like so:\n babushka benhoskings:textmate"
|
|
59
|
+
else
|
|
60
|
+
Base.task.process dep_names, vars.map {|i|
|
|
61
|
+
i.split('=', 2)
|
|
62
|
+
}.inject({}) {|hsh,i|
|
|
63
|
+
hsh[i.first] = i.last
|
|
64
|
+
hsh
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
handle('sources', "Manage dep sources") {
|
|
70
|
+
opt '-a', '--add NAME URI', "Add the source at URI as NAME"
|
|
71
|
+
opt '-u', '--update', "Update all known sources"
|
|
72
|
+
opt '-l', '--list', "List dep sources"
|
|
73
|
+
}.run {|cmd|
|
|
74
|
+
if cmd.opts.slice(:add, :update, :list).length != 1
|
|
75
|
+
fail_with "'sources' requires a single option."
|
|
76
|
+
elsif cmd.opts.has_key?(:add)
|
|
77
|
+
begin
|
|
78
|
+
Source.new(cmd.argv.first, :name => cmd.opts[:add]).add!
|
|
79
|
+
rescue SourceError => e
|
|
80
|
+
log_error e.message
|
|
81
|
+
end
|
|
82
|
+
elsif cmd.opts.has_key?(:update)
|
|
83
|
+
Base.sources.update!
|
|
84
|
+
elsif cmd.opts.has_key?(:list)
|
|
85
|
+
Base.sources.list!
|
|
86
|
+
end
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
handle('console', "Start an interactive (irb-based) babushka session").run {
|
|
90
|
+
exec "irb -r'#{Path.lib / 'babushka'}' --simple-prompt"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
handle('search', "Search for deps in the community database").run {|cmd|
|
|
94
|
+
if cmd.argv.length != 1
|
|
95
|
+
fail_with "'search' requires a single argument."
|
|
96
|
+
else
|
|
97
|
+
require 'net/http'
|
|
98
|
+
require 'yaml'
|
|
99
|
+
|
|
100
|
+
search_term = cmd.argv.first
|
|
101
|
+
results = Helpers.search_results_for(search_term)
|
|
102
|
+
|
|
103
|
+
if results.empty?
|
|
104
|
+
log "Never seen a dep with '#{search_term}' in its name."
|
|
105
|
+
else
|
|
106
|
+
Helpers.print_search_results search_term, results
|
|
107
|
+
true
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
handle('edit', "Load the file containing the specified dep in $EDITOR").run {|cmd|
|
|
113
|
+
if cmd.argv.length != 1
|
|
114
|
+
fail_with "'edit' requires a single argument."
|
|
115
|
+
elsif (dep = Dep.find_or_suggest(cmd.argv.first)).nil?
|
|
116
|
+
fail_with "Can't find '#{cmd.argv.first}' to edit."
|
|
117
|
+
elsif dep.load_path.nil?
|
|
118
|
+
fail_with "Can't edit '#{dep.name}, since it wasn't loaded from a file."
|
|
119
|
+
else
|
|
120
|
+
file, line = dep.context.file_and_line
|
|
121
|
+
editor_var = ENV['BABUSHKA_EDITOR'] || ENV['VISUAL'] || ENV['EDITOR'] || which('mate') || which('vim') || which('vi')
|
|
122
|
+
case editor_var
|
|
123
|
+
when /^mate/
|
|
124
|
+
exec "mate -l#{line} '#{file}'"
|
|
125
|
+
when /^vim?/, /^nano/, /^pico/, /^emacs/
|
|
126
|
+
exec "#{editor_var} +#{line} '#{file}'"
|
|
127
|
+
else
|
|
128
|
+
exec "#{editor_var} '#{file}'"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
end
|