r10k 1.1.4 → 1.2.0rc1

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 (69) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +1 -0
  3. data/.nodeset.yml +7 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +2 -1
  6. data/CHANGELOG +17 -12
  7. data/Gemfile +8 -0
  8. data/README.markdown +4 -2
  9. data/Rakefile +1 -0
  10. data/doc/dynamic-environments.markdown +206 -0
  11. data/doc/puppetfile.markdown +87 -0
  12. data/lib/r10k/cli.rb +1 -1
  13. data/lib/r10k/errors.rb +30 -3
  14. data/lib/r10k/execution.rb +5 -2
  15. data/lib/r10k/git/cache.rb +26 -42
  16. data/lib/r10k/git/commit.rb +22 -0
  17. data/lib/r10k/git/errors.rb +31 -22
  18. data/lib/r10k/git/head.rb +33 -0
  19. data/lib/r10k/git/ref.rb +63 -0
  20. data/lib/r10k/git/repository.rb +65 -36
  21. data/lib/r10k/git/tag.rb +26 -0
  22. data/lib/r10k/git/working_dir.rb +93 -83
  23. data/lib/r10k/git.rb +14 -0
  24. data/lib/r10k/module/forge.rb +129 -62
  25. data/lib/r10k/module/git.rb +72 -6
  26. data/lib/r10k/module/metadata.rb +47 -0
  27. data/lib/r10k/module/svn.rb +99 -0
  28. data/lib/r10k/module.rb +1 -0
  29. data/lib/r10k/module_repository/forge.rb +64 -0
  30. data/lib/r10k/module_repository.rb +8 -0
  31. data/lib/r10k/semver.rb +1 -1
  32. data/lib/r10k/svn/working_dir.rb +76 -0
  33. data/lib/r10k/task/deployment.rb +21 -28
  34. data/lib/r10k/util/subprocess/io.rb +12 -0
  35. data/lib/r10k/util/subprocess/result.rb +36 -0
  36. data/lib/r10k/util/subprocess/runner.rb +88 -0
  37. data/lib/r10k/util/subprocess.rb +107 -0
  38. data/lib/r10k/version.rb +1 -1
  39. data/r10k.gemspec +11 -1
  40. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/and_the_expected_version_is_latest/can_fetch_all_versions_of_a_given_module.yml +42 -0
  41. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/and_the_expected_version_is_latest/can_fetch_the_latest_version_of_a_given_module.yml +42 -0
  42. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions/can_fetch_all_versions_of_a_given_module.yml +42 -0
  43. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions/can_fetch_the_latest_version_of_a_given_module.yml +42 -0
  44. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions.yml +42 -0
  45. data/spec/fixtures/vcr/cassettes/R10K_Module_Forge/and_the_expected_version_is_latest/sets_the_expected_version_based_on_the_latest_forge_version.yml +42 -0
  46. data/spec/rspec-system-r10k/puppetfile.rb +24 -0
  47. data/spec/rspec-system-r10k/tmpdir.rb +32 -0
  48. data/spec/shared-examples/git-ref.rb +49 -0
  49. data/spec/spec_helper.rb +23 -0
  50. data/spec/system/module/forge/install_spec.rb +51 -0
  51. data/spec/system/module/git/install_spec.rb +117 -0
  52. data/spec/system/module/svn/install_spec.rb +51 -0
  53. data/spec/system/module/svn/update_spec.rb +38 -0
  54. data/spec/system/spec_helper.rb +60 -0
  55. data/spec/system/system-helpers.rb +4 -0
  56. data/spec/system/version_spec.rb +7 -0
  57. data/spec/system-provisioning/el.rb +38 -0
  58. data/spec/unit/deployment/source_spec.rb +1 -1
  59. data/spec/unit/git/cache_spec.rb +38 -0
  60. data/spec/unit/git/commit_spec.rb +33 -0
  61. data/spec/unit/git/head_spec.rb +27 -0
  62. data/spec/unit/git/ref_spec.rb +68 -0
  63. data/spec/unit/git/tag_spec.rb +31 -0
  64. data/spec/unit/module/forge_spec.rb +157 -37
  65. data/spec/unit/module/git_spec.rb +49 -0
  66. data/spec/unit/module/metadata_spec.rb +68 -0
  67. data/spec/unit/module/svn_spec.rb +146 -0
  68. data/spec/unit/module_repository/forge_spec.rb +32 -0
  69. metadata +151 -8
