rubycut-babushka 0.10.8 → 0.15.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +17 -15
  3. data/README.markdown +163 -41
  4. data/Rakefile +1 -1
  5. data/bin/babushka +1 -1
  6. data/deps/apt.rb +44 -0
  7. data/deps/babushka.rb +54 -42
  8. data/deps/deprecated.rb +16 -0
  9. data/deps/dev.rb +28 -3
  10. data/deps/git.rb +27 -12
  11. data/deps/homebrew.rb +2 -2
  12. data/deps/packages.rb +14 -15
  13. data/deps/pkg_managers.rb +21 -75
  14. data/deps/ruby.rb +5 -19
  15. data/deps/rubygems.rb +3 -3
  16. data/deps/system.rb +2 -2
  17. data/deps/templates/app.rb +60 -41
  18. data/deps/templates/bin.rb +16 -0
  19. data/deps/templates/installer.rb +9 -9
  20. data/deps/templates/lib.rb +17 -0
  21. data/deps/templates/managed.rb +1 -38
  22. data/deps/templates/src.rb +16 -8
  23. data/deps/templates/task.rb +11 -0
  24. data/deps/templates/tmbundle.rb +16 -2
  25. data/lib/babushka.rb +2 -3
  26. data/lib/babushka/accepts_block_for.rb +5 -3
  27. data/lib/babushka/asset.rb +172 -0
  28. data/lib/babushka/base.rb +37 -8
  29. data/lib/babushka/bug_reporter.rb +6 -6
  30. data/lib/babushka/cmdline.rb +11 -10
  31. data/lib/babushka/cmdline/handler.rb +7 -3
  32. data/lib/babushka/cmdline/helpers.rb +15 -23
  33. data/lib/babushka/cmdline/parser.rb +1 -1
  34. data/lib/babushka/core_patches/object.rb +1 -1
  35. data/lib/babushka/core_patches/string.rb +8 -3
  36. data/lib/babushka/current_ruby.rb +44 -0
  37. data/lib/babushka/dep.rb +111 -185
  38. data/lib/babushka/dep_context.rb +8 -3
  39. data/lib/babushka/dep_definer.rb +45 -15
  40. data/lib/babushka/dep_pool.rb +5 -8
  41. data/lib/babushka/{meta_dep.rb → dep_template.rb} +21 -2
  42. data/lib/babushka/dsl.rb +3 -0
  43. data/lib/babushka/git_repo.rb +143 -49
  44. data/lib/babushka/helpers/git_helpers.rb +7 -6
  45. data/lib/babushka/helpers/log_helpers.rb +51 -13
  46. data/lib/babushka/helpers/path_helpers.rb +5 -7
  47. data/lib/babushka/helpers/run_helpers.rb +15 -55
  48. data/lib/babushka/helpers/shell_helpers.rb +18 -26
  49. data/lib/babushka/helpers/uri_helpers.rb +9 -18
  50. data/lib/babushka/lambda_chooser.rb +20 -13
  51. data/lib/babushka/parameter.rb +20 -4
  52. data/lib/babushka/path_checker.rb +72 -0
  53. data/lib/babushka/pkg_helper.rb +38 -13
  54. data/lib/babushka/pkg_helpers/apt_helper.rb +15 -8
  55. data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +15 -14
  56. data/lib/babushka/pkg_helpers/binports_helper.rb +7 -7
  57. data/lib/babushka/pkg_helpers/brew_helper.rb +17 -25
  58. data/lib/babushka/pkg_helpers/gem_helper.rb +36 -27
  59. data/lib/babushka/pkg_helpers/npm_helper.rb +9 -9
  60. data/lib/babushka/pkg_helpers/pacman_helper.rb +5 -4
  61. data/lib/babushka/pkg_helpers/pip_helper.rb +14 -10
  62. data/lib/babushka/pkg_helpers/unknown_pkg_helper.rb +19 -0
  63. data/lib/babushka/pkg_helpers/yum_helper.rb +1 -1
  64. data/lib/babushka/popen.rb +13 -10
  65. data/lib/babushka/prompt.rb +14 -1
  66. data/lib/babushka/renderable.rb +11 -9
  67. data/lib/babushka/resource.rb +5 -166
  68. data/lib/babushka/run_reporter.rb +12 -3
  69. data/lib/babushka/shell.rb +54 -44
  70. data/lib/babushka/source.rb +41 -20
  71. data/lib/babushka/source_pool.rb +20 -13
  72. data/lib/babushka/system_definitions.rb +11 -3
  73. data/lib/babushka/system_detector.rb +31 -0
  74. data/lib/babushka/system_matcher.rb +53 -0
  75. data/lib/babushka/system_profile.rb +67 -89
  76. data/lib/babushka/task.rb +36 -8
  77. data/lib/babushka/{meta_dep_context.rb → templated_dep_context.rb} +1 -1
  78. data/lib/babushka/vars.rb +46 -4
  79. data/lib/babushka/version_of.rb +35 -17
  80. data/lib/babushka/version_str.rb +12 -8
  81. data/lib/components.rb +9 -8
  82. data/lib/fancypath/fancypath.rb +109 -83
  83. data/lib/inkan/inkan.rb +14 -14
  84. data/lib/{babushka → levenshtein}/levenshtein.rb +0 -0
  85. data/spec/acceptance/acceptance.rb +4 -4
  86. data/spec/acceptance_helper.rb +10 -6
  87. data/spec/babushka/accepts_for_spec.rb +137 -142
  88. data/spec/babushka/accepts_for_support.rb +13 -6
  89. data/spec/babushka/asset_spec.rb +165 -0
  90. data/spec/babushka/cmdline/help_spec.rb +11 -9
  91. data/spec/babushka/cmdline/meet_spec.rb +15 -0
  92. data/spec/babushka/cmdline/version_spec.rb +1 -1
  93. data/spec/babushka/core_patches_spec.rb +9 -0
  94. data/spec/babushka/current_ruby_spec.rb +73 -0
  95. data/spec/babushka/dep_context_spec.rb +27 -13
  96. data/spec/babushka/dep_definer_spec.rb +108 -16
  97. data/spec/babushka/dep_spec.rb +87 -104
  98. data/spec/babushka/dep_template_spec.rb +176 -0
  99. data/spec/babushka/deps_spec.rb +48 -19
  100. data/spec/babushka/gem_helper_spec.rb +46 -59
  101. data/spec/babushka/git_repo_spec.rb +242 -51
  102. data/spec/babushka/ip_spec.rb +11 -11
  103. data/spec/babushka/lambda_chooser_spec.rb +47 -9
  104. data/spec/babushka/parameter_spec.rb +21 -0
  105. data/spec/babushka/path_checker_spec.rb +35 -0
  106. data/spec/babushka/path_helpers_spec.rb +51 -50
  107. data/spec/babushka/prompt_spec.rb +4 -4
  108. data/spec/babushka/renderable_spec.rb +61 -28
  109. data/spec/babushka/shell_helpers_spec.rb +110 -85
  110. data/spec/babushka/shell_spec.rb +15 -0
  111. data/spec/babushka/source_pool_spec.rb +204 -210
  112. data/spec/babushka/source_spec.rb +125 -42
  113. data/spec/babushka/source_support.rb +1 -1
  114. data/spec/babushka/system_profile_spec.rb +86 -49
  115. data/spec/babushka/task_spec.rb +80 -13
  116. data/spec/babushka/vars_spec.rb +2 -1
  117. data/spec/babushka/version_of_spec.rb +29 -2
  118. data/spec/babushka/version_str_spec.rb +91 -65
  119. data/spec/babushka/xml_string_spec.rb +1 -1
  120. data/spec/deps/bad/broken.rb +2 -2
  121. data/spec/deps/bad/working.rb +0 -1
  122. data/spec/deps/good/{meta.rb → template.rb} +0 -0
  123. data/spec/deps/good/test.rb +0 -3
  124. data/spec/deps/outer/deps.rb +0 -2
  125. data/spec/fancypath/fancypath_spec.rb +30 -0
  126. data/spec/inkan/inkan_spec.rb +34 -32
  127. data/spec/spec_helper.rb +7 -50
  128. data/spec/system_detector_spec.rb +70 -0
  129. metadata +163 -177
  130. data/deps/os_x.rb +0 -33
  131. data/deps/templates/ppa.rb +0 -24
  132. data/lib/babushka/core_patches/io.rb +0 -8
  133. data/lib/babushka/dep_runner.rb +0 -85
  134. data/lib/babushka/helpers/suggest_helpers.rb +0 -16
  135. data/lib/babushka/pkg_helpers/base_helper.rb +0 -19
  136. data/lib/babushka/pkg_helpers/macports_helper.rb +0 -22
  137. data/spec/babushka/dep_definer_support.rb +0 -36
  138. data/spec/babushka/meta_dep_definer_spec.rb +0 -127
  139. data/spec/babushka/meta_dep_wrapper_spec.rb +0 -32
  140. data/spec/babushka/resource_spec.rb +0 -141
  141. data/spec/babushka/run_helpers_spec.rb +0 -26
  142. data/spec/babushka/source_pool_support.rb +0 -31
