rubycut-babushka 0.10.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +31 -0
  3. data/README.markdown +246 -0
  4. data/Rakefile +26 -0
  5. data/bin/babushka +11 -0
  6. data/deps/babushka.rb +101 -0
  7. data/deps/dev.rb +12 -0
  8. data/deps/fhs.rb +31 -0
  9. data/deps/git.rb +29 -0
  10. data/deps/homebrew.rb +30 -0
  11. data/deps/os_x.rb +33 -0
  12. data/deps/packages.rb +22 -0
  13. data/deps/pkg_managers.rb +110 -0
  14. data/deps/ruby.rb +23 -0
  15. data/deps/rubygems.rb +24 -0
  16. data/deps/system.rb +10 -0
  17. data/deps/templates/app.rb +68 -0
  18. data/deps/templates/external.rb +12 -0
  19. data/deps/templates/installer.rb +31 -0
  20. data/deps/templates/managed.rb +105 -0
  21. data/deps/templates/ppa.rb +24 -0
  22. data/deps/templates/src.rb +42 -0
  23. data/deps/templates/tmbundle.rb +15 -0
  24. data/lib/babushka.rb +28 -0
  25. data/lib/babushka/accepts_block_for.rb +72 -0
  26. data/lib/babushka/accepts_list_for.rb +49 -0
  27. data/lib/babushka/accepts_value_for.rb +24 -0
  28. data/lib/babushka/base.rb +78 -0
  29. data/lib/babushka/bug_reporter.rb +55 -0
  30. data/lib/babushka/cmdline.rb +133 -0
  31. data/lib/babushka/cmdline/handler.rb +41 -0
  32. data/lib/babushka/cmdline/helpers.rb +127 -0
  33. data/lib/babushka/cmdline/parser.rb +69 -0
  34. data/lib/babushka/colorizer.rb +59 -0
  35. data/lib/babushka/core_patches/array.rb +171 -0
  36. data/lib/babushka/core_patches/blank.rb +22 -0
  37. data/lib/babushka/core_patches/bytes.rb +52 -0
  38. data/lib/babushka/core_patches/hash.rb +107 -0
  39. data/lib/babushka/core_patches/hashish.rb +14 -0
  40. data/lib/babushka/core_patches/integer.rb +25 -0
  41. data/lib/babushka/core_patches/io.rb +8 -0
  42. data/lib/babushka/core_patches/numeric.rb +16 -0
  43. data/lib/babushka/core_patches/object.rb +27 -0
  44. data/lib/babushka/core_patches/string.rb +116 -0
  45. data/lib/babushka/core_patches/symbol.rb +12 -0
  46. data/lib/babushka/core_patches/try.rb +15 -0
  47. data/lib/babushka/core_patches/uri.rb +24 -0
  48. data/lib/babushka/dep.rb +470 -0
  49. data/lib/babushka/dep_context.rb +18 -0
  50. data/lib/babushka/dep_definer.rb +115 -0
  51. data/lib/babushka/dep_pool.rb +49 -0
  52. data/lib/babushka/dep_runner.rb +85 -0
  53. data/lib/babushka/dsl.rb +26 -0
  54. data/lib/babushka/git_repo.rb +185 -0
  55. data/lib/babushka/helpers/git_helpers.rb +32 -0
  56. data/lib/babushka/helpers/log_helpers.rb +176 -0
  57. data/lib/babushka/helpers/path_helpers.rb +34 -0
  58. data/lib/babushka/helpers/run_helpers.rb +145 -0
  59. data/lib/babushka/helpers/shell_helpers.rb +229 -0
  60. data/lib/babushka/helpers/suggest_helpers.rb +16 -0
  61. data/lib/babushka/helpers/uri_helpers.rb +36 -0
  62. data/lib/babushka/ip.rb +160 -0
  63. data/lib/babushka/lambda_chooser.rb +40 -0
  64. data/lib/babushka/levenshtein.rb +125 -0
  65. data/lib/babushka/meta_dep.rb +65 -0
  66. data/lib/babushka/meta_dep_context.rb +15 -0
  67. data/lib/babushka/parameter.rb +143 -0
  68. data/lib/babushka/pkg_helper.rb +81 -0
  69. data/lib/babushka/pkg_helpers/apt_helper.rb +61 -0
  70. data/lib/babushka/pkg_helpers/base_helper.rb +19 -0
  71. data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +48 -0
  72. data/lib/babushka/pkg_helpers/binports_helper.rb +34 -0
  73. data/lib/babushka/pkg_helpers/brew_helper.rb +110 -0
  74. data/lib/babushka/pkg_helpers/gem_helper.rb +120 -0
  75. data/lib/babushka/pkg_helpers/macports_helper.rb +22 -0
  76. data/lib/babushka/pkg_helpers/npm_helper.rb +45 -0
  77. data/lib/babushka/pkg_helpers/pacman_helper.rb +27 -0
  78. data/lib/babushka/pkg_helpers/pip_helper.rb +45 -0
  79. data/lib/babushka/pkg_helpers/src_helper.rb +16 -0
  80. data/lib/babushka/pkg_helpers/yum_helper.rb +25 -0
  81. data/lib/babushka/popen.rb +40 -0
  82. data/lib/babushka/prompt.rb +176 -0
  83. data/lib/babushka/renderable.rb +67 -0
  84. data/lib/babushka/resource.rb +215 -0
  85. data/lib/babushka/run_reporter.rb +60 -0
  86. data/lib/babushka/shell.rb +108 -0
  87. data/lib/babushka/source.rb +216 -0
  88. data/lib/babushka/source_pool.rb +146 -0
  89. data/lib/babushka/system_definitions.rb +97 -0
  90. data/lib/babushka/system_profile.rb +210 -0
  91. data/lib/babushka/task.rb +142 -0
  92. data/lib/babushka/vars.rb +108 -0
  93. data/lib/babushka/version_of.rb +65 -0
  94. data/lib/babushka/version_str.rb +57 -0
  95. data/lib/babushka/xml_string.rb +28 -0
  96. data/lib/components.rb +82 -0
  97. data/lib/fancypath/fancypath.rb +200 -0
  98. data/lib/inkan/inkan.rb +76 -0
  99. data/spec/acceptance/acceptance.rb +43 -0
  100. data/spec/acceptance_helper.rb +113 -0
  101. data/spec/archives/Blah.app.zip +0 -0
  102. data/spec/archives/archive.tar +0 -0
  103. data/spec/archives/archive.tar.bz2 +0 -0
  104. data/spec/archives/archive.tar.gz +0 -0
  105. data/spec/archives/archive.tbz2 +0 -0
  106. data/spec/archives/archive.tgz +0 -0
  107. data/spec/archives/archive.zip +0 -0
  108. data/spec/archives/content.txt +5 -0
  109. data/spec/archives/invalid_archive +5 -0
  110. data/spec/archives/nested archive/content.txt +5 -0
  111. data/spec/archives/nested_archive.tar +0 -0
  112. data/spec/archives/really_a_gzip.zip +0 -0
  113. data/spec/archives/test-0.3.1.tgz +0 -0
  114. data/spec/archives/tgz_archive +0 -0
  115. data/spec/archives/zip_without_extension +0 -0
  116. data/spec/babushka/accepts_for_spec.rb +174 -0
  117. data/spec/babushka/accepts_for_support.rb +72 -0
  118. data/spec/babushka/cmdline/console_spec.rb +11 -0
  119. data/spec/babushka/cmdline/help_spec.rb +61 -0
  120. data/spec/babushka/cmdline/version_spec.rb +10 -0
  121. data/spec/babushka/core_patches_spec.rb +171 -0
  122. data/spec/babushka/dep_context_spec.rb +58 -0
  123. data/spec/babushka/dep_definer_spec.rb +152 -0
  124. data/spec/babushka/dep_definer_support.rb +36 -0
  125. data/spec/babushka/dep_spec.rb +567 -0
  126. data/spec/babushka/dep_support.rb +29 -0
  127. data/spec/babushka/deps_spec.rb +113 -0
  128. data/spec/babushka/gem_helper_spec.rb +90 -0
  129. data/spec/babushka/git_repo_spec.rb +396 -0
  130. data/spec/babushka/ip_spec.rb +131 -0
  131. data/spec/babushka/lambda_chooser_spec.rb +115 -0
  132. data/spec/babushka/meta_dep_definer_spec.rb +127 -0
  133. data/spec/babushka/meta_dep_wrapper_spec.rb +32 -0
  134. data/spec/babushka/parameter_spec.rb +135 -0
  135. data/spec/babushka/path_helpers_spec.rb +102 -0
  136. data/spec/babushka/prompt_spec.rb +188 -0
  137. data/spec/babushka/renderable_spec.rb +100 -0
  138. data/spec/babushka/resource_spec.rb +141 -0
  139. data/spec/babushka/run_helpers_spec.rb +26 -0
  140. data/spec/babushka/shell_helpers_spec.rb +244 -0
  141. data/spec/babushka/shell_spec.rb +19 -0
  142. data/spec/babushka/source_pool_spec.rb +320 -0
  143. data/spec/babushka/source_pool_support.rb +31 -0
  144. data/spec/babushka/source_spec.rb +382 -0
  145. data/spec/babushka/source_support.rb +17 -0
  146. data/spec/babushka/system_profile_spec.rb +61 -0
  147. data/spec/babushka/task_spec.rb +141 -0
  148. data/spec/babushka/uri_spec.rb +13 -0
  149. data/spec/babushka/vars_spec.rb +59 -0
  150. data/spec/babushka/version_of_spec.rb +110 -0
  151. data/spec/babushka/version_str_spec.rb +130 -0
  152. data/spec/babushka/version_str_support.rb +37 -0
  153. data/spec/babushka/xml_string_spec.rb +98 -0
  154. data/spec/deps/bad/broken.rb +7 -0
  155. data/spec/deps/bad/working.rb +3 -0
  156. data/spec/deps/good/meta.rb +14 -0
  157. data/spec/deps/good/test.rb +11 -0
  158. data/spec/deps/outer/deps.rb +19 -0
  159. data/spec/deps/outer/more deps.rb +11 -0
  160. data/spec/deps/params/params.rb +10 -0
  161. data/spec/fancypath/fancypath_spec.rb +272 -0
  162. data/spec/fancypath_support.rb +10 -0
  163. data/spec/inkan/inkan_spec.rb +217 -0
  164. data/spec/renderable/different_example.conf.erb +4 -0
  165. data/spec/renderable/example.conf.erb +3 -0
  166. data/spec/renderable/example.sh +6 -0
  167. data/spec/renderable/with_binding.conf.erb +4 -0
  168. data/spec/renderable/xml_example.conf.erb +8 -0
  169. data/spec/repos/remote.git.tgz +0 -0
  170. data/spec/spec_helper.rb +87 -0
  171. metadata +238 -0
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe "cd" do
4
+ before do
5
+ @tmp_dir = tmp_prefix
6
+ `mkdir -p '#{@tmp_dir}'`
7
+ @tmp_dir_2 = File.join(tmp_prefix, '2')
8
+ `mkdir -p '#{@tmp_dir_2}'`
9
+
10
+ @original_pwd = Dir.pwd
11
+
12
+ @nonexistent_dir = File.join(tmp_prefix, 'nonexistent')
13
+ Dir.rmdir(@nonexistent_dir) if File.directory?(@nonexistent_dir)
14
+ end
15
+
16
+ it "should yield if no dir is given" do
17
+ has_yielded = false
18
+ cd(nil) {|path|
19
+ path.should be_an_instance_of(Fancypath)
20
+ Dir.pwd.should == @original_pwd
21
+ has_yielded = true
22
+ }
23
+ has_yielded.should be_true
24
+ end
25
+
26
+ it "should yield if no chdir is required" do
27
+ has_yielded = false
28
+ cd(@original_pwd) {|path|
29
+ path.should be_an_instance_of(Fancypath)
30
+ Dir.pwd.should == @original_pwd
31
+ has_yielded = true
32
+ }
33
+ has_yielded.should be_true
34
+ end
35
+ it "should change dir for the duration of the block" do
36
+ has_yielded = false
37
+ cd(@tmp_dir) {
38
+ Dir.pwd.should == @tmp_dir
39
+ has_yielded = true
40
+ }
41
+ has_yielded.should be_true
42
+ Dir.pwd.should == @original_pwd
43
+ end
44
+ it "should work recursively" do
45
+ cd(@tmp_dir) {
46
+ Dir.pwd.should == @tmp_dir
47
+ cd(@tmp_dir_2) {
48
+ Dir.pwd.should == @tmp_dir_2
49
+ }
50
+ Dir.pwd.should == @tmp_dir
51
+ }
52
+ Dir.pwd.should == @original_pwd
53
+ end
54
+ it "should fail on nonexistent dirs" do
55
+ L{ cd(@nonexistent_dir) }.should raise_error(Errno::ENOENT)
56
+ end
57
+ it "should create nonexistent dirs if :create => true is specified" do
58
+ cd(@nonexistent_dir, :create => true) {
59
+ Dir.pwd.should == @nonexistent_dir
60
+ }
61
+ Dir.pwd.should == @original_pwd
62
+ end
63
+ after {
64
+ Dir.rmdir(@nonexistent_dir) if File.directory?(@nonexistent_dir)
65
+ }
66
+ end
67
+
68
+ describe "in_build_dir" do
69
+ before {
70
+ @original_pwd = Dir.pwd
71
+ }
72
+ it "should change to the build dir with no args" do
73
+ in_build_dir {
74
+ Dir.pwd.should == "~/.babushka/build".p
75
+ }
76
+ Dir.pwd.should == @original_pwd
77
+ end
78
+ it "should append the supplied path when supplied" do
79
+ in_build_dir "tmp" do
80
+ Dir.pwd.should == "~/.babushka/build/tmp".p
81
+ end
82
+ Dir.pwd.should == @original_pwd
83
+ end
84
+ end
85
+
86
+ describe "in_download_dir" do
87
+ before {
88
+ @original_pwd = Dir.pwd
89
+ }
90
+ it "should change to the download dir with no args" do
91
+ in_download_dir {
92
+ Dir.pwd.should == "~/.babushka/downloads".p
93
+ }
94
+ Dir.pwd.should == @original_pwd
95
+ end
96
+ it "should append the supplied path when supplied" do
97
+ in_download_dir "tmp" do
98
+ Dir.pwd.should == "~/.babushka/downloads/tmp".p
99
+ end
100
+ Dir.pwd.should == @original_pwd
101
+ end
102
+ end
@@ -0,0 +1,188 @@
1
+ require 'spec_helper'
2
+
3
+ describe Prompt, "get_value" do
4
+ it "should raise when not running on a terminal" do
5
+ $stdin.should_receive(:tty?).and_return(false)
6
+ expect { Prompt.get_value('value') }.to raise_error(PromptUnavailable)
7
+ end
8
+
9
+ it "should raise when not running on a terminal and a default is present" do
10
+ $stdin.should_receive(:tty?).and_return(false)
11
+ expect { Prompt.get_value('value', :default => 'a default') }.to raise_error(PromptUnavailable)
12
+ end
13
+
14
+ it "should raise when a default is expected but not available" do
15
+ Base.task.should_receive(:opt).with(:defaults).and_return(true)
16
+ expect { Prompt.get_value('value') }.to raise_error(DefaultUnavailable)
17
+ end
18
+
19
+ it "should return the value" do
20
+ Prompt.should_receive(:log).with("value", {:newline => false})
21
+ Prompt.should_receive(:read_from_prompt).and_return('value')
22
+ Prompt.get_value('value').should == 'value'
23
+ end
24
+
25
+ describe "with default" do
26
+ it "should return the value when it's specified" do
27
+ Prompt.should_receive(:log).with("value [default]", {:newline => false})
28
+ Prompt.should_receive(:read_from_prompt).and_return('value')
29
+ Prompt.get_value('value', :default => 'default').should == 'value'
30
+ end
31
+ it "should return the default when no value is specified" do
32
+ Prompt.should_receive(:log).with("value [default]", {:newline => false})
33
+ Prompt.should_receive(:read_from_prompt).and_return('')
34
+ Prompt.get_value('value', :default => 'default').should == 'default'
35
+ end
36
+ it "should handle non-string defaults" do
37
+ Prompt.should_receive(:log).with("value [80]", {:newline => false})
38
+ Prompt.should_receive(:read_from_prompt).and_return('')
39
+ Prompt.get_value('value', :default => 80).should == '80'
40
+ end
41
+ end
42
+
43
+ it "should reject :choices and :choice_descriptions together" do
44
+ L{
45
+ Prompt.get_value('value', :choices => %w[a b c], :choice_descriptions => {:a => "description"})
46
+ }.should raise_error(ArgumentError, "You can't use the :choices and :choice_descriptions options together.")
47
+ end
48
+
49
+ describe "with choices" do
50
+ it "should accept a valid choice" do
51
+ Prompt.should_receive(:log).with("value (a,b,c)", {:newline => false})
52
+ Prompt.should_receive(:read_from_prompt).and_return('a')
53
+ Prompt.get_value('value', :choices => %w[a b c]).should == 'a'
54
+ end
55
+ it "should reject an invalid choice" do
56
+ Prompt.should_receive(:log).with("value (a,b,c)", {:newline => false})
57
+ Prompt.should_receive(:read_from_prompt).and_return('d')
58
+ Prompt.should_receive(:log).with("That's not a valid choice. value (a,b,c)", {:newline => false})
59
+ Prompt.should_receive(:read_from_prompt).and_return('a')
60
+ Prompt.get_value('value', :choices => %w[a b c]).should == 'a'
61
+ end
62
+ it "should reject non-string choices" do
63
+ L{
64
+ Prompt.get_value('value', :choices => [:a, :b])
65
+ }.should raise_error ArgumentError, "Choices must be passed as strings."
66
+ end
67
+ describe "with default" do
68
+ it "should accept a valid choice" do
69
+ Prompt.should_receive(:log).with("value (a,b,c) [b]", {:newline => false})
70
+ Prompt.should_receive(:read_from_prompt).and_return('a')
71
+ Prompt.get_value('value', :choices => %w[a b c], :default => 'b').should == 'a'
72
+ end
73
+ it "should reject an invalid choice" do
74
+ Prompt.should_receive(:log).with("value (a,b,c) [b]", {:newline => false})
75
+ Prompt.should_receive(:read_from_prompt).and_return('d')
76
+ Prompt.should_receive(:log).with("That's not a valid choice. value (a,b,c) [b]", {:newline => false})
77
+ Prompt.should_receive(:read_from_prompt).and_return('a')
78
+ Prompt.get_value('value', :choices => %w[a b c], :default => 'b').should == 'a'
79
+ end
80
+ describe "with no value specified" do
81
+ it "should accept a valid default" do
82
+ Prompt.should_receive(:log).with("value (a,b,c) [b]", {:newline => false})
83
+ Prompt.should_receive(:read_from_prompt).and_return('')
84
+ Prompt.get_value('value', :choices => %w[a b c], :default => 'b').should == 'b'
85
+ end
86
+ it "should reject an invalid default" do
87
+ Prompt.should_receive(:log).with("value (a,b,c) [d]", {:newline => false})
88
+ Prompt.should_receive(:read_from_prompt).and_return('')
89
+ Prompt.should_receive(:log).with("That's not a valid choice. value (a,b,c) [d]", {:newline => false})
90
+ Prompt.should_receive(:read_from_prompt).and_return('a')
91
+ Prompt.get_value('value', :choices => %w[a b c], :default => 'd').should == 'a'
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "with choice descriptions" do
98
+ it "should behave like choices, logging the descriptions" do
99
+ Prompt.should_receive(:log).with("There are 3 choices:")
100
+ Prompt.should_receive(:log).with("a - the first one")
101
+ Prompt.should_receive(:log).with("b - there's also this")
102
+ Prompt.should_receive(:log).with("c - or this")
103
+ Prompt.should_receive(:log).with("value", {:newline => false})
104
+ Prompt.should_receive(:read_from_prompt).and_return('d')
105
+ Prompt.should_receive(:log).with("That's not a valid choice. value", {:newline => false})
106
+ Prompt.should_receive(:read_from_prompt).and_return('a')
107
+ Prompt.get_value('value', :choice_descriptions => {'a' => "the first one", 'b' => "there's also this", 'c' => "or this"}).should == 'a'
108
+ end
109
+ end
110
+
111
+ describe "validation" do
112
+ it "should treat 'true' as valid" do
113
+ Prompt.should_receive(:read_from_prompt).and_return('value')
114
+ Prompt.get_value('value') {|value| true }.should == 'value'
115
+ end
116
+ it "should treat 'false' as invalid" do
117
+ Prompt.should_receive(:log).with("value", {:newline => false})
118
+ Prompt.should_receive(:read_from_prompt).and_return('another value')
119
+ Prompt.should_receive(:log).with("That wasn't valid. value", {:newline => false})
120
+ Prompt.should_receive(:read_from_prompt).and_return('value')
121
+ Prompt.get_value('value') {|value| value == 'value' }.should == 'value'
122
+ end
123
+ end
124
+ end
125
+
126
+ describe Prompt, "#get_path" do
127
+ it "should return the path" do
128
+ Prompt.should_receive(:log).with("path", {:newline => false})
129
+ Prompt.should_receive(:read_from_prompt).and_return(tmp_prefix)
130
+ Prompt.get_path('path', :type => :path).should == tmp_prefix
131
+ end
132
+ it "should return ~ intact" do
133
+ Prompt.should_receive(:log).with("path", {:newline => false})
134
+ Prompt.should_receive(:read_from_prompt).and_return('~')
135
+ Prompt.get_path('path').should == '~'
136
+ end
137
+ describe "with default" do
138
+ it "should return the value when it's specified" do
139
+ Prompt.should_receive(:log).with("path [/tmp]", {:newline => false})
140
+ Prompt.should_receive(:read_from_prompt).and_return(tmp_prefix)
141
+ Prompt.get_path('path', :default => '/tmp').should == tmp_prefix
142
+ end
143
+ it "should return the default when no value is specified" do
144
+ Prompt.should_receive(:log).with("path [/tmp]", {:newline => false})
145
+ Prompt.should_receive(:read_from_prompt).and_return('')
146
+ Prompt.get_path('path', :default => '/tmp').should == '/tmp'
147
+ end
148
+ end
149
+ describe "with nonexistent path" do
150
+ it "should fail" do
151
+ Prompt.should_receive(:log).with("path", {:newline => false})
152
+ Prompt.should_receive(:read_from_prompt).and_return((tmp_prefix / 'nonexistent').to_s)
153
+ Prompt.should_receive(:log).with("Doesn't exist, or not a directory. path", {:newline => false})
154
+ Prompt.should_receive(:read_from_prompt).and_return(tmp_prefix)
155
+ Prompt.get_path('path', :type => :path).should == tmp_prefix
156
+ end
157
+ it "should fail with a valid default" do
158
+ Prompt.should_receive(:log).with("path [/tmp]", {:newline => false})
159
+ Prompt.should_receive(:read_from_prompt).and_return((tmp_prefix / 'nonexistent').to_s)
160
+ Prompt.should_receive(:log).with("Doesn't exist, or not a directory. path [/tmp]", {:newline => false})
161
+ Prompt.should_receive(:read_from_prompt).and_return(tmp_prefix)
162
+ Prompt.get_path('path', :type => :path, :default => '/tmp').should == tmp_prefix
163
+ end
164
+ end
165
+ end
166
+
167
+ describe "'y' input" do
168
+ context "intentional" do
169
+ it "should return 'y'" do
170
+ Prompt.should_receive(:log).with("value", {:newline => false})
171
+ Prompt.should_receive(:read_from_prompt).and_return('y')
172
+ Prompt.should_receive(:log).with("Wait, do you mean the literal value 'y' [n]", {:newline => false})
173
+ Prompt.should_receive(:read_from_prompt).and_return('y')
174
+ Prompt.get_value('value').should == 'y'
175
+ end
176
+ end
177
+ context "unintentional" do
178
+ it "should ask for the value again with a custom log message" do
179
+ Prompt.should_receive(:log).with("value", {:newline => false})
180
+ Prompt.should_receive(:read_from_prompt).and_return('y')
181
+ Prompt.should_receive(:log).with("Wait, do you mean the literal value 'y' [n]", {:newline => false})
182
+ Prompt.should_receive(:read_from_prompt).and_return('n')
183
+ Prompt.should_receive(:log).with("Thought so :) Hit enter for the [default]. value", {:newline => false})
184
+ Prompt.should_receive(:read_from_prompt).and_return('value')
185
+ Prompt.get_value('value').should == 'value'
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'renderable' do
4
+ it "should not exist" do
5
+ subject.exists?.should be_false
6
+ end
7
+ describe '#render' do
8
+ before { subject.render(source_file) }
9
+ it "should exist" do
10
+ subject.exists?.should be_true
11
+ end
12
+ it "should have added the prefix" do
13
+ dest_file.read.should =~ Renderable::SEAL_REGEXP
14
+ end
15
+ it "should have interpolated the erb" do
16
+ dest_file.read.should =~ content
17
+ end
18
+ describe "#clean?" do
19
+ it "should be clean" do
20
+ subject.should be_clean
21
+ end
22
+ context "after shitting up the file" do
23
+ before {
24
+ shell "echo lulz >> #{subject.path}"
25
+ }
26
+ it "should not be clean" do
27
+ subject.should_not be_clean
28
+ end
29
+ end
30
+ end
31
+ describe '#from?' do
32
+ it "should be from the same content" do
33
+ subject.should be_from(source_file)
34
+ end
35
+ it "should not be from different content" do
36
+ subject.should_not be_from('spec/renderable/different_example.conf.erb')
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ describe Renderable do
43
+ context "with a config file" do
44
+ let(:source_file) { "spec/renderable/example.conf.erb" }
45
+ let(:dest_file) { tmp_prefix / 'example.conf' }
46
+ let(:content) { %r{root #{tmp_prefix};} }
47
+ subject { Renderable.new(dest_file) }
48
+ it_should_behave_like 'renderable'
49
+ end
50
+ context "with an xml file" do
51
+ let(:source_file) { "spec/renderable/xml_example.conf.erb" }
52
+ let(:dest_file) { tmp_prefix / 'xml_example.conf' }
53
+ let(:content) { %r{<key>Lol</key>} }
54
+ subject { Renderable.new(dest_file) }
55
+ it_should_behave_like 'renderable'
56
+ context "custom comment" do
57
+ before { subject.render(source_file, :comment => '<!--', :comment_suffix => '-->') }
58
+ it "should have rendered an xml comment in the output" do
59
+ dest_file.read.should =~ %r{<!-- Generated by babushka-[\d\.]+ at [^,]+, from \w{40}\. \w{40} -->}
60
+ end
61
+ after { dest_file.rm }
62
+ end
63
+ end
64
+ context "with a script containing a shebang" do
65
+ let(:source_file) { "spec/renderable/example.sh" }
66
+ let(:dest_file) { tmp_prefix / 'example.sh' }
67
+ let(:content) { %r{babushka 'benhoskings:up to date.repo'} }
68
+ subject { Renderable.new(dest_file) }
69
+ it_should_behave_like 'renderable'
70
+ end
71
+ describe "binding handling" do
72
+ subject { Renderable.new(tmp_prefix / 'example.conf') }
73
+ context "when no explicit binding is passed" do
74
+ before {
75
+ subject.instance_eval {
76
+ def custom_renderable_path
77
+ "from implicit binding"
78
+ end
79
+ }
80
+ subject.render('spec/renderable/with_binding.conf.erb')
81
+ }
82
+ it "should render using the implicit binding" do
83
+ (tmp_prefix / 'example.conf').read.should =~ /from implicit binding/
84
+ end
85
+ end
86
+ context "when an explicit binding is passed" do
87
+ before {
88
+ dep 'renderable binding spec' do
89
+ def custom_renderable_path
90
+ "from explicit binding"
91
+ end
92
+ end
93
+ subject.render('spec/renderable/with_binding.conf.erb', :context => Dep('renderable binding spec').context)
94
+ }
95
+ it "should render using the given binding" do
96
+ (tmp_prefix / 'example.conf').read.should =~ /from explicit binding/
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+
3
+ def archive_path
4
+ __FILE__.p.parent.parent / 'archives'
5
+ end
6
+
7
+ describe Resource do
8
+ it "should detect file types" do
9
+ Resource.type(archive_path / 'archive.zip').should == :zip
10
+ Resource.type(archive_path / 'archive.tgz').should == :gzip
11
+ end
12
+ it "should first attempt to detect type using file extension" do
13
+ Resource.type(archive_path / 'really_a_gzip.zip').should == :zip
14
+ end
15
+ it "should attempt to detect type via when there is no extension" do
16
+ Resource.type(archive_path / 'zip_without_extension').should == :zip
17
+ end
18
+ it "should detect supported archive types" do
19
+ Resource.for(archive_path / 'archive.tgz').should be_supported
20
+ Resource.for(archive_path / 'archive.tbz2').should be_supported
21
+ end
22
+ it "should raise an error on unsupported types" do
23
+ L{
24
+ Resource.for(archive_path / 'invalid_archive')
25
+ }.should raise_error("Don't know how to extract invalid_archive.")
26
+ end
27
+ it "should set the name" do
28
+ Resource.for(archive_path / 'archive.tar').name.should == 'archive'
29
+ Resource.for(archive_path / 'archive.tar.gz').name.should == 'archive'
30
+ end
31
+ it "should generate the proper command to extract the archive" do
32
+ {
33
+ 'tar' => "tar -xf '#{archive_path / 'archive.tar'}'",
34
+ 'tgz' => "tar -zxf '#{archive_path / 'archive.tgz'}'",
35
+ 'tbz2' => "tar -jxf '#{archive_path / 'archive.tbz2'}'",
36
+ 'zip' => "unzip -o '#{archive_path / 'archive.zip'}'"
37
+ }.each_pair {|ext,command|
38
+ Resource.for(archive_path / "archive.#{ext}").extract_command.should == command
39
+ }
40
+ end
41
+ it "should yield in the extracted dir" do
42
+ Resource.for(archive_path / "archive.tar").extract {
43
+ Dir.pwd.should == (tmp_prefix / 'archives/archive')
44
+ }
45
+ end
46
+ it "should yield in the nested dir if there is one" do
47
+ Resource.for(archive_path / "nested_archive.tar").extract {
48
+ Dir.pwd.should == (tmp_prefix / 'archives/nested_archive/nested archive')
49
+ }
50
+ end
51
+ it "should find a standard content dir as a nested dir" do
52
+ Resource.for(archive_path / "test-0.3.1.tgz").extract {
53
+ Dir.pwd.should == (tmp_prefix / 'archives/test-0.3.1/test-0.3.1')
54
+ Dir.glob('*').should == ['content.txt']
55
+ }
56
+ end
57
+ it "shouldn't descend into some dirs" do
58
+ Resource.for(archive_path / "Blah.app.zip").extract {
59
+ Dir.pwd.should == (tmp_prefix / 'archives/Blah.app')
60
+ Dir.glob('**/*').should == ['Blah.app', 'Blah.app/content.txt']
61
+ }
62
+ end
63
+ end
64
+
65
+ describe Resource, '#content_subdir' do
66
+ before {
67
+ @resource = Resource.new('test.zip')
68
+ }
69
+
70
+ context "when there is just a single file inside the archive" do
71
+ before {
72
+ Dir.stub!(:glob).and_return(['a dir'])
73
+ File.should_receive(:directory?).with('a dir').and_return(false)
74
+ }
75
+ it "should choose it, whatever it's called" do
76
+ @resource.content_subdir.should be_nil
77
+ end
78
+ end
79
+ context "when there is just a single non-descendable dir inside the archive" do
80
+ before {
81
+ Dir.stub!(:glob).and_return(['a dir.app'])
82
+ File.should_receive(:directory?).with('a dir.app').and_return(true)
83
+ }
84
+ it "should choose it, whatever it's called" do
85
+ @resource.content_subdir.should be_nil
86
+ end
87
+ end
88
+ context "when there is just a single dir inside the archive" do
89
+ before {
90
+ Dir.stub!(:glob).and_return(['a dir'])
91
+ File.should_receive(:directory?).with('a dir').and_return(true)
92
+ }
93
+ it "should choose it, whatever it's called" do
94
+ @resource.content_subdir.should == 'a dir'
95
+ end
96
+ end
97
+ context "when there is more than one dir" do
98
+ context "and none are named after the archive" do
99
+ before {
100
+ Dir.stub!(:glob).and_return(['contents', 'another'])
101
+ }
102
+ it "should return nil (so the original extraction dir is used)" do
103
+ @resource.content_subdir.should be_nil
104
+ end
105
+ end
106
+ context "and one is named after the archive" do
107
+ before {
108
+ Dir.stub!(:glob).and_return(['contents', 'test'])
109
+ }
110
+ it "should choose the directory named after the archive" do
111
+ @resource.content_subdir.should == 'test'
112
+ end
113
+ end
114
+ end
115
+ context "when there are non-descendable dirs" do
116
+ context "and none are named after the archive" do
117
+ before {
118
+ Dir.stub!(:glob).and_return(['contents', 'LaunchBar.app', 'RSpec.tmbundle'])
119
+ }
120
+ it "should not choose the non-descendable dir" do
121
+ @resource.content_subdir.should be_nil
122
+ end
123
+ end
124
+ context "and one is named after the archive" do
125
+ before {
126
+ Dir.stub!(:glob).and_return(['contents', 'test.app'])
127
+ }
128
+ it "should not choose the non-descendable dir" do
129
+ @resource.content_subdir.should be_nil
130
+ end
131
+ end
132
+ context "one is named after the archive, and a descendable dir is present too" do
133
+ before {
134
+ Dir.stub!(:glob).and_return(['contents', 'test.app', 'test'])
135
+ }
136
+ it "should choose the descendable dir" do
137
+ @resource.content_subdir.should == 'test'
138
+ end
139
+ end
140
+ end
141
+ end