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