@@ -6,19 +6,6 @@ module Babushka
6
6
  def manager_key; :brew end
7
7
  def manager_dep; 'homebrew' end
8
8
 
9
- def _install! pkgs, opts
10
- check_for_formulas(pkgs) && pkgs.all? {|pkg|
11
- log "Installing #{pkg} via #{manager_key}" do
12
- shell(
13
- "#{pkg_cmd} install #{cmdline_spec_for pkg} #{opts}",
14
- :sudo => should_sudo?,
15
- :log => true,
16
- :closing_status => :status_only
17
- )
18
- end
19
- }
20
- end
21
-
22
9
  def update_pkg_lists_if_required
23
10
  super.tap {|result|
24
11
  pkg_list_dir.touch if result
@@ -35,18 +22,23 @@ module Babushka
35
22
  super || !installed_pkgs_path.hypothetically_writable?
36
23
  end
37
24
 
38
-
39
25
  private
40
26
 
41
- class LibraryDep
42
- attr_reader :names
43
- def initialize *names
44
- @names = names
45
- end
27
+ def has_pkg? pkg
28
+ versions_of(pkg).sort.reverse.detect {|version| pkg.matches? version }
46
29
  end
47
30
 
48
- def _has? pkg
49
- versions_of(pkg).sort.reverse.detect {|version| pkg.matches? version }
31
+ def install_pkgs! pkgs, opts
32
+ check_for_formulas(pkgs) && pkgs.all? {|pkg|
33
+ log "Installing #{pkg} via #{manager_key}" do
34
+ shell(
35
+ "#{pkg_cmd} install #{cmdline_spec_for pkg} #{opts}",
36
+ :sudo => should_sudo?,
37
+ :log => true,
38
+ :closing_status => :status_only
39
+ )
40
+ end
41
+ }
50
42
  end
51
43
 
52
44
  def check_for_formulas pkgs
@@ -71,7 +63,7 @@ module Babushka
71
63
  }.flatten.select {|i|
72
64
  i[/\d/] # For it to be a version, it has to have at least 1 digit.
73
65
  }.map {|i|
74
- VersionOf i.split('/', 2)
66
+ Babushka.VersionOf i.split('/', 2)
75
67
  }.max.version
