r10k 1.2.4 → 1.3.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +8 -8
  2. data/{CHANGELOG → CHANGELOG.mkd} +51 -41
  3. data/doc/dynamic-environments/configuration.mkd +1 -1
  4. data/doc/dynamic-environments/git-environments.markdown +19 -0
  5. data/doc/dynamic-environments/usage.mkd +6 -0
  6. data/lib/r10k/cli/deploy.rb +15 -0
  7. data/lib/r10k/cli/ext/logging.rb +0 -1
  8. data/lib/r10k/cli/module/deploy.rb +0 -1
  9. data/lib/r10k/cli/puppetfile.rb +2 -2
  10. data/lib/r10k/cli.rb +2 -16
  11. data/lib/r10k/deployment/environment.rb +9 -79
  12. data/lib/r10k/deployment/source.rb +15 -89
  13. data/lib/r10k/deployment.rb +13 -14
  14. data/lib/r10k/environment/base.rb +42 -0
  15. data/lib/r10k/environment/git.rb +79 -0
  16. data/lib/r10k/environment/svn.rb +73 -0
  17. data/lib/r10k/environment.rb +7 -0
  18. data/lib/r10k/execution.rb +0 -1
  19. data/lib/r10k/git/cache.rb +11 -5
  20. data/lib/r10k/git/repository.rb +1 -8
  21. data/lib/r10k/git/working_dir.rb +11 -34
  22. data/lib/r10k/git.rb +0 -1
  23. data/lib/r10k/instance_cache.rb +32 -0
  24. data/lib/r10k/keyed_factory.rb +39 -0
  25. data/lib/r10k/module/forge.rb +2 -3
  26. data/lib/r10k/module/svn.rb +0 -1
  27. data/lib/r10k/puppetfile.rb +0 -1
  28. data/lib/r10k/registry.rb +3 -31
  29. data/lib/r10k/source/base.rb +60 -0
  30. data/lib/r10k/source/git.rb +195 -0
  31. data/lib/r10k/source/svn.rb +140 -0
  32. data/lib/r10k/source.rb +39 -0
  33. data/lib/r10k/svn/remote.rb +48 -0
  34. data/lib/r10k/svn/working_dir.rb +0 -2
  35. data/lib/r10k/svn.rb +6 -0
  36. data/lib/r10k/task/deployment.rb +1 -2
  37. data/lib/r10k/task.rb +0 -2
  38. data/lib/r10k/task_runner.rb +0 -1
  39. data/lib/r10k/util/core_ext/hash_ext.rb +19 -0
  40. data/lib/r10k/util/subprocess.rb +0 -1
  41. data/lib/r10k/version.rb +1 -1
  42. data/lib/r10k.rb +1 -0
  43. data/spec/unit/deployment/environment_spec.rb +16 -15
  44. data/spec/unit/environment/git_spec.rb +81 -0
  45. data/spec/unit/environment/svn_spec.rb +76 -0
  46. data/spec/unit/git/repository_spec.rb +0 -10
  47. data/spec/unit/git/working_dir_spec.rb +1 -110
  48. data/spec/unit/{registry_spec.rb → instance_cache_spec.rb} +3 -3
  49. data/spec/unit/keyed_factory_spec.rb +51 -0
  50. data/spec/unit/source/git_spec.rb +274 -0
  51. data/spec/unit/source/svn_spec.rb +102 -0
  52. data/spec/unit/source_spec.rb +10 -0
  53. data/spec/unit/svn/remote_spec.rb +21 -0
  54. data/spec/unit/util/core_ext/hash_ext_spec.rb +63 -0
  55. metadata +36 -10
  56. data/lib/r10k/git/alternates.rb +0 -49
  57. data/spec/unit/git/alternates_spec.rb +0 -90
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'r10k/environment'
3
+
4
+ describe R10K::Environment::SVN do
5
+
6
+ subject do
7
+ described_class.new(
8
+ 'myenv',
9
+ '/some/nonexistent/environmentdir',
10
+ 'svn-dirname',
11
+ {
12
+ :remote => 'https://svn-server.site/svn-repo/trunk'
13
+ }
14
+ )
15
+ end
16
+
17
+ let(:working_dir) { subject.working_dir }
18
+
19
+ describe "storing attributes" do
20
+ it "can return the environment name" do
21
+ expect(subject.name).to eq 'myenv'
22
+ end
23
+
24
+ it "can return the environment basedir" do
25
+ expect(subject.basedir).to eq '/some/nonexistent/environmentdir'
26
+ end
27
+
28
+ it "can return the environment dirname" do
29
+ expect(subject.dirname).to eq 'svn-dirname'
30
+ end
31
+
32
+ it "can return the environment remote" do
33
+ expect(subject.remote).to eq 'https://svn-server.site/svn-repo/trunk'
34
+ end
35
+ end
36
+
37
+ describe "synchronizing the environment" do
38
+ it "updates all modules when creating a new environment" do
39
+ allow(working_dir).to receive(:is_svn?).and_return(false)
40
+ expect(working_dir).to receive(:checkout)
41
+ expect(subject).to receive(:sync_modules)
42
+ subject.sync
43
+ end
44
+
45
+ it "does not update all modules when updating an existing environment" do
46
+ allow(working_dir).to receive(:is_svn?).and_return(true)
47
+ expect(working_dir).to receive(:update)
48
+ expect(subject).to_not receive(:sync_modules)
49
+ subject.sync
50
+ end
51
+ end
52
+
53
+ describe "generating a puppetfile for the environment" do
54
+ let(:puppetfile) { subject.puppetfile }
55
+
56
+ it "creates a puppetfile at the full path to the environment" do
57
+ expect(puppetfile.basedir).to eq '/some/nonexistent/environmentdir/svn-dirname'
58
+ end
59
+
60
+ it "sets the moduledir to 'modules' relative to the environment path" do
61
+ expect(puppetfile.moduledir).to eq '/some/nonexistent/environmentdir/svn-dirname/modules'
62
+ end
63
+
64
+ it "sets the puppetfile path to 'Puppetfile' relative to the environment path" do
65
+ expect(puppetfile.puppetfile_path).to eq '/some/nonexistent/environmentdir/svn-dirname/Puppetfile'
66
+ end
67
+ end
68
+
69
+ describe "enumerating modules" do
70
+ it "loads the Puppetfile and returns modules in that puppetfile" do
71
+ expect(subject.puppetfile).to receive(:load)
72
+ expect(subject.puppetfile).to receive(:modules).and_return [:modules]
73
+ expect(subject.modules).to eq([:modules])
74
+ end
75
+ end
76
+ end
@@ -21,14 +21,4 @@ describe R10K::Git::Repository do
21
21
  })