@@ -0,0 +1,38 @@
1
+ require 'system/spec_helper'
2
+
3
+ describe 'updating modules from SVN' do
4
+
5
+ extend SystemProvisioning::EL
6
+
7
+ before(:all) { yum_install 'subversion' }
8
+ after(:all) { shell %[yum -y remove subversion] }
9
+
10
+
11
+ it "reinstalls the module when the installed module isn't an svn repo"
12
+ it "reinstalls the module when the svn url doesn't match the installed module"
13
+
14
+ describe 'updating to a specific revision' do
15
+
16
+ include_context 'system module installation'
17
+
18
+ before(:all) do
19
+ shell %[echo "mod 'gitolite', :svn => 'https://github.com/nvalentine-puppetlabs/puppet-gitolite/trunk', :rev => '10'" > ./Puppetfile]
20
+ shell %[r10k puppetfile install]
21
+ shell %[echo "mod 'gitolite', :svn => 'https://github.com/nvalentine-puppetlabs/puppet-gitolite/trunk', :rev => '20'" > ./Puppetfile]
22
+ end
23
+
24
+ it "installs the module successfully" do
25
+ shell %[r10k puppetfile install] do |sh|
26
+ expect(sh.exit_code).to eq 0
27
+ end
28
+ end
29
+
30
+ it "checks out the specific revision" do
31
+ expect(command('cd modules/gitolite; svn info')).to return_stdout /Revision: 20/
32
+ end
33
+ end
34
+
35
+ describe 'when the installed revision is newer than the requested version' do
36
+ it 'downgrades the module'
37
+ end
38
+ end
@@ -0,0 +1,60 @@
1
+ require 'rspec-system/spec_helper'
2
+ require 'rspec-system-serverspec/helpers'
3
+
4
+ require 'system/system-helpers'
5
+
6
+ require 'system-provisioning/el'
7
+
8
+ require 'rspec-system-r10k/tmpdir'
9
+ require 'rspec-system-r10k/puppetfile'
10
+
11
+ RSpec.configure do |c|
12
+
13
+ include SystemProvisioning::EL
14
+
15
+ def install_deps
16
+ install_epel_release
17
+ install_puppetlabs_release
18
+
19
+ yum_install %w[ruby rubygems]
20
+ yum_install %w[puppet]
21
+ end
22
+
23
+ def build_artifact
24
+ require 'r10k/version'
25
+
26
+ desc = %x{git describe}.chomp
27
+ artifact_name = "r10k-#{desc}.gem"
28
+
29
+ system('gem build r10k.gemspec')
30
+ FileUtils.mv "r10k-#{R10K::VERSION}.gem", artifact_name
31
+
32
+ artifact_name
33
+ end
34
+
35
+ def upload_artifact(name)
36
+ rcp :sp => "./#{name}", :dp => '/root'
37
+ FileUtils.rm name
38
+ end
39
+
40
+ def install_artifact(name)
41
+ shell "gem install --no-rdoc --no-ri /root/#{name}"
42
+ shell "rm /root/#{name}"
43
+ end
44
+
45
+ def purge_gems
46
+ shell 'gem list | cut -d" " -f1 | xargs gem uninstall -aIx'
47
+ end
48
+
49
+ def purge_r10k
50
+ shell 'gem uninstall -aIx r10k'
51
+ end
52
+
53
+ c.before(:suite) do
54
+ purge_r10k
55
+ install_deps
56
+ name = build_artifact
57
+ upload_artifact(name)
58
+ install_artifact(name)
59
+ end
60
+ end
@@ -0,0 +1,4 @@
1
+ shared_context 'system module installation' do
2
+ before(:all) { shell 'rm -rf modules' }
3
+ after(:all) { shell 'rm -rf modules' }
4
+ end
@@ -0,0 +1,7 @@
1
+ require 'system/spec_helper'
2
+
3
+ describe 'printing the version' do
4
+ describe command('r10k version') do
5
+ it { should return_stdout /1.1/ }
6
+ end
7
+ end
@@ -0,0 +1,38 @@
1
+ module SystemProvisioning
2
+ module EL
3
+ def install_epel_release
4
+ rpm_install(
5
+ 'epel-release',
6
+ 'http://dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm'
7
+ )
8
+ end
9
+
10
+ def install_puppetlabs_release
11
+ rpm_install(
12
+ 'puppetlabs-release',
13
+ 'http://yum.puppetlabs.com/puppetlabs-release-el-5.noarch.rpm'
14
+ )
15
+ end
16
+
17
+ def yum_install(*pkgs)
18
+ pkgs = Array(*pkgs)
19
+
20
+ pkgs.each do |pkg|
21
+
22
+ check_cmd = shell "rpm -q --filesbypkg #{pkg}"
23
+ if check_cmd.exit_code != 0
24
+ shell "yum -y install #{pkg}"
25
+ end
26
+ end
27
+ end
28
+
29
+ def rpm_install(name, install_name = nil)
30
+ install_name ||= name
31
+
32
+ check_cmd = shell "rpm -q --filesbypkg #{name}"
33
+ if check_cmd.exit_code != 0
34
+ shell "rpm -Uvh #{install_name}"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -6,7 +6,7 @@ describe R10K::Deployment::Source do
6
6
  let(:remote) { 'git://github.com/adrienthebo/r10k-fixture-repo' }