76
68
  end
77
69
 
@@ -89,6 +81,7 @@ module Babushka
89
81
  def pkg_update_timeout
90
82
  3600 # 1 hour
91
83
  end
84
+
92
85
  def pkg_list_dir
93
86
  prefix
94
87
  end
@@ -96,12 +89,11 @@ module Babushka
96
89
  def installed_pkgs_path
97
90
  prefix / 'Cellar'
98
91
  end
92
+
99
93
  def formulas_path
100
94
  prefix / 'Library/Formula'
101
95
  end
102
- def formula_path_for pkg
103
- formulas_path / pkg.to_s.end_with('.rb')
104
- end
96
+
105
97
  def homebrew_lib_path
106
98
  prefix / 'Library/Homebrew'
107
99
  end
@@ -6,47 +6,48 @@ module Babushka
6
6
  def manager_key; :gem end
7
7
  def manager_dep; 'rubygems' end
8
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?
9
+ def install! pkgs, opts = nil
10
+ super.tap {
11
+ shell!('rbenv rehash') if Babushka.ruby.rbenv?
14
12
  }
15
13
  end
16
14
 
17
15
  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)
16
+ unless (detected_version = has?(Babushka.VersionOf(gem_name, version), :log => false)).nil?
17
+ Babushka.ruby.gem_dir / Babushka.VersionOf(gem_name, detected_version)
20
18
  end
21
19
  end
22
20
 
23
21
  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
22
+ Babushka.ruby.bin_dir
27
23
  end
28
24
 
29
25
  def gem_root
30
- gemdir / 'gems'
26
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.gem_root', :instead => 'Babushka.ruby.gem_dir'
27
+ Babushka.ruby.gem_dir
31
28
  end
32
29
 
33
30
  def gemspec_dir
34
- gemdir / 'specifications'
31
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.gemspec_dir', :instead => 'Babushka.ruby.gemspec_dir'
32
+ Babushka.ruby.gemspec_dir
35
33
  end
