update git provider to handle checking out into an existing (empty) dir
[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 empty and not a repository" do
78           it "should raise an exception" do
79             provider.expects(:path_exists?).returns(true)
80             provider.expects(:path_empty?).returns(false)
81             proc { provider.create }.should raise_error(Puppet::Error)
82           end
83         end
84       end
85
86       resource_with :ensure => :bare do
87         context "when the path does not exist" do
88           it "should execute 'git init --bare'" do
89             expects_chdir
90             expects_mkdir
91             expects_directory?(false)
92             provider.expects(:working_copy_exists?).returns(false)
93             provider.expects(:git).with('init', '--bare')
94             provider.create
95           end
96         end
97
98         context "when the path is a working copy repository" do
99           it "should convert it to a bare repository" do
100             provider.expects(:working_copy_exists?).returns(true)
101             provider.expects(:convert_working_copy_to_bare)
102             provider.create
103           end
104         end
105
106         context "when the path is not empty and not a repository" do
107           it "should raise an exception" do
108             expects_directory?(true)
109             provider.expects(:path_empty?).returns(false)
110             proc { provider.create }.should raise_error(Puppet::Error)
111           end
112         end
113       end
114     end
115
116   end
117
118   context 'destroying' do
119     it "it should remove the directory" do
120       expects_rm_rf
121       provider.destroy
122     end
123   end
124
125   context "checking the revision property" do
126     resource_with :revision do
127       before do
128         expects_chdir
129         provider.expects(:git).with('rev-parse', 'HEAD').returns('currentsha')
130       end
131
132       context "when its SHA is not different than the current SHA" do
133         it "should return the ref" do
134           provider.expects(:git).with('config', 'remote.origin.url').returns('')
135           provider.expects(:git).with('fetch', 'origin') # FIXME
136           provider.expects(:git).with('fetch', '--tags', 'origin')
137           provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('currentsha')
138           provider.expects(:git).with('tag', '-l').returns("Hello")
139           provider.revision.should == resource.value(:revision)
140         end
141       end
142
143       context "when its SHA is different than the current SHA" do
144         it "should return the current SHA" do
145           provider.expects(:git).with('config', 'remote.origin.url').returns('')
146           provider.expects(:git).with('fetch', 'origin') # FIXME
147           provider.expects(:git).with('fetch', '--tags', 'origin')
148           provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('othersha')
149           provider.expects(:git).with('tag', '-l').returns("Hello")
150           provider.revision.should == 'currentsha'
151         end
152       end
153
154       context "when its a ref to a remote head" do
155         it "should return the revision" do
156           provider.expects(:git).with('config', 'remote.origin.url').returns('')
157           provider.expects(:git).with('fetch', 'origin') # FIXME
158           provider.expects(:git).with('fetch', '--tags', 'origin')
159           provider.expects(:git).with('tag', '-l').returns("Hello")
160           provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('')
161           provider.expects(:git).with('ls-remote', '--heads', '--tags', 'origin', resource.value(:revision)).returns("newsha refs/heads/#{resource.value(:revision)}")
162           provider.revision.should == 'currentsha'
163         end
164       end
165
166       context "when its a ref to non existant remote head" do
167         it "should fail" do
168           provider.expects(:git).with('config', 'remote.origin.url').returns('')
169           provider.expects(:git).with('fetch', 'origin') # FIXME
170           provider.expects(:git).with('fetch', '--tags', 'origin')
171           provider.expects(:git).with('tag', '-l').returns("Hello")
172           provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('')
173           provider.expects(:git).with('ls-remote', '--heads', '--tags', 'origin', resource.value(:revision)).returns('')
174           expect { provider.revision }.should raise_error(Puppet::Error, /not a local or remote ref$/)
175         end
176       end
177
178       context "when the source is modified" do
179         resource_with :source => 'git://git@foo.com/bar.git' do
180           it "should update the origin url" do
181             provider.expects(:git).with('config', 'remote.origin.url').returns('old')
182             provider.expects(:git).with('config', 'remote.origin.url', 'git://git@foo.com/bar.git')
183             provider.expects(:git).with('fetch', 'origin') # FIXME
184             provider.expects(:git).with('fetch', '--tags', 'origin')
185             provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('currentsha')
186             provider.expects(:git).with('tag', '-l').returns("Hello")
187             provider.revision.should == resource.value(:revision)
188           end
189         end
190       end
191     end
192   end
193
194   context "setting the revision property" do
195     before do
196       expects_chdir
197     end
198     context "when it's an existing local branch", :resource => {:revision => 'feature/foo'} do
199       it "should use 'git fetch' and 'git reset'" do
200         provider.expects(:update_submodules)
201         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
202         provider.expects(:git).with('checkout', '--force', resource.value(:revision))
203         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
204         provider.expects(:git).with('reset', '--hard', "origin/#{resource.value(:revision)}")
205         provider.revision = resource.value(:revision)
206       end
207     end
208     context "when it's a remote branch", :resource => {:revision => 'only/remote'} do
209       it "should use 'git fetch' and 'git reset'" do
210         provider.expects(:update_submodules)
211         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
212         provider.expects(:git).with('checkout', '--force', resource.value(:revision))
213         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
214         provider.expects(:git).with('reset', '--hard', "origin/#{resource.value(:revision)}")
215         provider.revision = resource.value(:revision)
216       end
217     end
218     context "when it's a commit or tag", :resource => {:revision => 'a-commit-or-tag'} do
219       it "should use 'git fetch' and 'git reset'" do
220         provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
221         provider.expects(:git).with('checkout', '--force', resource.value(:revision))
222         provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
223         provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
224         provider.expects(:git).with('submodule', 'update', '--init', '--recursive')
225         provider.revision = resource.value(:revision)
226       end
227     end
228   end
229
230   context "updating references" do
231     it "should use 'git fetch --tags'" do
232       expects_chdir
233       provider.expects(:git).with('config', 'remote.origin.url').returns('')
234       provider.expects(:git).with('fetch', 'origin')
235       provider.expects(:git).with('fetch', '--tags', 'origin')
236       provider.update_references
237     end
238   end
239
240   context "checking if revision" do
241     before do
242       expects_chdir
243       provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
244     end
245     context "is a local branch" do
246       context "when it's listed in 'git branch -a'", :resource => {:revision => 'feature/foo'} do
247         it "should return true" do
248           provider.should be_local_branch_revision
249         end
250       end
251       context "when it's not listed in 'git branch -a'" , :resource => {:revision => 'feature/notexist'}do
252         it "should return false" do
253           provider.should_not be_local_branch_revision
254         end
255       end
256     end
257     context "is a remote branch" do
258       context "when it's listed in 'git branch -a' with an 'origin/' prefix", :resource => {:revision => 'only/remote'} do
259         it "should return true" do
260           provider.should be_remote_branch_revision
261         end
262       end
263       context "when it's not listed in 'git branch -a' with an 'origin/' prefix" , :resource => {:revision => 'only/local'}do
264         it "should return false" do
265           provider.should_not be_remote_branch_revision
266         end
267       end
268     end
269   end
270
271 end