7
7
  let(:basedir) { '/tmp' }
8
8
 
9
- describe 'environments' do
9
+ describe 'environments', :integration => true do
10
10
  it 'uses the name as a prefix when told' do
11
11
  subject = described_class.new(name, remote, basedir, true)
12
12
  subject.fetch_remote()
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'r10k/git/cache'
3
+
4
+ describe R10K::Git::Cache do
5
+
6
+ subject(:cache) { described_class.new('git://some/git/remote') }
7
+
8
+ before do
9
+ expect(cache).to receive(:execute).never
10
+ end
11
+
12
+ describe "updating the cache" do
13
+ it "only updates the cache once" do
14
+ expect(cache).to receive(:sync!).exactly(1).times
15
+ cache.sync
16
+ cache.sync
17
+ end
18
+ end
19
+
20
+
21
+ describe "enumerating branches" do
22
+ let(:refs) do
23
+ %w[
24
+ refs/heads/master
25
+ refs/heads/next
26
+ refs/heads/next-fetch-errors
27
+ refs/heads/next-update-forge-modules
28
+ ].map { |line| line + "\n" }.join
29
+ end
30
+
31
+ it "lists local branches using git for-each-ref" do
32
+ expect(cache).to receive(:git).with(%w[for-each-ref refs/heads --format %(refname)], anything).and_return refs
33
+
34
+ expect(cache.branches).to eq %w[master next next-fetch-errors next-update-forge-modules]
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'r10k/git'
3
+
4
+ describe R10K::Git::Commit do
5
+
6
+ let(:ref) { '96eeaba8c5069e31400a3dfcbeb37d016c1b1980' }
7
+ let(:repo) { double('git repository') }
8
+ subject { described_class.new(ref) }
9
+
10
+
11
+ describe "determining if the commit can be resolved" do
12
+ before do
13
+ subject.repository = repo
14
+ end
15
+
16
+ it "is true if the commit can be rev-parsed" do
17
+ expect(repo).to receive(:rev_parse).with(ref).and_return ref
18
+ expect(subject).to be_resolvable
19
+ end
20
+
21
+ it "is true if the commit cannot be rev-parsed" do
22
+ expect(repo).to receive(:rev_parse).with(ref).and_raise(R10K::Git::UnresolvableRefError, :ref => ref)
23
+ expect(subject).to_not be_resolvable
24
+ end
25
+ end
26
+
27
+ it "can be converted to a string" do
28
+ expect(subject.to_s).to eq ref
29
+ end
30
+
31
+ it_behaves_like "a git ref"
32
+ it_behaves_like "an immutable git ref"
33
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require 'r10k/git'
3
+
4
+ describe R10K::Git::Head do
5
+
6
+ let(:ref) { 'git/branch' }
7
+ let(:repo) { double('git repository') }
8
+ subject { described_class.new(ref) }
9
+
10
+
11
+ describe "determining if the head can be resolved" do
12
+ it "is always false"
13
+ end
14
+
15
+ describe "determining if the head needs to be fetched" do
16
+ it "is always true" do
17
+ expect(subject.fetch?).to be_true
18
+ end
19
+ end
20
+
21
+ it "can be converted to a string" do
22
+ expect(subject.to_s).to eq ref
23
+ end
24
+
25
+ it_behaves_like "a git ref"
26
+ end
27
+
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'r10k/git'
3
+
4
+ describe R10K::Git::Ref do
5
+
6
+ let(:ref) { 'master' }
7
+ let(:repo) { double('git repository') }
8
+ subject { described_class.new(ref) }
9
+
10
+ describe "fetching the SHA1" do
11
+ it "raises an error if there is not a linked repository" do
12
+ expect {
13
+ subject.sha1
14
+ }.to raise_error(ArgumentError, /Cannot resolve .*#{ref}.*: no associated git repository/)
15
+ end
16
+
17
+ it "raises an error if the SHA1 could not be resolved" do
18
+ subject.repository = repo
19
+ expect(repo).to receive(:rev_parse).with(ref).and_raise(R10K::Git::UnresolvableRefError)
20
+
21
+ expect {
22
+ subject.sha1
23
+ }.to raise_error(R10K::Git::UnresolvableRefError)
24
+ end
25
+
26
+ it "looks up the ref against the linked repository" do
27
+ subject.repository = repo
28
+ expect(repo).to receive(:rev_parse).with(ref).and_return 'hash'
29
+ expect(subject.sha1).to eq 'hash'
30
+ end
31
+
32
+ it "invokes the #ref method" do
33
+ subject.repository = repo
34
+ expect(repo).to receive(:rev_parse).with(ref).and_return 'hash'
35
+ expect(subject).to receive(:ref).and_return ref
36
+ expect(subject.sha1).to eq 'hash'
37
+ end
38
+ end
39
+
40
+ describe "determining if the ref can be resolved" do
41
+ describe "and the ref is a head" do
42
+ it "is always false"
43
+ end
44
+
45
+ describe "and the ref is a tag" do
46
+ it "is true if the tag has been fetched"
47
+ it "is false if the tag cannot be resolved"
48
+ end
49
+
50
+ describe "and the ref is a commit" do
51
+ it "is true if the commit has been fetched"
52
+ it "is false if the commit cannot be resolved"
53
+ end
54
+ end
55
+
56
+ describe "determining if the ref needs to be fetched" do
57
+ it "uses the result of #resolvable? if the ref is a tag"
58
+ it "uses the result of #resolvable? if the ref is a commit"
59
+
60
+ it "is true if the ref is a head"
61
+ end
62
+
63
+ it "can be converted to a string" do
64
+ expect(subject.to_s).to eq ref
65
+ end
66
+
67
+ it_behaves_like "a git ref"
68
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'r10k/git'
3
+
4
+ describe R10K::Git::Tag do
5
+
6
+ let(:ref) { '0.1.0' }
7
+ let(:repo) { double('git repository') }
8
+ subject { described_class.new(ref) }
9
+
10
+
11
+ describe "determining if the tag can be resolved" do
12
+ it "is true if the tag has been fetched" do
13
+ expect(repo).to receive(:rev_parse).with(ref).and_return('32f8ec692906783ee60e02e4a4154bc3a87dfeb6')
14
+ subject.repository = repo
15
+ expect(subject).to be_resolvable
16
+ end
17
+
18
+ it "is false if the tag cannot be resolved" do
19
+ expect(repo).to receive(:rev_parse).with(ref).and_raise(R10K::Git::UnresolvableRefError, :ref => ref)
20
+ subject.repository = repo
21
+ expect(subject).to_not be_resolvable
22
+ end
23
+ end
24
+
25
+ it "can be converted to a string" do
26
+ expect(subject.to_s).to eq ref
27
+ end
28
+
29
+ it_behaves_like "a git ref"
30
+ it_behaves_like "an immutable git ref"
31
+ end
@@ -3,26 +3,24 @@ require 'r10k/semver'
3
3
  require 'spec_helper'
4
4
 
5
5
  describe R10K::Module::Forge do
6
- before :each do
7
- allow_any_instance_of(Object).to receive(:systemu).and_raise "Tests should never invoke system calls"
8
- end
9
6
 
10
- before :each do
11
- log = double('stub logger').as_null_object
12
- described_class.any_instance.stub(:logger).and_return log
13
- end
7
+ include_context 'stub logging'
8
+ include_context 'fail on execution'
9
+
10
+ let(:fixture_modulepath) { File.expand_path('spec/fixtures/module/forge', PROJECT_ROOT) }
11
+ let(:empty_modulepath) { File.expand_path('spec/fixtures/empty', PROJECT_ROOT) }
14
12
 
15
13
  describe "implementing the Puppetfile spec" do
16
14
  it "should implement 'branan/eight_hundred', '8.0.0'" do
17
- described_class.should be_implement('branan/eight_hundred', '8.0.0')
15
+ expect(described_class).to be_implement('branan/eight_hundred', '8.0.0')
18
16
  end
19
17
 
20
18
  it "should fail with an invalid full name" do
21
- described_class.should_not be_implement('branan-eight_hundred', '8.0.0')
19
+ expect(described_class).to_not be_implement('branan-eight_hundred', '8.0.0')
22
20
  end
23
21
 
24
22
  it "should fail with an invalid version" do
25
- described_class.should_not be_implement('branan-eight_hundred', 'not a semantic version')
23
+ expect(described_class).to_not be_implement('branan-eight_hundred', 'not a semantic version')
26
24
  end
27
25
  end
28
26
 
@@ -30,61 +28,183 @@ describe R10K::Module::Forge do
30
28
  subject { described_class.new('branan/eight_hundred', '/moduledir', '8.0.0') }
31
29
 
32
30
  its(:name) { should eq 'eight_hundred' }
33
- its(:owner) { should eq 'branan' }
31
+ its(:author) { should eq 'branan' }
34
32
  its(:full_name) { should eq 'branan/eight_hundred' }
35
33
  its(:basedir) { should eq '/moduledir' }
36
34
  its(:full_path) { should eq '/moduledir/eight_hundred' }
37
35
  end
38
36
 
39
37
  describe "when syncing" do
40
- let(:fixture_modulepath) { File.expand_path('spec/fixtures/module/forge', PROJECT_ROOT) }
41
- let(:empty_modulepath) { File.expand_path('spec/fixtures/empty', PROJECT_ROOT) }
38
+ let(:metadata) do
39
+ double('metadata',
40
+ :exist? => true,
41
+ :author => 'branan',
42
+ :version => R10K::SemVer.new('8.0.0'))
43
+ end
44
+
45
+ subject { described_class.new('branan/eight_hundred', fixture_modulepath, '8.0.0') }
46
+
47
+ before { allow(R10K::Module::Metadata).to receive(:new).and_return metadata }
42
48
 
43
49
  describe "and the module is in sync" do
44
- subject { described_class.new('branan/eight_hundred', fixture_modulepath, '8.0.0') }
50
+ before do
51
+ allow(subject).to receive(:status).and_return :insync
52
+ end
45
53
 
46
- it { should be_insync }
47
- its(:version) { should eq '8.0.0' }
54
+ it "is in sync" do
55
+ expect(subject).to be_insync
56
+ end
57
+
58
+ it "doesn't act when syncing anything" do
59
+ expect(subject).to receive(:install).never
60
+ expect(subject).to receive(:upgrade).never
61
+ expect(subject).to receive(:reinstall).never
62
+ subject.sync
63
+ end
48
64
  end
49
65
 
50
- describe "and the desired version is newer than the installed version" do
51
- subject { described_class.new('branan/eight_hundred', fixture_modulepath, '80.0.0') }
66
+ describe "and the module is mismatched" do
67
+ before do
68
+ allow(subject).to receive(:status).and_return :mismatched
69
+ end
70
+
71
+ it "is not in sync" do
72
+ expect(subject).to_not be_insync
73
+ end
74
+
75
+ it "reinstalls the module" do
76
+ expect(subject).to receive(:reinstall)
77
+ subject.sync
78
+ end
52
79
 
53
- it { should_not be_insync }
54
- its(:version) { should eq 'v8.0.0' }
80
+ it "reinstalls by removing the existing directory and calling the module tool" do
81
+ expect(FileUtils).to receive(:rm_rf)
82
+ expect(subject).to receive(:pmt) do |args|
83
+ expect(args).to include 'install'
84
+ expect(args).to include '--version=8.0.0'
85
+ expect(args).to include 'branan/eight_hundred'
86
+ end
55
87
 
56
- it "should try to upgrade the module" do
57
- expected = %w{upgrade --version=80.0.0 --ignore-dependencies branan/eight_hundred}
58
- expect(subject).to receive(:pmt).with(expected)
59
88
  subject.sync
60
89
  end
61
90
  end
62
91
 
63
- describe "and the desired version is older than the installed version" do
64
- subject { described_class.new('branan/eight_hundred', fixture_modulepath, '7.0.0') }
92
+ describe "and the module is outdated" do
93
+ before do
94
+ allow(subject).to receive(:status).and_return :outdated
95
+ end
96
+
97
+ it "is not in sync" do
98
+ expect(subject).to_not be_insync
99
+ end
100
+
101
+ it "upgrades the module" do
102
+ expect(subject).to receive(:upgrade)
103
+ subject.sync
104
+ end
65
105
 
66
- it { should_not be_insync }
67
- its(:version) { should eq '8.0.0' }
106
+ it "upgrades by calling the module tool" do
107
+ expect(subject).to receive(:pmt) do |args|
108
+ expect(args).to include 'upgrade'
109
+ expect(args).to include '--version=8.0.0'
110
+ expect(args).to include 'branan/eight_hundred'
111
+ end
68
112
 
69
- it "should try to downgrade the module" do
70
- # Again with the magical "v" prefix to the version.
71
- expected = %w{upgrade --version=7.0.0 --ignore-dependencies branan/eight_hundred}
72
- expect(subject).to receive(:pmt).with(expected)
73
113
  subject.sync
74
114
  end
75
115
  end
76
116
 
77
117
  describe "and the module is not installed" do
78
- subject { described_class.new('branan/eight_hundred', empty_modulepath, '8.0.0') }
118
+ before do
119
+ allow(subject).to receive(:status).and_return :absent
120
+ end
79
121
 
80
- it { should_not be_insync }
81
- its(:version) { should eq R10K::SemVer::MIN }
122
+ it "is not in sync" do
123
+ expect(subject).to_not be_insync
124
+ end
82
125
 
83
- it "should try to install the module" do
84
- expected = %w{install --version=8.0.0 --ignore-dependencies branan/eight_hundred}
85
- expect(subject).to receive(:pmt).with(expected)
126
+ it "installs the module" do
127
+ expect(subject).to receive(:uninstall).never
128
+ expect(subject).to receive(:install)
86
129
  subject.sync
87
130
  end
131
+
132
+ it "installs by calling the module tool" do
133
+ expect(subject).to receive(:pmt) do |args|
134
+ expect(args).to include 'install'
135
+ expect(args).to include '--version=8.0.0'
136
+ expect(args).to include 'branan/eight_hundred'
137
+ end
138
+
139
+ subject.sync
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "determining the status" do
145
+
146
+ let(:metadata) { double 'metadata', :version => R10K::SemVer.new('8.0.0'), :author => 'branan', :exist? => true, :read => nil }
147
+
148
+ subject { described_class.new('branan/eight_hundred', '/moduledir', '8.0.0') }
149
+
150
+ before do
151
+ allow(R10K::Module::Metadata).to receive(:new).and_return metadata
152
+ end
153
+
154
+ it "is :absent if the module directory is absent" do
155
+ allow(subject).to receive(:exist?).and_return false
156
+ expect(subject.status).to eq :absent
157
+ end
158
+
159
+ it "is :mismatched if there is no module metadata" do
160
+ allow(subject).to receive(:exist?).and_return true
161
+ allow(metadata).to receive(:exist?).and_return false
162
+
163
+ expect(subject.status).to eq :mismatched
164
+ end
165
+
166
+ it "is :mismatched if the metadata author doesn't match the expected author" do
167
+ allow(subject).to receive(:exist?).and_return true
168
+
169
+ allow(metadata).to receive(:author).and_return 'blargh'
170
+
171
+ expect(subject.status).to eq :mismatched
172
+ end
173
+
174
+ it "is :outdated if the metadata version doesn't match the expected version" do
175
+ allow(subject).to receive(:exist?).and_return true
176
+
177
+ allow(metadata).to receive(:version).and_return R10K::SemVer.new('7.0.0')
178
+
179
+ expect(subject.status).to eq :outdated
180
+ end
181
+
182
+ it "is :insync if the version and the author are in sync" do
183
+ allow(subject).to receive(:exist?).and_return true
184
+
185
+ expect(subject.status).to eq :insync
186
+ end
187
+ end
188
+
189
+ describe "and the expected version is :latest", :vcr => true, :unless => (RUBY_VERSION == '1.8.7') do
190
+ subject { described_class.new('branan/eight_hundred', '/moduledir', :latest) }
191
+
192
+ let(:_metadata) do
193
+ double('metadata',
194
+ :version => R10K::SemVer.new('7.0.0'),
195
+ :author => 'branan',
196
+ :exist? => true,
197
+ :read => nil)
198
+ end
199
+
200
+ before do
201
+ allow(R10K::Module::Metadata).to receive(:new).and_return _metadata
202
+ end
203
+
204
+ it "sets the expected version based on the latest forge version" do
205
+ allow(subject).to receive(:exist?).and_return true
206
+ expect(subject.status).to eq :outdated
207
+ expect(subject.expected_version).to eq R10K::SemVer.new('8.0.0')
88
208
  end
89
209
  end
90
210
  end