Merge pull request #78 from jhoblitt/git_provider_checkout_remote_refs
[puppet_vcsrepo.git] / spec / unit / puppet / provider / vcsrepo / git_spec.rb
1 require 'spec_helper'
2
3 describe_provider :vcsrepo, :git, :resource => {:path => '/tmp/vcsrepo'} do
4
5   context 'creating' do
6     resource_with :source do
7       resource_with :ensure => :present do
8         context "with a revision that is a remote branch", :resource => {:revision => 'only/remote'} do
9           it "should execute 'git clone' and 'git checkout -b'" do
10             provider.expects(:git).with('clone', resource.value(:source), resource.value(:path))
11             expects_chdir('/')
12             expects_chdir
13             provider.expects(:update_submodules)
14             provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
15             provider.expects(:git).with('checkout', '--force', resource.value(:revision))
16             provider.create
17           end
18         end
19         context "with a revision that is not a remote branch", :resource => {:revision => 'a-commit-or-tag'} do
20           it "should execute 'git clone' and 'git reset --hard'" do
21             provider.expects(:git).with('clone', resource.value(:source), resource.value(:path))
22             expects_chdir('/')
23             expects_chdir
24             provider.expects(:update_submodules)
25             provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
26             provider.expects(:git).with('checkout', '--force', resource.value(:revision))
27             provider.create
28           end
29         end
30         resource_without :revision do
31           it "should execute 'git clone' and submodule commands" do
32             provider.expects(:git).with('clone', resource.value(:source), resource.value(:path))
33             provider.expects(:update_submodules)
34             provider.create
35           end
36         end
37       end
38
39       resource_with :ensure => :bare do
40         resource_with :revision do
41           it "should just execute 'git clone --bare'" do
42             provider.expects(:git).with('clone', '--bare', resource.value(:source), resource.value(:path))
43             provider.create
44           end
45         end
46
47         resource_without :revision do
48           it "should just execute 'git clone --bare'" do
49             provider.expects(:git).with('clone', '--bare', resource.value(:source), resource.value(:path))
50             provider.create
51           end
52         end
53       end
54     end
55
56     context "when a source is not given" do
57       resource_with :ensure => :present do
58         context "when the path does not exist" do
59           it "should execute 'git init'" do
60             expects_mkdir
61             expects_chdir
62             expects_directory?(false)
63             provider.expects(:bare_exists?).returns(false)
64             provider.expects(:git).with('init')
65             provider.create
66           end
67         end
68
69         context "when the path is a bare repository" do
70           it "should convert it to a working copy" do
71             provider.expects(:bare_exists?).returns(true)
72             provider.expects(:convert_bare_to_working_copy)
73             provider.create
74           end
75         end
76
77         context "when the path is not a repository" do
78           it "should raise an exception" do
79             provider.expects(:path_exists?).returns(true)
80             proc { provider.create }.should raise_error(Puppet::Error)
81           end
82         end
83       end
84
85       resource_with :ensure => :bare do
86         context "when the path does not exist" do
87           it "should execute 'git init --bare'" do
88             expects_chdir
89             expects_mkdir
90             expects_directory?(false)
91             provider.expects(:working_copy_exists?).returns(false)
92             provider.expects(:git).with('init', '--bare')
93             provider.create
94           end
95         end
96
97         context "when the path is a working copy repository" do
98           it "should convert it to a bare repository" do
99             provider.expects(:working_copy_exists?).returns(true)
100             provider.expects(:convert_working_copy_to_bare)
101             provider.create
102           end
103         end
104
105         context "when the path is not a repository" do
106           it "should raise an exception" do
107             expects_directory?(true)
108             proc { provider.create }.should raise_error(Puppet::Error)
109           end
110         end
111       end
112     end
113
114   end
115
116   context 'destroying' do
117     it "it should remove the directory" do
118       expects_rm_rf
119       provider.destroy
120     end
121   end
122
123   context "checking the revision property" do
124     resource_with :revision do
125       before do
126         expects_chdir
127         provider.expects(:git).with('rev-parse', 'HEAD').returns('currentsha')
128       end
129
130       context "when its SHA is not different than the current SHA" do
131         it "should return the ref" do
132           provider.expects(:git).with('config', 'remote.origin.url').returns('')
133           provider.expects(:git).with('fetch', 'origin') # FIXME
134           provider.expects(:git).with('fetch', '--tags', 'origin')
135           provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('currentsha')
136           provider.expects(:git).with('tag', '-l').returns("Hello")
137           provider.revision.should == resource.value(:revision)
138         end
139       end
140
141       context "when its SHA is different than the current SHA" do
142         it "should return the current SHA" do
143           provider.expects(:git).with('config', 'remote.origin.url').returns('')
144           provider.expects(:git).with('fetch', 'origin') # FIXME
145           provider.expects(:git).with('fetch', '--tags', 'origin')
146           provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('othersha')
147           provider.expects(:git).with('tag', '-l').returns("Hello")
148           provider.revision.should == 'currentsha'
149         end
150       end
151
152       context "when its a ref to a remote head" do
153         it "should return the revision" do
154           provider.expects(:git).with('config', 'remote.origin.url').returns('')
155           provider.expects(:git).with('fetch', 'origin') # FIXME
156           provider.expects(:git).with('fetch', '--tags', 'origin')
157           provider.expects(:git).with('tag', '-l').returns("Hello")
158           provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('')
159           provider.expects(:git).with('ls-remote', '--heads', '--tags', 'origin', resource.value(:revision)).returns("newsha refs/heads/#{resource.value(:revision)}")
160           provider.revision.should == 'currentsha'
161         end
162       end
163
164       context "when its a ref to non existant remote head" do
165         it "should fail" do
166           provider.expects(:git).with('config', 'remote.origin.url').returns('')
167           provider.expects(:git).with('fetch', 'origin') # FIXME
168           provider.expects(:git).with('fetch', '--tags', 'origin')
169           provider.expects(:git).with('tag', '-l').returns("Hello")
170           provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('')
171           provider.expects(:git).with('ls-remote', '--heads', '--tags', 'origin', resource.value(:revision)).returns('')
172           expect { provider.revision }.should raise_error(Puppet::Error, /not a local or remote ref$/)
173         end
174       end
175
176       context "when the source is modified" do
177         resource_with :source => 'git://git@foo.com/bar.git' do
178           it "should update the origin url" do
179             provider.expects(:git).with('config', 'remote.origin.url').returns('old')
180             provider.expects(:git).with('config', 'remote.origin.url', 'git://git@foo.com/bar.git')
181             provider.expects(:git).with('fetch', 'origin') # FIXME
182             provider.expects(:git).with('fetch', '--tags', 'origin')
183             provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('currentsha')
184             provider.expects(:git).with('tag', '-l').returns("Hello")
185             provider.revision.should == resource.value(:revision)
186           end
187         end
188       end
189     end
190   end
191
192   context "setting the revision property" do
193     before do
194       expects_chdir
195     end
196     context "when it's an existing local branch", :resource => {:revision => 'feature/foo'} do
197       it "should use 'git fetch' and 'git reset'" do
198         provider.expects(:update_submodules)
199         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
200         provider.expects(:git).with('checkout', '--force', resource.value(:revision))
201         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
202         provider.expects(:git).with('reset', '--hard', "origin/#{resource.value(:revision)}")
203         provider.revision = resource.value(:revision)
204       end
205     end
206     context "when it's a remote branch", :resource => {:revision => 'only/remote'} do
207       it "should use 'git fetch' and 'git reset'" do
208         provider.expects(:update_submodules)
209         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
210         provider.expects(:git).with('checkout', '--force', resource.value(:revision))
211         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
212         provider.expects(:git).with('reset', '--hard', "origin/#{resource.value(:revision)}")
213         provider.revision = resource.value(:revision)
214       end
215     end
216     context "when it's a commit or tag", :resource => {:revision => 'a-commit-or-tag'} do
217       it "should use 'git fetch' and 'git reset'" do
218         provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
219         provider.expects(:git).with('checkout', '--force', resource.value(:revision))
220         provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
221         provider.expects(:git).with('submodule', 'init')
222         provider.expects(:git).with('submodule', 'update')
223         provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
224         provider.expects(:git).with('submodule', 'foreach', 'git', 'submodule', 'init')
225         provider.expects(:git).with('submodule', 'foreach', 'git', 'submodule', 'update')
226         provider.revision = resource.value(:revision)
227       end
228     end
229   end
230
231   context "updating references" do
232     it "should use 'git fetch --tags'" do
233       expects_chdir
234       provider.expects(:git).with('config', 'remote.origin.url').returns('')
235       provider.expects(:git).with('fetch', 'origin')
236       provider.expects(:git).with('fetch', '--tags', 'origin')
237       provider.update_references
238     end
239   end
240
241   context "checking if revision" do
242     before do
243       expects_chdir
244       provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
245     end
246     context "is a local branch" do
247       context "when it's listed in 'git branch -a'", :resource => {:revision => 'feature/foo'} do
248         it "should return true" do
249           provider.should be_local_branch_revision
250         end
251       end
252       context "when it's not listed in 'git branch -a'" , :resource => {:revision => 'feature/notexist'}do
253         it "should return false" do
254           provider.should_not be_local_branch_revision
255         end
256       end
257     end
258     context "is a remote branch" do
259       context "when it's listed in 'git branch -a' with an 'origin/' prefix", :resource => {:revision => 'only/remote'} do
260         it "should return true" do
261           provider.should be_remote_branch_revision
262         end
263       end
264       context "when it's not listed in 'git branch -a' with an 'origin/' prefix" , :resource => {:revision => 'only/local'}do
265         it "should return false" do
266           provider.should_not be_remote_branch_revision
267         end
268       end
269     end
270   end
271
272 end