22
22
  end
23
23
  end
24
-
25
- describe "tags" do
26
- let(:tags) { %w[0.1.1 0.1.2 0.1.3 0.1.4 0.2.0 0.3.0 2.0.0] }
27
- let(:output) { tags.map {|x| x + "\n"}.join }
28
-
29
- it "returns a list of tags for this repo" do
30
- expect(subject).to receive(:git).with(%w[tag -l], anything).and_return(double(:stdout => output))
31
- expect(subject.tags).to eq(tags)
32
- end
33
- end
34
24
  end
@@ -2,120 +2,11 @@ require 'spec_helper'
2
2
  require 'r10k/git'
3
3
 
4
4
  describe R10K::Git::WorkingDir do
5
- include_context "fail on execution"
6
5
 
7
6
  describe "initializing" do
8
7
  it "generates a new cache for the remote" do
9
- wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir')
8
+ wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/tmp')
10
9
  wd.cache.should be_kind_of R10K::Git::Cache
11
10
  end
12
-
13
- it "uses the provided ref as the dirname when no dirname is given" do
14
- wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir')
15
- expect(wd.dirname).to eq('master')
16
- end
17
-
18
- it "uses an explicit dirname when given" do
19
- wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir', 'mydir')
20
- expect(wd.dirname).to eq('mydir')
21
- end
22
- end
23
-
24
- describe "synchronizing the working directory" do
25
- subject { described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir') }
26
- it "clones the repository when the repository doesn't exist" do
27
- expect(subject).to receive(:cloned?).and_return false
28
- expect(subject).to receive(:clone)
29
- subject.sync
30
- end
31
-
32
- it "updates the repository when the repository already exists" do
33
- expect(subject).to receive(:cloned?).and_return true
34
- expect(subject).to receive(:update)
35
- subject.sync
36
- end
37
- end
38
-
39
- describe "when cloning a new repository" do
40
- subject { described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir') }
41
-
42
- before do
43
- allow(subject).to receive(:cloned?).and_return false
44
- end
45
-
46
- it "updates the cache before cloning" do
47
- expect(subject.cache).to receive(:sync)
48
- allow(subject).to receive(:git)
49
- allow(subject).to receive(:checkout)
50
- subject.sync
51
- end
52
-
53
- it "clones the repository and uses the cache git dir as an object reference" do
54
- allow(subject.cache).to receive(:sync)
55
- expect(subject).to receive(:git).with(['clone', '--reference', subject.cache.git_dir,
56
- 'git://github.com/adrienthebo/r10k-fixture-repo',
57
- '/some/nonexistent/dir/master'])
58
- expect(subject).to receive(:git).with(['remote', 'add', 'cache', subject.cache.git_dir],
59
- an_instance_of(Hash))
60
-
61
- expect(subject).to receive(:git).with(['fetch', 'cache'], an_instance_of(Hash))
62
- allow(subject).to receive(:checkout)
63
- subject.sync
64
- end
65
-
66
- it 'checks out the specific ref after the clone' do
67
- allow(subject.cache).to receive(:sync)
68
- allow(subject).to receive(:git)
69
- expect(subject).to receive(:checkout)
70
- subject.sync
71
- end
72
- end
73
-
74
- describe "updating an existing repository" do
75
- subject { described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir') }
76
-
77
- before do
78
- allow(subject).to receive(:cloned?).and_return true
79
- end
80
-
81
- it "updates the remotes when they are out of sync" do
82
- allow(subject).to receive(:ref_needs_fetch?).and_return false
83
- allow(subject).to receive(:needs_checkout?).and_return false
84
-
85
- expect(subject).to receive(:update_remotes?).and_return true
86
- expect(subject).to receive(:update_remotes)
87
-
88
- subject.sync
89
- end
90
-
91
- it "updates the cache when the ref requires an update" do
92
- allow(subject).to receive(:update_remotes?).and_return false
93
-
94
- expect(subject).to receive(:ref_needs_fetch?).and_return true
95
- expect(subject).to receive(:fetch_from_cache)
96
- expect(subject).to receive(:checkout).with(an_instance_of(R10K::Git::Ref))
97
-
98
- subject.sync
99
- end
100
-
101
- it "checks out the ref when the wrong commit is checked out" do
102
- allow(subject).to receive(:update_remotes?).and_return false
103
- allow(subject).to receive(:ref_needs_fetch?).and_return false
104
-
105
- expect(subject).to receive(:needs_checkout?).and_return true
106
- expect(subject).to receive(:checkout).with(an_instance_of(R10K::Git::Ref))
107
-
108
- subject.sync
109
- end
110
-
111
- it "doesn't update the repo when everything is in sync" do
112
- allow(subject).to receive(:update_remotes?).and_return false
113
- allow(subject).to receive(:ref_needs_fetch?).and_return false
114
- allow(subject).to receive(:needs_checkout?).and_return false
115
-
116
- expect(subject).to_not receive(:checkout)
117
-
118
- subject.sync
119
- end
120
11
  end
121
12
  end
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'r10k/registry'
3
+ require 'r10k/instance_cache'
4
4
 
5
- describe R10K::Registry do
5
+ describe R10K::InstanceCache do
6
6
 
7
- describe "setting up a new registry" do
7
+ describe "setting up a new instance cache" do
8
8
  let(:klass) do
9
9
  dubs = double('test class')
10
10
  allow(dubs).to receive(:new) { |*args| args }
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'r10k/keyed_factory'
3
+
4
+ describe R10K::KeyedFactory do
5
+
6
+ let(:registered) { Class.new }
7
+
8
+ describe "registering implementations" do
9
+ it "can register new implementations" do
10
+ subject.register(:klass, registered)
11
+ expect(subject.retrieve(:klass)).to eq registered
12
+ end
13
+
14
+ it "raises an error when a duplicate implementation is registered" do
15
+ subject.register(:klass, registered)
16
+
17
+ expect {
18
+ subject.register(:klass, registered)
19
+ }.to raise_error(R10K::KeyedFactory::DuplicateImplementationError)
20
+ end
21
+
22
+ it "can register classes with nil as a key" do
23
+ subject.register(nil, registered)
24
+ expect(subject.retrieve(nil)).to eq registered
25
+ end
26
+ end
27
+
28
+ describe "generating instances" do
29
+ before do
30
+ subject.register(:klass, registered)
31
+ end
32
+
33
+ it "generates an instance with the associated class" do
34
+ instance = subject.generate(:klass)
35
+ expect(instance).to be_a_kind_of registered
36
+ end
37
+
38
+ it "can generate a class with nil as a key" do
39
+ other = Class.new
40
+ subject.register(nil, other)
41
+ instance = subject.generate(nil)
42
+ expect(instance).to be_a_kind_of other
43
+ end
44
+
45
+ it "raises an error if no implementation was registered with the given key" do
46
+ expect {
47
+ subject.generate(:foo)
48
+ }.to raise_error(R10K::KeyedFactory::UnknownImplementationError)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,274 @@
1
+ require 'spec_helper'
2
+ require 'r10k/source'
3
+
4
+ describe R10K::Source::Git do
5
+
6
+ subject do
7
+ described_class.new('mysource', '/some/nonexistent/dir',
8
+ {:remote => 'https://git-server/repo.git'})
9
+ end
10
+
11
+ it "stores the name" do
12
+ expect(subject.name).to eq 'mysource'
13
+ end
14
+
15
+ it "stores the basedir" do
16
+ expect(subject.basedir).to eq '/some/nonexistent/dir'
17
+ end
18
+
19
+ describe "preloading" do
20
+ it "fetches the git cache" do
21
+ expect(subject.cache).to receive(:sync)
22
+ subject.preload!
23
+ end
24
+ end
25
+
26
+ describe "lazily generating environments" do
27
+ it "returns an empty list of environments when the cache has not been created" do
28
+ allow(subject.cache).to receive(:cached?).and_return false
29
+ expect(subject.environments).to be_empty
30
+ end
31
+
32
+ it "generates environments when the cache is present and environments have not been loaded" do
33
+ allow(subject.cache).to receive(:cached?).and_return true
34
+ allow(subject).to receive(:generate_environments).and_return %w[hi]
35
+ expect(subject.environments).to have(1).items
36
+ end
37
+
38
+ it "doesn't recreate environments if they have already been loaded" do
39
+ allow(subject.cache).to receive(:cached?).and_return true
40
+ allow(subject).to receive(:generate_environments).once.and_return %w[hi]
41
+ expect(subject.environments).to have(1).items
42
+ expect(subject.environments).to have(1).items
43
+ end
44
+ end
45
+
46
+ describe "eagerly generating environments" do
47
+ before do
48
+ allow(subject.cache).to receive(:branches).and_return %w[master]
49
+ end
50
+
51
+ let(:master_env) { subject.generate_environments.first }
52
+
53
+ it "creates an environment for each branch" do
54
+ expect(subject.generate_environments).to have(1).items
55
+ end
56
+
57
+ it "copies the source remote to the environment" do
58
+ expect(master_env.remote).to eq subject.remote
59
+ end
60
+
61
+ it "uses the branch name as the directory by default" do
62
+ expect(master_env.dirname).to eq 'master'
63
+ end
64
+ end
65
+ end
66
+
67
+ describe R10K::Source::Git, "handling invalid branch names" do
68
+ %w[correct_and_warn correct].each do |setting|
69
+ describe "when invalid is #{setting}" do
70
+ subject do
71
+ described_class.new('/some/nonexistent/dir', 'mysource', {
72
+ :remote => 'https://git-server/repo.git',
73
+ :invalid_branches => setting
74
+ })
75
+ end
76
+
77
+ before do
78
+ allow(subject.cache).to receive(:branches).and_return ['master', 'invalid-branch']
79
+ end
80
+
81
+ it "creates an environment for each branch" do
82
+ expect(subject.generate_environments).to have(2).items
83
+ end
84
+
85
+ it "removes invalid characters from branch names" do
86
+ invalid_env = subject.generate_environments.last
87
+ expect(invalid_env.dirname).to eq 'invalid_branch'
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "when invalid is 'error'" do
93
+ subject do
94
+ described_class.new('/some/nonexistent/dir', 'mysource', {
95
+ :remote => 'https://git-server/repo.git',
96
+ :invalid_branches => 'error',
97
+ })
98
+ end
99
+
100
+ before do
101
+ allow(subject.cache).to receive(:branches).and_return ['master', 'invalid-branch']
102
+ end
103
+
104
+ it "only creates an environment for valid branches" do
105
+ expect(subject.generate_environments).to have(1).items
106
+ end
107
+ end
108
+ end
109
+
110
+ # Since prefixing is an immutable property of a source, it's easier to create
111
+ # a new context and duplicate stubs in a single location rather than packing a
112
+ # single test with all the stubs that entirely recreate the source.
113
+ describe R10K::Source::Git, 'when prefixing is enabled' do
114
+ subject do
115
+ described_class.new(
116
+ 'prefixed',
117
+ '/some/nonexistent/dir',
118
+ {
119
+ :prefix => true,
120
+ :remote => 'https://git-server/repo.git',
121
+ })
122
+ end
123
+
124
+ describe "generating prefixed environments" do
125
+ before do
126
+ allow(subject.cache).to receive(:cached?).and_return true
127
+ allow(subject.cache).to receive(:branches).and_return %w[master other]
128
+ end
129
+
130
+ let(:environments) { subject.environments }
131
+
132
+ it "creates an environment for each branch" do
133
+ expect(subject.environments).to have(2).items
134
+ end
135
+
136
+ it "prefixes the source name to environments when prefixing is enabled" do
137
+ expect(environments[0].dirname).to eq 'prefixed_master'
138
+ expect(environments[1].dirname).to eq 'prefixed_other'
139
+ end
140
+ end
141
+ end
142
+
143
+ describe R10K::Source::Git, 'registering as a source' do
144
+ it "registers with the :git key" do
145
+ expect(R10K::Source.retrieve(:git)).to eq described_class
146
+ end
147
+
148
+ it "registers with the nil key" do
149
+ expect(R10K::Source.retrieve(nil)).to eq described_class
150
+ end
151
+ end
152
+
153
+ describe R10K::Source::Git::BranchName do
154
+ describe "prefixing" do
155
+ it "uses the branch name as the dirname when prefixing is off" do
156
+ bn = described_class.new('mybranch', {:prefix => false, :sourcename => 'foo'})
157
+ expect(bn.dirname).to eq 'mybranch'
158
+ end
159
+
160
+ it "prepends the source name when prefixing is on" do
161
+ bn = described_class.new('mybranch', {:prefix => true, :sourcename => 'foo'})
162
+ expect(bn.dirname).to eq 'foo_mybranch'
163
+ end
164
+ end
165
+
166
+ describe "determining the validate behavior with :invalid" do
167
+ [
168
+ ['correct_and_warn', {:validate => true, :correct => true}],
169
+ ['correct', {:validate => false, :correct => true}],
170
+ ['error', {:validate => true, :correct => false}],
171
+ ].each do |(setting, outcome)|
172
+ it "treats #{setting} as #{outcome.inspect}" do
173
+ bn = described_class.new('mybranch', {:invalid => setting})
174
+ expect(bn.validate?).to eq outcome[:validate]
175
+ expect(bn.correct?).to eq outcome[:correct]
176
+ end
177
+ end
178
+ end
179
+
180
+ describe "determining if a branch is a valid environment name" do
181
+ invalid_cases = [
182
+ 'hyphenated-branch',
183
+ 'dotted.branch',
184
+ 'slashed/branch',
185
+ 'at@branch',
186
+ 'http://branch'
187
+ ]
188
+
189
+ valid_cases = [
190
+ 'my_branchname',
191
+ 'my_issue_346',
192
+ ]
193
+
194
+ describe "and validate is false" do
195
+ invalid_cases.each do |branch|
196
+ it "is valid if the branch is #{branch}" do
197
+ bn = described_class.new(branch, {:validate => false})
198
+ expect(bn).to be_valid
199
+ end
200
+ end
201
+
202
+ valid_cases.each do |branch|
203
+ it "is valid if the branch is #{branch}" do
204
+ bn = described_class.new(branch, {:validate => false})
205
+ expect(bn).to be_valid
206
+ end
207
+ end
208
+ end
209
+
210
+ describe "and validate is true" do
211
+ invalid_cases.each do |branch|
212
+ it "is invalid if the branch is #{branch}" do
213
+ bn = described_class.new(branch, {:validate => true})
214
+ expect(bn).to_not be_valid
215
+ end
216
+ end
217
+
218
+ valid_cases.each do |branch|
219
+ it "is valid if the branch is #{branch}" do
220
+ bn = described_class.new(branch, {:validate => true})
221
+ expect(bn).to be_valid
222
+ end
223
+ end
224
+
225
+ end
226
+ end
227
+
228
+ describe "correcting branch names" do
229
+ invalid_cases = [
230
+ 'hyphenated-branch',
231
+ 'dotted.branch',
232
+ 'slashed/branch',
233
+ 'at@branch',
234
+ 'http://branch'
235
+ ]
236
+
237
+ valid_cases = [
238
+ 'my_branchname',
239
+ 'my_issue_346',
240
+ ]
241
+
242
+ describe "and correct is false" do
243
+ invalid_cases.each do |branch|
244
+ it "doesn't modify #{branch}" do
245
+ bn = described_class.new(branch.dup, {:correct => false})
246
+ expect(bn.dirname).to eq branch
247
+ end
248
+ end
249
+
250
+ valid_cases.each do |branch|
251
+ it "doesn't modify #{branch}" do
252
+ bn = described_class.new(branch.dup, {:correct => false})
253
+ expect(bn.dirname).to eq branch
254
+ end
255
+ end
256
+ end
257
+
258
+ describe "and correct is true" do
259
+ invalid_cases.each do |branch|
260
+ it "replaces invalid characters in #{branch} with underscores" do
261
+ bn = described_class.new(branch.dup, {:correct => true})
262
+ expect(bn.dirname).to eq branch.gsub(/\W/, '_')
263
+ end
264
+ end
265
+
266
+ valid_cases.each do |branch|
267
+ it "doesn't modify #{branch}" do
268
+ bn = described_class.new(branch.dup, {:correct => true})
269
+ expect(bn.dirname).to eq branch
270
+ end
271
+ end
272
+ end
273
+ end
274
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+ require 'r10k/source'
3
+
4
+ describe R10K::Source::SVN do
5
+
6
+ subject do
7
+ described_class.new('mysource', '/some/nonexistent/dir',
8
+ {:remote => 'https://svn-server.site/repo'})
9
+ end
10
+
11
+ it "stores the name" do
12
+ expect(subject.name).to eq 'mysource'
13
+ end
14
+
15
+ it "stores the basedir" do
16
+ expect(subject.basedir).to eq '/some/nonexistent/dir'
17
+ end
18
+
19
+
20
+ describe "lazily generating environments" do
21
+ it "generates environments when they have not been loaded" do
22
+ expect(subject).to receive(:generate_environments).and_return %w[hi]
23
+ expect(subject.environments).to eq %w[hi]
24
+ end
25
+
26
+ it "doesn't recreate environments if they have already been loaded" do
27
+ expect(subject).to receive(:generate_environments).once.and_return %w[hi]
28
+ subject.environments
29
+ subject.environments
30
+ end
31
+ end
32
+
33
+ describe "eagerly generating environments" do
34
+ before do
35
+ allow(subject.svn_remote).to receive(:branches).and_return %w[apache dns robobutler]
36
+ end
37
+
38
+ let(:environments) { subject.generate_environments }
39
+
40
+ it "creates an environment for each branch and the trunk" do
41
+ expect(environments[0].name).to eq 'production'
42
+ expect(environments[1].name).to eq 'apache'
43
+ expect(environments[2].name).to eq 'dns'
44
+ expect(environments[3].name).to eq 'robobutler'
45
+ end
46
+
47
+ it "maps trunk to production" do
48
+ expect(environments[0].remote).to eq 'https://svn-server.site/repo/trunk'
49
+ end
50
+
51
+ it "sets the remote for branch environments to subdirectories of the branches/ directory" do
52
+ expect(environments[1].remote).to eq 'https://svn-server.site/repo/branches/apache'
53
+ expect(environments[2].remote).to eq 'https://svn-server.site/repo/branches/dns'
54
+ expect(environments[3].remote).to eq 'https://svn-server.site/repo/branches/robobutler'
55
+ end
56
+
57
+ it "uses the branch name as the directory by default" do
58
+ expect(environments[0].dirname).to eq 'production'
59
+ expect(environments[1].dirname).to eq 'apache'
60
+ expect(environments[2].dirname).to eq 'dns'
61
+ expect(environments[3].dirname).to eq 'robobutler'
62
+ end
63
+ end
64
+ end
65
+
66
+ describe R10K::Source::SVN, 'when prefixing is enabled' do
67
+ subject do
68
+ described_class.new(
69
+ 'mysource',
70
+ '/some/nonexistent/dir',
71
+ {
72
+ :remote => 'https://svn-server.site/repo',
73
+ :prefix => true
74
+ }
75
+ )
76
+ end
77
+
78
+ describe "generating prefixed environments" do
79
+ before do
80
+ allow(subject.svn_remote).to receive(:branches).and_return %w[apache dns robobutler]
81
+ end
82
+
83
+ let(:environments) { subject.generate_environments }
84
+
85
+ it "creates an environment for each branch and the trunk" do
86
+ expect(environments).to have(4).items
87
+ end
88
+
89
+ it "prefixes the source name to environments" do
90
+ expect(environments[0].dirname).to eq 'mysource_production'
91
+ expect(environments[1].dirname).to eq 'mysource_apache'
92
+ expect(environments[2].dirname).to eq 'mysource_dns'
93
+ expect(environments[3].dirname).to eq 'mysource_robobutler'
94
+ end
95
+ end
96
+ end
97
+
98
+ describe R10K::Source::SVN, 'registering as a source' do
99
+ it "registers with the :svn key" do
100
+ expect(R10K::Source.retrieve(:svn)).to eq described_class
101
+ end
102
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'r10k/source'
3
+
4
+ describe R10K::Source do
5
+ it "implementds methods for a keyed factory" do
6
+ expect(described_class).to respond_to :register
7
+ expect(described_class).to respond_to :retrieve
8
+ expect(described_class).to respond_to :generate
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ require 'r10k'
2
+ require 'r10k/svn'
3
+
4
+ describe R10K::SVN::Remote do
5
+ subject { described_class.new('https://svn-server.site/repo') }
6
+
7
+ it "generates the trunk URL by appending '/trunk' to the base URL" do
8
+ expect(subject.trunk).to eq 'https://svn-server.site/repo/trunk'
9
+ end
10
+
11
+ describe "retrieving branches" do
12
+ let(:branches) do
13
+ %[apache/\ndns/\nrobobutler/\nstaging/\n]
14
+ end
15
+
16
+ it "enumerates the /branches directory of the base URL" do
17
+ allow(subject).to receive(:svn).with(['ls', 'https://svn-server.site/repo/branches']).and_return(branches)
18
+ expect(subject.branches).to eq(%w[apache dns robobutler staging])
19
+ end
20
+ end
21
+ end