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,120 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class GemHelper < PkgHelper
|
|
3
|
+
class << self
|
|
4
|
+
def pkg_type; :gem end
|
|
5
|
+
def pkg_cmd; 'gem' end
|
|
6
|
+
def manager_key; :gem end
|
|
7
|
+
def manager_dep; 'rubygems' end
|
|
8
|
+
|
|
9
|
+
def _install! pkgs, opts
|
|
10
|
+
pkgs.each {|pkg|
|
|
11
|
+
log_shell "Installing #{pkg} via #{manager_key}",
|
|
12
|
+
"#{pkg_cmd} install #{cmdline_spec_for pkg} #{opts}",
|
|
13
|
+
:sudo => should_sudo?
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def gem_path_for gem_name, version = nil
|
|
18
|
+
unless (detected_version = has?(VersionOf(gem_name, version), :log => false)).nil?
|
|
19
|
+
gem_root / VersionOf(gem_name, detected_version)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def bin_path
|
|
24
|
+
# The directory in which the binaries from gems are found. This is
|
|
25
|
+
# sometimes different to where `gem` itself is running from.
|
|
26
|
+
env_info.val_for('EXECUTABLE DIRECTORY').p
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def gem_root
|
|
30
|
+
gemdir / 'gems'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def gemspec_dir
|
|
34
|
+
gemdir / 'specifications'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def gemdir
|
|
38
|
+
env_info.val_for('INSTALLATION DIRECTORY')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ruby_path
|
|
42
|
+
env_info.val_for('RUBY EXECUTABLE').p
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def ruby_wrapper_path
|
|
46
|
+
if ruby_path.to_s['/.rvm/rubies/'].nil?
|
|
47
|
+
ruby_path
|
|
48
|
+
else
|
|
49
|
+
ruby_path.sub(
|
|
50
|
+
# /Users/ben/.rvm/rubies/ruby-1.9.2-p0/bin/ruby
|
|
51
|
+
/^(.*)\/\.rvm\/rubies\/([^\/]+)\/bin\/ruby/
|
|
52
|
+
) {
|
|
53
|
+
# /Users/ben/.rvm/wrappers/ruby-1.9.2-p0/ruby
|
|
54
|
+
"#{$1}/.rvm/wrappers/#{$2}/ruby"
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def ruby_arch
|
|
60
|
+
if RUBY_PLATFORM =~ /universal/
|
|
61
|
+
"universal"
|
|
62
|
+
elsif RUBY_PLATFORM == "java"
|
|
63
|
+
"java"
|
|
64
|
+
elsif RUBY_PLATFORM =~ /darwin/
|
|
65
|
+
# e.g. "/opt/ruby-enterprise/bin/ruby: Mach-O 64-bit executable x86_64"
|
|
66
|
+
shell("file -L '#{ruby_path}'").sub(/.* /, '')
|
|
67
|
+
else
|
|
68
|
+
Base.host.cpu_type
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def ruby_binary_slug
|
|
73
|
+
[
|
|
74
|
+
(defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'),
|
|
75
|
+
RUBY_VERSION,
|
|
76
|
+
ruby_arch,
|
|
77
|
+
(RUBY_PLATFORM['darwin'] ? 'macosx' : RUBY_PLATFORM.sub(/^.*?-/, ''))
|
|
78
|
+
].join('-')
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def slug_for ruby
|
|
82
|
+
shell %Q{#{ruby} -e "require '#{Babushka::Path.lib / 'babushka'}'; puts Babushka::GemHelper.ruby_binary_slug"}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def should_sudo?
|
|
86
|
+
super || (gem_root.exists? && !gem_root.writable?)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def version
|
|
90
|
+
env_info.val_for('RUBYGEMS VERSION').to_version
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def _has? pkg
|
|
97
|
+
versions_of(pkg).sort.reverse.detect {|version| pkg.matches? version }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def versions_of pkg
|
|
101
|
+
pkg_name = pkg.respond_to?(:name) ? pkg.name : pkg
|
|
102
|
+
gemspecs_for(pkg_name).select {|i|
|
|
103
|
+
i.p.read.val_for('s.name')[/^[\'\"\%qQ\{]*#{pkg_name}[\'\"\}]*$/]
|
|
104
|
+
}.map {|i|
|
|
105
|
+
File.basename(i).scan(/^#{pkg_name}-(.*).gemspec$/).flatten.first
|
|
106
|
+
}.map {|i|
|
|
107
|
+
i.to_version
|
|
108
|
+
}.sort
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def gemspecs_for pkg_name
|
|
112
|
+
gemspec_dir.glob("#{pkg_name}-*.gemspec")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def env_info
|
|
116
|
+
@_cached_env_info ||= shell('gem env')
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class MacportsHelper < PkgHelper
|
|
3
|
+
class << self
|
|
4
|
+
def existing_packages
|
|
5
|
+
Dir.glob(prefix / "var/macports/software/*").map {|i| File.basename i }
|
|
6
|
+
end
|
|
7
|
+
def pkg_type; :port end
|
|
8
|
+
def pkg_cmd; 'port' end
|
|
9
|
+
def manager_key; :macports end
|
|
10
|
+
|
|
11
|
+
def _install! pkgs, opts
|
|
12
|
+
log_shell "Fetching #{pkgs.join(', ')}", "#{pkg_cmd} fetch #{pkgs.join(' ')}", :sudo => should_sudo?
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
def _has? pkg
|
|
18
|
+
existing_packages.include? pkg.name.split(/\s+/, 2).first
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class NpmHelper < PkgHelper
|
|
3
|
+
class << self
|
|
4
|
+
def pkg_type; :npm end
|
|
5
|
+
def pkg_cmd; "#{pkg_binary} --color false" end
|
|
6
|
+
def pkg_binary; "npm" end
|
|
7
|
+
def manager_key; :npm end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def _install! pkgs, opts
|
|
12
|
+
pkgs.each {|pkg|
|
|
13
|
+
log_shell "Installing #{pkg} via #{manager_key}",
|
|
14
|
+
"#{pkg_cmd} install -g #{cmdline_spec_for pkg} #{opts}",
|
|
15
|
+
:sudo => should_sudo?
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def _has? pkg
|
|
20
|
+
# Some example output:
|
|
21
|
+
# socket.io@0.6.15 =rauchg active installed remote
|
|
22
|
+
shell("#{pkg_cmd} ls -g").split("\n").grep(
|
|
23
|
+
/^\W*#{Regexp.escape(pkg.name)}\@/
|
|
24
|
+
).any? {|match|
|
|
25
|
+
pkg.matches? match.scan(/\@(.*)$/).flatten.first
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def cmdline_spec_for pkg
|
|
30
|
+
if pkg.version.nil?
|
|
31
|
+
# e.g. 'socket.io'
|
|
32
|
+
"'#{pkg.name}'"
|
|
33
|
+
else
|
|
34
|
+
# e.g. 'socket.io@==0.12.0'
|
|
35
|
+
"'#{pkg.name}@#{pkg.version.operator}#{pkg.version.version}'"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def should_sudo?
|
|
40
|
+
!File.writable?(bin_path / pkg_binary)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class PacmanHelper < PkgHelper
|
|
3
|
+
class << self
|
|
4
|
+
def pkg_type; :package end # a description of the type of package, that makes sense in the context of, e.g. "the zsh deb"
|
|
5
|
+
def pkg_cmd; "#{pkg_binary}" end # The full command to run the package manager
|
|
6
|
+
def pkg_binary; "pacman" end # The name of the binary itself
|
|
7
|
+
def manager_key; :pacman end # How packages should be specified in deps, e.g. "via :apt, 'zsh'"
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# NOTE By default, Arch has sudo's `tty_tickets` option enabled. This will
|
|
12
|
+
# result in sudo asking for your password every single time it's run from
|
|
13
|
+
# Babushka. If you find this annoying, please refer to
|
|
14
|
+
# https://wiki.archlinux.org/index.php/Sudo#Disable_per-terminal_sudo
|
|
15
|
+
#
|
|
16
|
+
# tl;dr - Add the following line to /etc/sudoers:
|
|
17
|
+
# Defaults !tty_tickets
|
|
18
|
+
def _install! pkgs, opts
|
|
19
|
+
log_shell "Downloading", "#{pkg_cmd} -S --noconfirm #{pkgs.join(' ')}", :sudo => should_sudo?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def _has? pkg_name
|
|
23
|
+
raw_shell("pacman -Q #{pkg_name}").stderr !~ /not found$/
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class PipHelper < PkgHelper
|
|
3
|
+
class << self
|
|
4
|
+
def pkg_type; :pip end
|
|
5
|
+
def pkg_cmd; pkg_binary end
|
|
6
|
+
def pkg_binary; "pip" end
|
|
7
|
+
def manager_key; :pip end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def _install! pkgs, opts
|
|
12
|
+
pkgs.each {|pkg|
|
|
13
|
+
log_shell "Installing #{pkg} via #{manager_key}",
|
|
14
|
+
"#{pkg_cmd} install #{cmdline_spec_for pkg} #{opts}",
|
|
15
|
+
:sudo => should_sudo?
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def _has? pkg
|
|
20
|
+
# Some example output:
|
|
21
|
+
# gunicorn==0.12.0
|
|
22
|
+
raw_shell("pip freeze '#{pkg.name}'").stdout.split("\n").select {|line|
|
|
23
|
+
line[/^#{Regexp.escape(pkg.name)}\=\=/]
|
|
24
|
+
}.any? {|match|
|
|
25
|
+
pkg.matches? match.scan(/\=\=(.*)$/).flatten.first
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def cmdline_spec_for pkg
|
|
30
|
+
if pkg.version.nil?
|
|
31
|
+
# e.g. 'gunicorn'
|
|
32
|
+
"'#{pkg.name}'"
|
|
33
|
+
else
|
|
34
|
+
# e.g. 'gunicorn==0.12.0'
|
|
35
|
+
"'#{pkg.name}#{pkg.version.operator}#{pkg.version.version}'"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def should_sudo?
|
|
40
|
+
!File.writable?(bin_path / pkg_binary)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class SrcHelper < PkgHelper
|
|
3
|
+
class << self
|
|
4
|
+
def pkg_type; :src end
|
|
5
|
+
|
|
6
|
+
def install_src! cmd, opts = {}
|
|
7
|
+
log_shell "install", cmd, :sudo => (opts[:sudo] || should_sudo?)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def prefix
|
|
11
|
+
'/usr/local'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class YumHelper < PkgHelper
|
|
3
|
+
class << self
|
|
4
|
+
def pkg_type; :rpm end
|
|
5
|
+
def pkg_cmd; pkg_binary end
|
|
6
|
+
def pkg_binary; "yum" end
|
|
7
|
+
def manager_key; :yum end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def _has? pkg_name
|
|
12
|
+
# Some example output, with 'wget' installed:
|
|
13
|
+
# fedora-13: 'wget.x86_64 1.12-2.fc13 @fedora'
|
|
14
|
+
# centos-5.5: 'wget.x86_64 1.11.4-2.el5_4.1 installed'
|
|
15
|
+
raw_shell("#{pkg_binary} list -q '#{pkg_name}'").stdout.split("\n").select {|line|
|
|
16
|
+
line[/^#{Regexp.escape(pkg_name.to_s)}\.\w+\b/] # e.g. wget.x86_64
|
|
17
|
+
}.any? {|match|
|
|
18
|
+
final_word = match[/[^\s]+$/] || ''
|
|
19
|
+
(final_word == 'installed') || final_word.starts_with?('@')
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class Open3
|
|
3
|
+
def self.popen3 cmd, opts = {}, &block
|
|
4
|
+
pipes = { :in => IO::pipe, :out => IO::pipe, :err => IO::pipe }
|
|
5
|
+
near = { :in => pipes[:in][1], :out => pipes[:out][0], :err => pipes[:err][0] }
|
|
6
|
+
far = { :in => pipes[:in][0], :out => pipes[:out][1], :err => pipes[:err][1] }
|
|
7
|
+
|
|
8
|
+
pid = fork {
|
|
9
|
+
reopen_pipe_for :read, pipes[:in], STDIN
|
|
10
|
+
reopen_pipe_for :write, pipes[:out], STDOUT
|
|
11
|
+
reopen_pipe_for :write, pipes[:err], STDERR
|
|
12
|
+
|
|
13
|
+
Dir.chdir opts[:chdir] if opts[:chdir]
|
|
14
|
+
ENV.update opts[:env] if opts[:env]
|
|
15
|
+
|
|
16
|
+
exec(*cmd)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
far.values.each(&:close)
|
|
20
|
+
near.values.each {|p| p.sync = true }
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
yield near[:in], near[:out], near[:err]
|
|
24
|
+
Process.waitpid2(pid).last.exitstatus
|
|
25
|
+
ensure
|
|
26
|
+
near.values.each {|p| p.close unless p.closed? }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def self.reopen_pipe_for task, pipe, io
|
|
33
|
+
to_close = pipe[task == :read ? 1 : 0]
|
|
34
|
+
to_reopen = pipe[task == :read ? 0 : 1]
|
|
35
|
+
to_close.close
|
|
36
|
+
io.reopen to_reopen
|
|
37
|
+
to_reopen.close
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
|
|
3
|
+
class DefaultUnavailable < RuntimeError
|
|
4
|
+
def initialize message
|
|
5
|
+
super %{Not prompting for "#{message}" because we're running with '--defaults'.}
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class PromptUnavailable < RuntimeError
|
|
10
|
+
def initialize message
|
|
11
|
+
super %{Can't prompt for "#{message}" because STDIN isn't a terminal.}
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class Prompt
|
|
16
|
+
extend LogHelpers
|
|
17
|
+
|
|
18
|
+
module Helpers
|
|
19
|
+
def confirm message, opts = {}, &block
|
|
20
|
+
Prompt.confirm message, opts, &block
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
def confirm message, opts = {}, &block
|
|
26
|
+
prompter = (!opts[:always_ask] && respond_to?(:var)) ? :var : :get_value
|
|
27
|
+
answer = send(prompter, message,
|
|
28
|
+
:message => message,
|
|
29
|
+
:confirmation => true,
|
|
30
|
+
:default => (opts[:default] || 'y')
|
|
31
|
+
).starts_with?('y')
|
|
32
|
+
|
|
33
|
+
if block.nil?
|
|
34
|
+
answer
|
|
35
|
+
elsif answer
|
|
36
|
+
block.call
|
|
37
|
+
elsif opts[:otherwise]
|
|
38
|
+
log opts[:otherwise]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_ip message, opts = {}
|
|
43
|
+
get_value(message, opts.merge(
|
|
44
|
+
:retry => "That's not an IP, like '10.0.1.1'."
|
|
45
|
+
)) {|value|
|
|
46
|
+
IP.new(value).valid?
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def get_ip_range message, opts = {}
|
|
51
|
+
get_value(message, opts.merge(
|
|
52
|
+
:retry => "That's not an IP range, like '10.0.1.x'."
|
|
53
|
+
)) {|value|
|
|
54
|
+
IPRange.new(value).valid?
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_path message, opts = {}
|
|
59
|
+
get_value(message, opts.merge(
|
|
60
|
+
:retry => "Doesn't exist, or not a directory."
|
|
61
|
+
)) {|value|
|
|
62
|
+
(value || '').p.dir?
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def get_value message, opts = {}, &block
|
|
67
|
+
if opts[:choices] && opts[:choice_descriptions]
|
|
68
|
+
raise ArgumentError, "You can't use the :choices and :choice_descriptions options together."
|
|
69
|
+
elsif opts[:choice_descriptions]
|
|
70
|
+
opts[:choices] = opts[:choice_descriptions].keys
|
|
71
|
+
end
|
|
72
|
+
if opts[:choices] && opts[:choices].any? {|c| !c.is_a?(String) }
|
|
73
|
+
raise ArgumentError, "Choices must be passed as strings."
|
|
74
|
+
end
|
|
75
|
+
opts.defaults! :prompt => '? '
|
|
76
|
+
prompt_and_read_value prompt_message(message, opts), opts.merge(:ask => !Base.task.opt(:defaults)), &block
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def prompt_message message, opts
|
|
83
|
+
if opts[:choices] && opts[:choice_descriptions].nil?
|
|
84
|
+
"#{message.chomp '?'} (#{opts[:choices] * ','})"
|
|
85
|
+
else
|
|
86
|
+
message.chomp '?'
|
|
87
|
+
end + "#{" #{opts[:dynamic] ? '{' : '['}#{opts[:default]}#{opts[:dynamic] ? '}' : ']'}" if opts[:default]}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def log_choice_descriptions descriptions
|
|
91
|
+
unless descriptions.nil?
|
|
92
|
+
max_length = descriptions.keys.map(&:length).max
|
|
93
|
+
log "There are #{descriptions.length} choices:"
|
|
94
|
+
descriptions.each_pair {|choice,description|
|
|
95
|
+
log "#{choice.ljust(max_length)} - #{description}"
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def prompt_and_read_value message, opts, &block
|
|
101
|
+
if !opts[:default] && !opts[:ask]
|
|
102
|
+
raise DefaultUnavailable.new(message)
|
|
103
|
+
elsif opts[:ask] && !$stdin.tty?
|
|
104
|
+
raise PromptUnavailable.new(message)
|
|
105
|
+
else
|
|
106
|
+
log_choice_descriptions opts[:choice_descriptions]
|
|
107
|
+
log message, :newline => false
|
|
108
|
+
|
|
109
|
+
if opts[:default] && !opts[:ask]
|
|
110
|
+
puts '.'
|
|
111
|
+
opts[:default]
|
|
112
|
+
else
|
|
113
|
+
read_value_from_prompt message, opts, &block
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def read_value_from_prompt message, opts, &block
|
|
119
|
+
value = nil
|
|
120
|
+
|
|
121
|
+
value = read_from_prompt(opts[:prompt].end_with(' '), opts[:choices]).try(:chomp)
|
|
122
|
+
value = opts[:default].to_s if value.blank? && !(opts[:default] && opts[:default].to_s.empty?)
|
|
123
|
+
|
|
124
|
+
error = if opts[:choices] && !opts[:choices].include?(value)
|
|
125
|
+
"That's not a valid choice"
|
|
126
|
+
elsif block_given? && !yield(value)
|
|
127
|
+
opts[:retry] || "That wasn't valid"
|
|
128
|
+
elsif value.blank? && !(opts[:default] && opts[:default].empty?)
|
|
129
|
+
"That was blank"
|
|
130
|
+
elsif !opts[:confirmation] && value == 'y' && !confirm("Wait, do you mean the literal value 'y'?", :default => 'n', :always_ask => true)
|
|
131
|
+
"Thought so :) Hit enter for the [default]"
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if error
|
|
135
|
+
log "#{error.end_with('.')} #{message}", :newline => false
|
|
136
|
+
read_value_from_prompt message, opts, &block
|
|
137
|
+
else
|
|
138
|
+
value
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
begin
|
|
143
|
+
require 'readline'
|
|
144
|
+
def read_from_prompt prompt, choices = nil
|
|
145
|
+
using_libedit = !Readline.respond_to?(:vi_editing_mode)
|
|
146
|
+
Readline.completion_append_character = nil
|
|
147
|
+
|
|
148
|
+
Readline.completion_proc = if !choices.nil?
|
|
149
|
+
L{|str| choices.select {|i| i.starts_with? choice } }
|
|
150
|
+
else
|
|
151
|
+
L{|str|
|
|
152
|
+
Dir["#{str}*"].map {|path|
|
|
153
|
+
path.end_with(if File.directory?(path)
|
|
154
|
+
using_libedit ? '' : '/' # libedit adds its own trailing slash to dirs
|
|
155
|
+
else
|
|
156
|
+
' ' # Add a trailing space to files
|
|
157
|
+
end)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# This is required in addition to the call in bin/babushka.rb for
|
|
163
|
+
# interrupts to work during Readline calls.
|
|
164
|
+
Base.exit_on_interrupt!
|
|
165
|
+
|
|
166
|
+
Readline.readline(prompt, true).try(:strip)
|
|
167
|
+
end
|
|
168
|
+
rescue LoadError
|
|
169
|
+
def read_from_prompt prompt, choices = nil
|
|
170
|
+
print prompt
|
|
171
|
+
$stdin.gets.try(:strip)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|