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.
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,29 @@
1
+ def setup_yield_counts
2
+ @yield_counts = Hash.new {|hsh,k| hsh[k] = Hash.new {|hsh,k| 0 } }
3
+
4
+ @yield_counts_none = {}
5
+ @yield_counts_met_run = {:setup => 1, :met? => 1}
6
+ @yield_counts_meet_run = {:setup => 1, :met? => 2, :prepare => 1, :before => 1, :meet => 1, :after => 1}
7
+ @yield_counts_dep_failed = {:setup => 1}
8
+ @yield_counts_failed_meet_run = {:setup => 1, :met? => 2, :prepare => 1, :before => 1, :meet => 1, :after => 1}
9
+ @yield_counts_early_exit_meet_run = {:setup => 1, :met? => 1, :prepare => 1, :before => 1, :meet => 1}
10
+ @yield_counts_already_met = {:setup => 1, :met? => 1}
11
+ @yield_counts_failed_at_before = {:setup => 1, :met? => 2, :prepare => 1, :before => 1}
12
+ end
13
+
14
+ def make_counter_dep opts = {}
15
+ incrementers = DepContext.accepted_blocks.inject({}) {|lambdas,key|
16
+ lambdas[key] = L{ @yield_counts[opts[:name]][key] += 1 }
17
+ lambdas
18
+ }
19
+ dep opts[:name] do
20
+ requires opts[:requires]
21
+ requires_when_unmet opts[:requires_when_unmet]
22
+ DepContext.accepted_blocks.each {|dep_method|
23
+ send dep_method do
24
+ incrementers[dep_method].call
25
+ (opts[dep_method] || default_block_for(dep_method)).call
26
+ end
27
+ }
28
+ end
29
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+ require 'dep_support'
3
+
4
+ shared_examples_for "met?" do
5
+ describe "met?" do
6
+ before { Dep('a').met? }
7
+ it "should met?-check each dep exactly once" do
8
+ %w[a b c d e f].each {|i| @yield_counts[i].should == @yield_counts_already_met }
9
+ end
10
+ it "shouldn't run the meet-only dep" do
11
+ @yield_counts['g'].should == @yield_counts_none
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "an already met dep tree" do
17
+ before {
18
+ setup_yield_counts
19
+ make_counter_dep :name => 'a', :requires => %w[b c]
20
+ make_counter_dep :name => 'b', :requires => %w[c d e]
21
+ make_counter_dep :name => 'c', :requires => %w[f]
22
+ make_counter_dep :name => 'd', :requires => %w[e f], :requires_when_unmet => %w[g]
23
+ make_counter_dep :name => 'e', :requires => %w[f]
24
+ make_counter_dep :name => 'f'
25
+ make_counter_dep :name => 'g'
26
+ }
27
+ it_should_behave_like "met?"
28
+ describe "meet" do
29
+ before { Dep('a').meet }
30
+ it "should meet no deps" do
31
+ %w[a b c d e f].each {|i| @yield_counts[i].should == @yield_counts_already_met }
32
+ end
33
+ it "shouldn't run the meet-only dep" do
34
+ @yield_counts['g'].should == @yield_counts_none
35
+ end
36
+ end
37
+ after { Base.sources.anonymous.deps.clear! }
38
+ end
39
+
40
+ describe "an unmeetable dep tree" do
41
+ before {
42
+ setup_yield_counts
43
+ make_counter_dep :name => 'a', :met? => L{ false }, :requires => %w[b c]
44
+ make_counter_dep :name => 'b', :met? => L{ false }, :requires => %w[c d e]
45
+ make_counter_dep :name => 'c', :met? => L{ false }, :requires => %w[f], :requires_when_unmet => %w[g]
46
+ make_counter_dep :name => 'd', :met? => L{ false }, :requires => %w[e f]
47
+ make_counter_dep :name => 'e', :met? => L{ false }, :requires => %w[f]
48
+ make_counter_dep :name => 'f', :met? => L{ false }
49
+ make_counter_dep :name => 'g', :met? => L{ false }
50
+ }
51
+ it_should_behave_like "met?"
52
+ describe "meet" do
53
+ before { Dep('a').meet }
54
+ it "should fail on the bootom-most dep" do
55
+ %w[f].each {|i| @yield_counts[i].should == @yield_counts_failed_meet_run }
56
+ end
57
+ it "should bubble the fail back up" do
58
+ %w[a b c].each {|i| @yield_counts[i].should == @yield_counts_dep_failed }
59
+ end
60
+ it "shouldn't run any deps after the fail" do
61
+ %w[d e g].each {|i| @yield_counts[i].should == @yield_counts_none }
62
+ end
63
+ end
64
+ after { Base.sources.anonymous.deps.clear! }
65
+ end
66
+
67
+ describe "a meetable dep tree" do
68
+ before {
69
+ setup_yield_counts
70
+ make_counter_dep :name => 'a', :requires => %w[b c] , :met? => L{ @yield_counts['a'][:met?] > 1 }
71
+ make_counter_dep :name => 'b', :requires => %w[c d e], :met? => L{ @yield_counts['b'][:met?] > 1 }
72
+ make_counter_dep :name => 'c', :requires => %w[f] , :met? => L{ @yield_counts['c'][:met?] > 1 }, :requires_when_unmet => %w[g]
73
+ make_counter_dep :name => 'd', :requires => %w[e f] , :met? => L{ @yield_counts['d'][:met?] > 1 }
74
+ make_counter_dep :name => 'e', :requires => %w[f] , :met? => L{ @yield_counts['e'][:met?] > 1 }
75
+ make_counter_dep :name => 'f', :met? => L{ @yield_counts['f'][:met?] > 1 }
76
+ make_counter_dep :name => 'g', :met? => L{ @yield_counts['g'][:met?] > 1 }
77
+ }
78
+ it_should_behave_like "met?"
79
+ describe "meet" do
80
+ before { Dep('a').meet }
81
+ it "should meet each dep exactly once" do
82
+ Base.sources.anonymous.deps.names.each {|i| @yield_counts[i].should == @yield_counts_meet_run }
83
+ end
84
+ end
85
+ after { Base.sources.anonymous.deps.clear! }
86
+ end
87
+
88
+ describe "a partially meetable dep tree" do
89
+ before {
90
+ setup_yield_counts
91
+ make_counter_dep :name => 'a', :requires => %w[b c] , :met? => L{ @yield_counts['a'][:met?] > 1 }
92
+ make_counter_dep :name => 'b', :requires => %w[c d e], :met? => L{ @yield_counts['b'][:met?] > 1 }
93
+ make_counter_dep :name => 'c', :requires => %w[f] , :met? => L{ @yield_counts['c'][:met?] > 1 }, :requires_when_unmet => %w[g]
94
+ make_counter_dep :name => 'd', :requires => %w[e f] , :met? => L{ @yield_counts['d'][:met?] > 1 }
95
+ make_counter_dep :name => 'e', :requires => %w[f] , :met? => L{ false }
96
+ make_counter_dep :name => 'f', :met? => L{ @yield_counts['f'][:met?] > 1 }
97
+ make_counter_dep :name => 'g', :met? => L{ @yield_counts['g'][:met?] > 1 }
98
+ }
99
+ it_should_behave_like "met?"
100
+ describe "meet" do
101
+ before { Dep('a').meet }
102
+ it "should meet deps until one fails" do
103
+ %w[c f g].each {|i| @yield_counts[i].should == @yield_counts_meet_run }
104
+ end
105
+ it "should fail on the unmeetable dep" do
106
+ %w[e].each {|i| @yield_counts[i].should == @yield_counts_failed_meet_run }
107
+ end
108
+ it "should bubble the fail up" do
109
+ %w[a b d].each {|i| @yield_counts[i].should == @yield_counts_dep_failed }
110
+ end
111
+ end
112
+ after { Base.sources.anonymous.deps.clear! }
113
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ def stub_env_info
4
+ GemHelper.stub!(:env_info).and_return(%q{
5
+ RubyGems Environment:
6
+ - INSTALLATION DIRECTORY: /Library/Ruby/Gems/1.8
7
+ })
8
+ end
9
+
10
+ def stub_versions_of
11
+ GemHelper.stub!(:versions_of).and_return([
12
+ VersionStr.new('0.2.11'),
13
+ VersionStr.new('0.2.11.3'),
14
+ VersionStr.new('0.3.7'),
15
+ VersionStr.new('0.3.9')
16
+ ])
17
+ end
18
+
19
+ describe "has?" do
20
+ before {
21
+ stub_versions_of
22
+ }
23
+ it "should report installed gems correctly" do
24
+ GemHelper.has?('hammock 0.3.9').should == VersionStr.new('0.3.9')
25
+ end
26
+ it "should report missing gems correctly" do
27
+ GemHelper.has?('hammock 0.3.8').should be_nil
28
+ end
29
+ it "should report matching gems correctly" do
30
+ GemHelper.has?('hammock >= 0.3.10').should be_nil
31
+ GemHelper.has?('hammock >= 0.3.9').should == VersionStr.new('0.3.9')
32
+ GemHelper.has?('hammock >= 0.3.8').should == VersionStr.new('0.3.9')
33
+ GemHelper.has?('hammock >= 0.3.7').should == VersionStr.new('0.3.9')
34
+ GemHelper.has?('hammock ~> 0.2.7').should == VersionStr.new('0.2.11.3')
35
+ GemHelper.has?('hammock ~> 0.3.7').should == VersionStr.new('0.3.9')
36
+ end
37
+ end
38
+
39
+ describe "gem_path_for" do
40
+ before {
41
+ stub_env_info
42
+ stub_versions_of
43
+ @prefix = '/Library/Ruby/Gems/1.8/gems'
44
+ }
45
+ it "should return the correct path" do
46
+ GemHelper.gem_path_for('hammock').should == @prefix / 'hammock-0.3.9'
47
+ GemHelper.gem_path_for('hammock', '0.3.9').should == @prefix / 'hammock-0.3.9'
48
+ GemHelper.gem_path_for('hammock', '~> 0.3.7').should == @prefix / 'hammock-0.3.9'
49
+ GemHelper.gem_path_for('hammock', '0.3.8').should be_nil
50
+ end
51
+ end
52
+
53
+ describe Babushka::GemHelper do
54
+ describe '.should_sudo?' do
55
+ before :each do
56
+ Babushka::GemHelper.stub!(
57
+ :gem_root => '/path/to/gems'.p,
58
+ :bin_path => '/path/to/bins'.p
59
+ )
60
+ end
61
+
62
+ it "should return true if the bin dir is not writeable" do
63
+ File.should_receive(:writable?).with('/path/to/bins').and_return(false)
64
+ Babushka::GemHelper.should_sudo?.should be_true
65
+ end
66
+
67
+ context "when the bin dir is writable" do
68
+ before {
69
+ File.should_receive(:writable?).with('/path/to/bins').and_return(true)
70
+ }
71
+ it "should return false if the gem dir does not exist" do
72
+ Babushka::GemHelper.gem_root.should_receive(:exists?).and_return(false)
73
+ Babushka::GemHelper.should_sudo?.should be_false
74
+ end
75
+ context "when the gem dir exists" do
76
+ before {
77
+ Babushka::GemHelper.gem_root.should_receive(:exists?).and_return(true)
78
+ }
79
+ it "should return true if the gem dir is not writeable" do
80
+ Babushka::GemHelper.gem_root.should_receive(:writable?).and_return(false)
81
+ Babushka::GemHelper.should_sudo?.should be_true
82
+ end
83
+ it "should return false if the gem dir is writeable" do
84
+ Babushka::GemHelper.gem_root.should_receive(:writable?).and_return(true)
85
+ Babushka::GemHelper.should_sudo?.should be_false
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,396 @@
1
+ require 'spec_helper'
2
+
3
+ def stub_commitless_repo name
4
+ (tmp_prefix / 'repos' / name).rm
5
+ cd tmp_prefix / 'repos' / name, :create => true do
6
+ shell "git init"
7
+ end
8
+ end
9
+
10
+ def stub_repo name
11
+ (tmp_prefix / 'repos' / "#{name}_remote").rm
12
+ cd tmp_prefix / 'repos' / "#{name}_remote", :create => true do
13
+ shell "tar -zxvf #{File.dirname(__FILE__) / '../repos/remote.git.tgz'}"
14
+ end
15
+
16
+ (tmp_prefix / 'repos' / name).rm
17
+ cd tmp_prefix / 'repos' do
18
+ shell "git clone #{name}_remote/remote.git #{name}"
19
+ end
20
+ end
21
+
22
+ def repo_context name, &block
23
+ cd(tmp_prefix / 'repos'/ name, &block)
24
+ end
25
+
26
+ describe GitRepo, 'creation' do
27
+ before(:all) { stub_repo 'a' }
28
+ it "should return nil on nonexistent paths" do
29
+ Babushka::GitRepo.new(tmp_prefix / 'repos/nonexistent').root.should == nil
30
+ end
31
+ it "should return nil on non-repo paths" do
32
+ Babushka::GitRepo.new(tmp_prefix / 'repos').root.should == nil
33
+ end
34
+ it "should recognise the repo path as a string" do
35
+ Babushka::GitRepo.new((tmp_prefix / 'repos/a').to_s).root.should == tmp_prefix / 'repos/a'
36
+ end
37
+ it "should recognise the repo path as a Fancypath" do
38
+ Babushka::GitRepo.new(tmp_prefix / 'repos/a').root.should == tmp_prefix / 'repos/a'
39
+ end
40
+ it "should find the parent when called on the subdir" do
41
+ Babushka::GitRepo.new(tmp_prefix / 'repos/a/lib').root.should == tmp_prefix / 'repos/a'
42
+ end
43
+ it "should find the git dir within the repo" do
44
+ Babushka::GitRepo.new(tmp_prefix / 'repos/a').git_dir.should == tmp_prefix / 'repos/a/.git'
45
+ Babushka::GitRepo.new(tmp_prefix / 'repos/a/lib').git_dir.should == tmp_prefix / 'repos/a/.git'
46
+ end
47
+ it "should store path as a Fancypath" do
48
+ Babushka::GitRepo.new((tmp_prefix / 'repos/a').to_s).path.should be_an_instance_of(Fancypath)
49
+ Babushka::GitRepo.new(tmp_prefix / 'repos/a').path.should be_an_instance_of(Fancypath)
50
+ end
51
+ it "should return the repo path as a Fancypath" do
52
+ Babushka::GitRepo.new((tmp_prefix / 'repos/a').to_s).root.should be_an_instance_of(Fancypath)
53
+ Babushka::GitRepo.new(tmp_prefix / 'repos/a').root.should be_an_instance_of(Fancypath)
54
+ end
55
+ end
56
+
57
+ describe GitRepo, 'without a repo' do
58
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/nonexistent') }
59
+ it "should not exist" do
60
+ subject.exists?.should be_false
61
+ end
62
+ [:clean?, :dirty?, :current_branch, :current_head, :remote_branch_exists?, :ahead?].each {|method|
63
+ it "should raise on #{method}" do
64
+ L{ subject.send(method) }.should raise_error(Babushka::GitRepoError, "There is no repo at #{tmp_prefix / 'repos/nonexistent'}.")
65
+ end
66
+ }
67
+ context "with lazy eval" do
68
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/lazy') }
69
+ it "should fail before the repo is created, but work afterwards" do
70
+ subject.exists?.should be_false
71
+ L{ subject.clean? }.should raise_error(Babushka::GitRepoError, "There is no repo at #{tmp_prefix / 'repos/lazy'}.")
72
+ stub_repo 'lazy'
73
+ subject.exists?.should be_true
74
+ subject.should be_clean
75
+ end
76
+ end
77
+ end
78
+
79
+ describe GitRepo, "with a repo" do
80
+ before(:all) { stub_repo 'a' }
81
+ it "should exist with string path" do
82
+ Babushka::GitRepo.new((tmp_prefix / 'repos/a').to_s).exists?.should be_true
83
+ end
84
+ it "should exist with Fancypath path" do
85
+ Babushka::GitRepo.new(tmp_prefix / 'repos/a').exists?.should be_true
86
+ end
87
+ end
88
+
89
+ describe GitRepo, '#clean? / #dirty?' do
90
+ context "on commitless repos" do
91
+ before(:all) { stub_commitless_repo 'a' }
92
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
93
+ it "should be clean" do
94
+ subject.should be_clean
95
+ subject.should_not be_dirty
96
+ end
97
+ end
98
+ context "on normal repos" do
99
+ before(:all) { stub_repo 'a' }
100
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
101
+ it "should be clean" do
102
+ subject.should be_clean
103
+ subject.should_not be_dirty
104
+ end
105
+ context "when there are changes" do
106
+ before {
107
+ cd(tmp_prefix / 'repos/a') { shell "echo dirt >> content.txt" }
108
+ }
109
+ it "should be dirty" do
110
+ subject.should_not be_clean
111
+ subject.should be_dirty
112
+ end
113
+ context "when the changes are staged" do
114
+ before {
115
+ cd(tmp_prefix / 'repos/a') { shell "git add --update ." }
116
+ }
117
+ it "should be dirty" do
118
+ subject.should_not be_clean
119
+ subject.should be_dirty
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ describe GitRepo, '#include?' do
127
+ before(:all) { stub_repo 'a' }
128
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
129
+ it "should return true for valid commits" do
130
+ subject.include?('20758f2d9d696c51ac83a0fd36626d421057b24d').should be_true
131
+ subject.include?('20758f2').should be_true
132
+ end
133
+ it "should return false for nonexistent commits" do
134
+ subject.include?('20758f2d9d696c51ac83a0fd36626d421057b24e').should be_false
135
+ subject.include?('20758f3').should be_false
136
+ end
137
+ end
138
+
139
+ describe GitRepo, '#branches' do
140
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
141
+ context "on a repo with commits" do
142
+ before(:all) { stub_repo 'a' }
143
+ it "should return the only branch in a list" do
144
+ subject.branches.should == ['master']
145
+ end
146
+ context "after creating another branch" do
147
+ before {
148
+ repo_context('a') { shell "git checkout -b next" }
149
+ }
150
+ it "should return both branches" do
151
+ subject.branches.should == ['master', 'next']
152
+ end
153
+ context "after changing back to master" do
154
+ before {
155
+ repo_context('a') { shell "git checkout master" }
156
+ }
157
+ it "should return both branches" do
158
+ subject.branches.should == ['master', 'next']
159
+ end
160
+ end
161
+ end
162
+ end
163
+ context "on a repo with no commits" do
164
+ before { stub_commitless_repo 'a' }
165
+ it "should return no branches" do
166
+ subject.branches.should == []
167
+ end
168
+ end
169
+ end
170
+
171
+ describe GitRepo, '#current_branch' do
172
+ before(:all) { stub_repo 'a' }
173
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
174
+ it "should return 'master'" do
175
+ subject.current_branch.should == 'master'
176
+ end
177
+ context "after creating another branch" do
178
+ before {
179
+ repo_context('a') { shell "git checkout -b next" }
180
+ }
181
+ it "should return 'next'" do
182
+ subject.current_branch.should == 'next'
183
+ end
184
+ context "after changing back to master" do
185
+ before {
186
+ repo_context('a') { shell "git checkout master" }
187
+ }
188
+ it "should return 'next'" do
189
+ subject.current_branch.should == 'master'
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ describe GitRepo, '#current_head' do
196
+ before { stub_repo 'a' }
197
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
198
+ it "should return a short commit id" do
199
+ subject.current_head.should =~ /^[0-9a-f]{7}$/
200
+ end
201
+ end
202
+
203
+ describe GitRepo, '#current_full_head' do
204
+ before { stub_repo 'a' }
205
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
206
+ it "should return a full commit id" do
207
+ subject.current_full_head.should =~ /^[0-9a-f]{40}$/
208
+ end
209
+ end
210
+
211
+ describe GitRepo, '#ahead?' do
212
+ before(:all) {
213
+ stub_repo 'a'
214
+ cd(tmp_prefix / 'repos/a') {
215
+ shell "git checkout -b topic"
216
+ }
217
+ }
218
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
219
+ it "should have a local topic branch" do
220
+ subject.current_branch.should == 'topic'
221
+ end
222
+ it "should return true if the current branch has no remote" do
223
+ subject.remote_branch_exists?.should be_false
224
+ subject.should be_ahead
225
+ end
226
+ context "when remote branch exists" do
227
+ before(:all) {
228
+ cd(tmp_prefix / 'repos/a') {
229
+ shell "git push origin topic"
230
+ shell 'echo "Ch-ch-ch-changes" >> content.txt'
231
+ shell 'git commit -a -m "Changes!"'
232
+ }
233
+ }
234
+ it "should have a local topic branch" do
235
+ subject.current_branch.should == 'topic'
236
+ end
237
+ it "should return true if there are unpushed commits on the current branch" do
238
+ subject.remote_branch_exists?.should be_true
239
+ subject.should be_ahead
240
+ end
241
+ context "when the branch is fully pushed" do
242
+ before {
243
+ cd(tmp_prefix / 'repos/a') {
244
+ shell "git push origin topic"
245
+ }
246
+ }
247
+ it "should not be ahead" do
248
+ subject.remote_branch_exists?.should be_true
249
+ subject.should_not be_ahead
250
+ end
251
+ end
252
+ end
253
+ end
254
+
255
+ describe GitRepo, '#behind?' do
256
+ before(:all) {
257
+ stub_repo 'a'
258
+ cd(tmp_prefix / 'repos/a') {
259
+ shell "git checkout -b next"
260
+ shell "git reset --hard origin/next^"
261
+ }
262
+ }
263
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
264
+ it "should return true if there are new commits on the remote" do
265
+ subject.remote_branch_exists?.should be_true
266
+ subject.should be_behind
267
+ end
268
+ context "when the remote is merged" do
269
+ before {
270
+ cd(tmp_prefix / 'repos/a') {
271
+ shell "git merge origin/next"
272
+ }
273
+ }
274
+ it "should not be behind" do
275
+ subject.remote_branch_exists?.should be_true
276
+ subject.should_not be_behind
277
+ end
278
+ end
279
+ end
280
+
281
+ describe GitRepo, '#clone!' do
282
+ before(:all) { stub_repo 'a' }
283
+ context "for existing repos" do
284
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
285
+ it "should raise" do
286
+ L{
287
+ subject.clone!('a_remote/remote.git')
288
+ }.should raise_error(GitRepoExists, "Can't clone a_remote/remote.git to existing path #{tmp_prefix / 'repos/a'}.")
289
+ end
290
+ end
291
+ context "for non-existent repos" do
292
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/b') }
293
+ it "should not exist yet" do
294
+ subject.exists?.should be_false
295
+ end
296
+ context "when the clone fails" do
297
+ it "should raise" do
298
+ L{
299
+ subject.clone!(tmp_prefix / 'repos/a_remote/nonexistent.git')
300
+ }.should raise_error(GitRepoError)
301
+ end
302
+ end
303
+ context "after cloning" do
304
+ before { subject.clone! "a_remote/remote.git" }
305
+ it "should exist now" do
306
+ subject.exists?.should be_true
307
+ end
308
+ it "should have the correct remote" do
309
+ subject.repo_shell("git remote -v").should == %Q{
310
+ origin\t#{tmp_prefix / 'repos/a_remote/remote.git'} (fetch)
311
+ origin\t#{tmp_prefix / 'repos/a_remote/remote.git'} (push)
312
+ }.strip
313
+ end
314
+ it "should have the remote branch" do
315
+ subject.repo_shell("git branch -a").should == %Q{
316
+ * master
317
+ remotes/origin/HEAD -> origin/master
318
+ remotes/origin/master
319
+ remotes/origin/next
320
+ }.strip
321
+ end
322
+ end
323
+ after {
324
+ shell "rm -rf #{tmp_prefix / 'repos/b'}"
325
+ }
326
+ end
327
+ end
328
+
329
+ describe GitRepo, '#branch!' do
330
+ before(:all) { stub_repo 'a' }
331
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
332
+ it "should not already have a next branch" do
333
+ subject.branches.should_not include('next')
334
+ end
335
+ context "after tracking" do
336
+ before { subject.branch! "next" }
337
+ it "should have created a next branch" do
338
+ subject.branches.should include('next')
339
+ end
340
+ it "should not be tracking anything" do
341
+ subject.repo_shell('git config branch.next.remote').should be_nil
342
+ end
343
+ end
344
+ end
345
+
346
+ describe GitRepo, '#track!' do
347
+ before(:all) { stub_repo 'a' }
348
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
349
+ it "should not already have a next branch" do
350
+ subject.branches.should_not include('next')
351
+ end
352
+ context "after tracking" do
353
+ before { subject.track! "origin/next" }
354
+ it "should have created a next branch" do
355
+ subject.branches.should include('next')
356
+ end
357
+ it "should be tracking origin/next" do
358
+ subject.repo_shell('git config branch.next.remote').should == 'origin'
359
+ end
360
+ end
361
+ end
362
+
363
+ describe GitRepo, '#checkout!' do
364
+ before(:all) {
365
+ stub_repo 'a'
366
+ cd(tmp_prefix / 'repos/a') {
367
+ shell "git checkout -b next"
368
+ }
369
+ }
370
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
371
+ it "should already have a next branch" do
372
+ subject.branches.should =~ %w[master next]
373
+ subject.current_branch.should == 'next'
374
+ end
375
+ context "after checking out" do
376
+ before { subject.checkout! "master" }
377
+ it "should be on the master branch now" do
378
+ subject.current_branch.should == 'master'
379
+ end
380
+ end
381
+ end
382
+
383
+ describe GitRepo, '#reset_hard!' do
384
+ before {
385
+ stub_repo 'a'
386
+ cd(tmp_prefix / 'repos/a') {
387
+ shell "echo 'more rubies' >> lib/rubies.rb"
388
+ }
389
+ }
390
+ subject { Babushka::GitRepo.new(tmp_prefix / 'repos/a') }
391
+ it "should make a dirty repo clean" do
392
+ subject.should be_dirty
393
+ subject.reset_hard!
394
+ subject.should be_clean
395
+ end
396
+ end