36
34
 
37
35
  def gemdir
38
- env_info.val_for('INSTALLATION DIRECTORY')
36
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.gemdir'
37
+ Babushka.ruby.send(:gem_env).val_for('INSTALLATION DIRECTORY')
39
38
  end
40
39
 
41
40
  def ruby_path
42
- env_info.val_for('RUBY EXECUTABLE').p
41
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.ruby_path', :instead => 'Babushka.ruby.path'
42
+ Babushka.ruby.path
43
43
  end
44
44
 
45
45
  def ruby_wrapper_path
46
- if ruby_path.to_s['/.rvm/rubies/'].nil?
47
- ruby_path
46
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.ruby_wrapper_path'
47
+ if Babushka.ruby.path.to_s['/.rvm/rubies/'].nil?
48
+ Babushka.ruby.path
48
49
  else
49
- ruby_path.sub(
50
+ Babushka.ruby.path.sub(
50
51
  # /Users/ben/.rvm/rubies/ruby-1.9.2-p0/bin/ruby
51
52
  /^(.*)\/\.rvm\/rubies\/([^\/]+)\/bin\/ruby/
52
53
  ) {
@@ -57,19 +58,21 @@ module Babushka
57
58
  end
58
59
 
59
60
  def ruby_arch
61
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.ruby_arch'
60
62
  if RUBY_PLATFORM =~ /universal/
61
63
  "universal"
62
64
  elsif RUBY_PLATFORM == "java"
63
65
  "java"
64
66
  elsif RUBY_PLATFORM =~ /darwin/
65
67
  # e.g. "/opt/ruby-enterprise/bin/ruby: Mach-O 64-bit executable x86_64"
66
- shell("file -L '#{ruby_path}'").sub(/.* /, '')
68
+ shell("file -L '#{Babushka.ruby.path}'").sub(/.* /, '')
67
69
  else
68
- Base.host.cpu_type
70
+ Babushka.host.cpu_type
69
71
  end
70
72
  end
71
73
 
72
74
  def ruby_binary_slug
75
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.ruby_binary_slug'
73
76
  [
74
77
  (defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'),
75
78
  RUBY_VERSION,
@@ -79,24 +82,34 @@ module Babushka
79
82
  end
80
83
 
81
84
  def slug_for ruby
85
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.slug_for'
82
86
  shell %Q{#{ruby} -e "require '#{Babushka::Path.lib / 'babushka'}'; puts Babushka::GemHelper.ruby_binary_slug"}
83
87
  end
84
88
 
85
89
  def should_sudo?
86
- super || (gem_root.exists? && !gem_root.writable?)
90
+ super || (Babushka.ruby.gem_dir.exists? && !Babushka.ruby.gem_dir.writable?)
87
91
  end
88
92
 
89
93
  def version
90
- env_info.val_for('RUBYGEMS VERSION').to_version
94
+ deprecated! '2013-04-28', :method_name => 'Babushka::GemHelper.version', :instead => 'Babushka.ruby.gem_version'
95
+ Babushka.ruby.gem_version
91
96
  end
92
97
 
93
98
 
94
99
  private
95
100
 
96
- def _has? pkg
101
+ def has_pkg? pkg
97
102
  versions_of(pkg).sort.reverse.detect {|version| pkg.matches? version }
98
103
  end
99
104
 
105
+ def install_pkgs! pkgs, opts
106
+ pkgs.each {|pkg|
107
+ log_shell "Installing #{pkg} via #{manager_key}",
108
+ "#{pkg_cmd} install #{cmdline_spec_for pkg} #{opts}",
109
+ :sudo => should_sudo?
110
+ }
111
+ end
112
+
100
113
  def versions_of pkg
101
114
  pkg_name = pkg.respond_to?(:name) ? pkg.name : pkg
102
115
  gemspecs_for(pkg_name).select {|i|
@@ -109,11 +122,7 @@ module Babushka
109
122
  end
110
123
 
111
124
  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')
125
+ Babushka.ruby.gemspec_dir.glob("#{pkg_name}-*.gemspec")
117
126
  end
118
127
  end
119
128
  end
@@ -8,15 +8,7 @@ module Babushka
8
8
 
9
9
  private
10
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
11
+ def has_pkg? pkg
20
12
  # Some example output:
21
13
  # socket.io@0.6.15 =rauchg active installed remote
22
14
  shell("#{pkg_cmd} ls -g").split("\n").grep(
@@ -26,6 +18,14 @@ module Babushka
26
18
  }
27
19
  end
28
20
 
21
+ def install_pkgs! pkgs, opts
22
+ pkgs.each {|pkg|
23
+ log_shell "Installing #{pkg} via #{manager_key}",
24
+ "#{pkg_cmd} install -g #{cmdline_spec_for pkg} #{opts}",
25
+ :sudo => should_sudo?
26
+ }
27
+ end
28
+
29
29
  def cmdline_spec_for pkg
30
30
  if pkg.version.nil?
31
31
  # e.g. 'socket.io'
@@ -8,6 +8,10 @@ module Babushka
8
8
 
9
9
  private
10
10
 
11
+ def has_pkg? pkg_name
12
+ raw_shell("pacman -Q #{pkg_name}").stderr !~ /not found$/
13
+ end
14
+
11
15
  # NOTE By default, Arch has sudo's `tty_tickets` option enabled. This will
12
16
  # result in sudo asking for your password every single time it's run from
13
17
  # Babushka. If you find this annoying, please refer to
@@ -15,13 +19,10 @@ module Babushka
15
19
  #
16
20
  # tl;dr - Add the following line to /etc/sudoers:
17
21
  # Defaults !tty_tickets
18
- def _install! pkgs, opts
22
+ def install_pkgs! pkgs, opts
19
23
  log_shell "Downloading", "#{pkg_cmd} -S --noconfirm #{pkgs.join(' ')}", :sudo => should_sudo?
20
24
  end
21
25
 
22
- def _has? pkg_name
23
- raw_shell("pacman -Q #{pkg_name}").stderr !~ /not found$/
24
- end
25
26
  end
26
27
  end
27
28
  end
@@ -6,26 +6,30 @@ module Babushka
6
6
  def pkg_binary; "pip" end
7
7
  def manager_key; :pip end
8
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
- }
9
+ def manager_dep
10
+ 'pip'
17
11
  end
18
12
 
19
- def _has? pkg
13
+ private
14
+
15
+ def has_pkg? pkg
20
16
  # Some example output:
21
17
  # gunicorn==0.12.0
22
- raw_shell("pip freeze '#{pkg.name}'").stdout.split("\n").select {|line|
18
+ raw_shell("pip freeze").stdout.split("\n").select {|line|
23
19
  line[/^#{Regexp.escape(pkg.name)}\=\=/]
24
20
  }.any? {|match|
25
21
  pkg.matches? match.scan(/\=\=(.*)$/).flatten.first
26
22
  }
27
23
  end
28
24
 
25
+ def install_pkgs! pkgs, opts
26
+ pkgs.each {|pkg|
27
+ log_shell "Installing #{pkg} via #{manager_key}",
28
+ "#{pkg_cmd} install #{cmdline_spec_for pkg} #{opts}",
29
+ :sudo => should_sudo?
30
+ }
31
+ end
32
+
29
33
  def cmdline_spec_for pkg
30
34
  if pkg.version.nil?
31
35
  # e.g. 'gunicorn'
@@ -0,0 +1,19 @@
1
+ module Babushka
2
+ class UnknownPkgHelper < PkgHelper
3
+ class << self
4
+ def pkg_type; :unknown end
5
+ def manager_key; :unknown end
6
+ def manager_dep; nil end
7
+
8
+ private
9
+
10
+ def has_pkg? pkg
11
+ raise UnmeetableDep, "This system's package manager (if it has one) isn't supported."
12
+ end
13
+
14
+ def install_pkgs! pkgs, opts
15
+ raise UnmeetableDep, "This system's package manager (if it has one) isn't supported."
16
+ end
17
+ end
18
+ end
19
+ end
@@ -8,7 +8,7 @@ module Babushka
8
8
 
9
9
  private
10
10
 
11
- def _has? pkg_name
11
+ def has_pkg? pkg_name
12
12
  # Some example output, with 'wget' installed:
13
13
  # fedora-13: 'wget.x86_64 1.12-2.fc13 @fedora'
14
14
  # centos-5.5: 'wget.x86_64 1.11.4-2.el5_4.1 installed'
@@ -1,14 +1,17 @@
1
1
  module Babushka
2
2
  class Open3
3
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] }
4
+ pipe_in, pipe_out, pipe_err = IO::pipe, IO::pipe, IO::pipe
5
+
6
+ # To write to the process' STDIN, and read from its STDOUT/ERR.
7
+ near = [pipe_in[1], pipe_out[0], pipe_err[0]]
8
+ # The other ends, connected to the process.
9
+ far = [pipe_in[0], pipe_out[1], pipe_err[1]]
7
10
 
8
11
  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
+ reopen_pipe_for :read, pipe_in, STDIN
13
+ reopen_pipe_for :write, pipe_out, STDOUT
14
+ reopen_pipe_for :write, pipe_err, STDERR
12
15
 
13
16
  Dir.chdir opts[:chdir] if opts[:chdir]
14
17
  ENV.update opts[:env] if opts[:env]
@@ -16,14 +19,14 @@ module Babushka
16
19
  exec(*cmd)
17
20
  }
18
21
 
19
- far.values.each(&:close)
20
- near.values.each {|p| p.sync = true }
22
+ near.each {|p| p.sync = true }
23
+ far.each(&:close)
21
24
 
22
25
  begin
23
- yield near[:in], near[:out], near[:err]
26
+ yield(*near)
24
27
  Process.waitpid2(pid).last.exitstatus
25
28
  ensure
26
- near.values.each {|p| p.close unless p.closed? }
29
+ near.each {|p| p.close unless p.closed? }
27
30
  end
28
31
  end
29
32
 
@@ -22,6 +22,19 @@ module Babushka
22
22
  end
23
23
 
24
24
  class << self
25
+ def suggest_value_for typo, choices
26
+ if (possible_matches = choices.similar_to(typo.to_s)).empty?
27
+ nil # nothing to suggest
28
+ elsif possible_matches.length == 1
29
+ confirm "#{"Did you mean".colorize('grey')} '#{possible_matches.first}'#{"?".colorize('grey')}" do
30
+ possible_matches.first
31
+ end or false
32
+ else
33
+ log "Similar: #{possible_matches.map {|d| "'#{d}'" }.join(', ')}"
34
+ get_value("Did you mean any of those".colorize('grey'), :default => possible_matches.first)
35
+ end
36
+ end
37
+
25
38
  def confirm message, opts = {}, &block
26
39
  prompter = (!opts[:always_ask] && respond_to?(:var)) ? :var : :get_value
27
40
  answer = send(prompter, message,
@@ -127,7 +140,7 @@ module Babushka
127
140
  opts[:retry] || "That wasn't valid"
128
141
  elsif value.blank? && !(opts[:default] && opts[:default].empty?)
129
142
  "That was blank"
130
- elsif !opts[:confirmation] && value == 'y' && !confirm("Wait, do you mean the literal value 'y'?", :default => 'n', :always_ask => true)
143
+ elsif !opts[:confirmation] && %w[y yes].include?(value) && !confirm("Wait, do you mean the literal value '#{value}'?", :default => 'n', :always_ask => true)
131
144
  "Thought so :) Hit enter for the [default]"
132
145
  end
133
146
 
@@ -7,7 +7,7 @@ module Babushka
7
7
 
8
8
  attr_reader :path
9
9
  def initialize path
10
- @path = path
10
+ @path = path.p
11
11
  end
12
12
 
13
13
  def render source, opts = {}
@@ -22,7 +22,7 @@ module Babushka
22
22
  end
23
23
 
24
24
  def exists?
25
- path.p.exists?
25
+ path.exists?
26
26
  end
27
27
 
28
28
  def clean?
@@ -33,6 +33,14 @@ module Babushka
33
33
  exists? && source_sha == sha_of(source)
34
34
  end
35
35
 
36
+ def source_sha
37
+ path.open {|f|
38
+ [f.gets, f.gets].compact.detect {|l|
39
+ l[/^#!/].nil? # The first line that isn't a hashbang
40
+ } || ''
41
+ }.scan(/, from ([0-9a-f]{40})\./).flatten.first
42
+ end
43
+
36
44
  private
37
45
 
38
46
  def inkan_output_for source, opts = {}
@@ -56,12 +64,6 @@ module Babushka
56
64
  raise "Source doesn't exist: #{source.p}" unless source.p.exists?
57
65
  Digest::SHA1.hexdigest(source.p.read)
58
66
  end
59
-
60
- def source_sha
61
- File.open(path.p) {|f|
62
- first_line = f.gets
63
- first_line[/\A#!/] ? f.gets : first_line
64
- }.scan(/, from ([0-9a-f]{40})\./).flatten.first
65
- end
66
67
  end
67
68
  end
69
+