cookbook-omnifetch 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/LICENSE +201 -0
- data/README.md +45 -0
- data/Rakefile +2 -0
- data/cookbook-omnifetch.gemspec +39 -0
- data/lib/cookbook-omnifetch.rb +137 -0
- data/lib/cookbook-omnifetch/artifactserver.rb +122 -0
- data/lib/cookbook-omnifetch/base.rb +77 -0
- data/lib/cookbook-omnifetch/exceptions.rb +106 -0
- data/lib/cookbook-omnifetch/git.rb +183 -0
- data/lib/cookbook-omnifetch/github.rb +8 -0
- data/lib/cookbook-omnifetch/integration.rb +46 -0
- data/lib/cookbook-omnifetch/path.rb +86 -0
- data/lib/cookbook-omnifetch/version.rb +3 -0
- data/spec/fixtures/cookbooks/example_cookbook-0.5.0/README.md +12 -0
- data/spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb +3 -0
- data/spec/fixtures/cookbooks/example_cookbook-0.5.0/recipes/default.rb +8 -0
- data/spec/fixtures/cookbooks/example_cookbook/.gitignore +2 -0
- data/spec/fixtures/cookbooks/example_cookbook/.kitchen.yml +26 -0
- data/spec/fixtures/cookbooks/example_cookbook/Berksfile +1 -0
- data/spec/fixtures/cookbooks/example_cookbook/Berksfile.lock +3 -0
- data/spec/fixtures/cookbooks/example_cookbook/README.md +12 -0
- data/spec/fixtures/cookbooks/example_cookbook/metadata.rb +3 -0
- data/spec/fixtures/cookbooks/example_cookbook/recipes/default.rb +8 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/unit/artifactserver_spec.rb +51 -0
- data/spec/unit/base_spec.rb +81 -0
- data/spec/unit/git_spec.rb +258 -0
- data/spec/unit/path_spec.rb +108 -0
- metadata +144 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'cookbook-omnifetch/exceptions'
|
2
|
+
|
3
|
+
module CookbookOmnifetch
|
4
|
+
|
5
|
+
class MissingConfiguration < OmnifetchError; end
|
6
|
+
|
7
|
+
class NullValue; end
|
8
|
+
|
9
|
+
class Integration
|
10
|
+
|
11
|
+
def self.configurables
|
12
|
+
@configurables ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configurable(name)
|
16
|
+
configurables << name
|
17
|
+
|
18
|
+
attr_writer name
|
19
|
+
|
20
|
+
define_method(name) do
|
21
|
+
value = instance_variable_get("@#{name}".to_sym)
|
22
|
+
case value
|
23
|
+
when NullValue
|
24
|
+
raise MissingConfiguration, "`#{name}` is not configured"
|
25
|
+
when Proc
|
26
|
+
value.call
|
27
|
+
else
|
28
|
+
value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
configurable :cache_path
|
35
|
+
configurable :storage_path
|
36
|
+
configurable :shell_out_class
|
37
|
+
configurable :cached_cookbook_class
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
self.class.configurables.each do |configurable|
|
41
|
+
instance_variable_set("@#{configurable}".to_sym, NullValue.new)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'cookbook-omnifetch/base'
|
2
|
+
|
3
|
+
module CookbookOmnifetch
|
4
|
+
class PathLocation < BaseLocation
|
5
|
+
# Technically path locations are always installed, but this method
|
6
|
+
# intentionally returns +false+ to force validation of the cookbook at the
|
7
|
+
# path.
|
8
|
+
#
|
9
|
+
# @see BaseLocation#installed?
|
10
|
+
def installed?
|
11
|
+
false
|
12
|
+
end
|
13
|
+
|
14
|
+
# The installation for a path location is actually just a noop
|
15
|
+
#
|
16
|
+
# @see BaseLocation#install
|
17
|
+
def install
|
18
|
+
validate_cached!(expanded_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @see BaseLocation#cached_cookbook
|
22
|
+
def cached_cookbook
|
23
|
+
@cached_cookbook ||= CookbookOmnifetch.cached_cookbook_class.from_path(expanded_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns true if the location is a metadata location. By default, no
|
27
|
+
# locations are the metadata location.
|
28
|
+
#
|
29
|
+
# @return [Boolean]
|
30
|
+
def metadata?
|
31
|
+
!!options[:metadata]
|
32
|
+
end
|
33
|
+
|
34
|
+
def install_path
|
35
|
+
relative_path
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return this PathLocation's path relative to the associated Berksfile. It
|
39
|
+
# is actually the path reative to the associated Berksfile's parent
|
40
|
+
# directory.
|
41
|
+
#
|
42
|
+
# @return [Pathname]
|
43
|
+
# the relative path relative to the target
|
44
|
+
def relative_path
|
45
|
+
# TODO: this requires Berkshelf::Dependency to provide a delegate (ish) method that does
|
46
|
+
#
|
47
|
+
# def relative_paths_root
|
48
|
+
# File.dirname(berksfile.filepath)
|
49
|
+
# end
|
50
|
+
@relative_path ||= expanded_path.relative_path_from(Pathname.new(dependency.relative_paths_root))
|
51
|
+
end
|
52
|
+
|
53
|
+
# The fully expanded path of this cookbook on disk, relative to the
|
54
|
+
# Berksfile.
|
55
|
+
#
|
56
|
+
# @return [Pathname]
|
57
|
+
def expanded_path
|
58
|
+
# TODO: this requires Berkshelf::Dependency to provide a delegate (ish) method that does
|
59
|
+
#
|
60
|
+
# def relative_paths_root
|
61
|
+
# File.dirname(berksfile.filepath)
|
62
|
+
# end
|
63
|
+
@expanded_path ||= Pathname.new File.expand_path(options[:path], dependency.relative_paths_root)
|
64
|
+
end
|
65
|
+
|
66
|
+
def ==(other)
|
67
|
+
other.is_a?(PathLocation) &&
|
68
|
+
other.metadata? == metadata? &&
|
69
|
+
other.relative_path == relative_path
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_lock
|
73
|
+
out = " path: #{relative_path}\n"
|
74
|
+
out << " metadata: true\n" if metadata?
|
75
|
+
out
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_s
|
79
|
+
"source at #{relative_path}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def inspect
|
83
|
+
"#<CookbookOmnifetch::PathLocation metadata: #{metadata?}, path: #{relative_path}>"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
driver_plugin: vagrant
|
3
|
+
|
4
|
+
platforms:
|
5
|
+
- name: ubuntu-12.04
|
6
|
+
driver_config:
|
7
|
+
box: canonical-ubuntu-12.04
|
8
|
+
box_url: http://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-amd64-vagrant-disk1.box
|
9
|
+
require_chef_omnibus: true
|
10
|
+
- name: ubuntu-10.04
|
11
|
+
driver_config:
|
12
|
+
box: opscode-ubuntu-10.04
|
13
|
+
box_url: http://opscode-vm.s3.amazonaws.com/vagrant/opscode_ubuntu-10.04_chef-11.2.0.box
|
14
|
+
- name: centos-6.3
|
15
|
+
driver_config:
|
16
|
+
box: opscode-centos-6.3
|
17
|
+
box_url: http://opscode-vm.s3.amazonaws.com/vagrant/opscode_centos-6.3_chef-11.2.0.box
|
18
|
+
- name: centos-5.8
|
19
|
+
driver_config:
|
20
|
+
box: opscode-centos-5.8
|
21
|
+
box_url: http://opscode-vm.s3.amazonaws.com/vagrant/opscode_centos-5.8_chef-11.2.0.box
|
22
|
+
|
23
|
+
suites:
|
24
|
+
- name: default
|
25
|
+
run_list: []
|
26
|
+
attributes: {}
|
@@ -0,0 +1 @@
|
|
1
|
+
site :opscode
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'cookbook-omnifetch'
|
2
|
+
|
3
|
+
module Fixtures
|
4
|
+
|
5
|
+
def fixtures_path
|
6
|
+
spec_root.join('fixtures')
|
7
|
+
end
|
8
|
+
|
9
|
+
def spec_root
|
10
|
+
Pathname.new(File.expand_path(File.dirname(__FILE__)))
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
module MockShellOut; end
|
16
|
+
module MockCachedCookbook; end
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
|
20
|
+
config.raise_errors_for_deprecations!
|
21
|
+
|
22
|
+
config.include Fixtures
|
23
|
+
|
24
|
+
config.expect_with :rspec do |c|
|
25
|
+
c.syntax = [:expect]
|
26
|
+
end
|
27
|
+
config.mock_with :rspec do |c|
|
28
|
+
c.syntax = [:expect, :should]
|
29
|
+
end
|
30
|
+
|
31
|
+
config.filter_run :focus => true
|
32
|
+
|
33
|
+
config.run_all_when_everything_filtered = true
|
34
|
+
|
35
|
+
config.before(:suite) do
|
36
|
+
CookbookOmnifetch.configure do |c|
|
37
|
+
c.cache_path = File.expand_path('~/.berkshelf')
|
38
|
+
c.storage_path = Pathname.new(File.expand_path('~/.berkshelf/cookbooks'))
|
39
|
+
c.shell_out_class = MockShellOut
|
40
|
+
c.cached_cookbook_class = MockCachedCookbook
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cookbook-omnifetch/artifactserver'
|
3
|
+
|
4
|
+
module CookbookOmnifetch
|
5
|
+
describe ArtifactserverLocation do
|
6
|
+
|
7
|
+
let(:cookbook_name) { "nginx" }
|
8
|
+
|
9
|
+
let(:cookbook_version) { "1.5.23" }
|
10
|
+
|
11
|
+
let(:constraint) { double("Constraint") }
|
12
|
+
|
13
|
+
let(:dependency) { double("Dependency", name: cookbook_name, constraint: constraint) }
|
14
|
+
|
15
|
+
let(:options) { {artifactserver: "https://cookbooks.opscode.com/api/v1", version: cookbook_version } }
|
16
|
+
|
17
|
+
subject(:public_repo_location) { ArtifactserverLocation.new(dependency, options) }
|
18
|
+
|
19
|
+
it "has a URI" do
|
20
|
+
expect(public_repo_location.uri).to eq("https://cookbooks.opscode.com/api/v1")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has a repo host" do
|
24
|
+
expect(public_repo_location.repo_host).to eq("cookbooks.opscode.com")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has an exact version" do
|
28
|
+
expect(public_repo_location.cookbook_version).to eq("1.5.23")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "has a cache key containing the site URI and version" do
|
32
|
+
expect(public_repo_location.cache_key).to eq("nginx-1.5.23-cookbooks.opscode.com")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "sets the install location as the cache path plus cache key" do
|
36
|
+
expected_install_path = Pathname.new('~/.berkshelf/cookbooks').expand_path.join("nginx-1.5.23-cookbooks.opscode.com")
|
37
|
+
expect(public_repo_location.install_path).to eq(expected_install_path)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "considers the cookbook installed if it exists in the main cache" do
|
41
|
+
expect(public_repo_location.install_path).to receive(:exist?).and_return(true)
|
42
|
+
expect(public_repo_location.installed?).to be true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "considers the cookbook not installed if it doesn't exist in the main cache" do
|
46
|
+
expect(public_repo_location.install_path).to receive(:exist?).and_return(false)
|
47
|
+
expect(public_repo_location.installed?).to be false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cookbook-omnifetch/base'
|
3
|
+
|
4
|
+
module CookbookOmnifetch
|
5
|
+
describe BaseLocation do
|
6
|
+
let(:constraint) { double('constraint') }
|
7
|
+
let(:dependency) { double('dependency', name: 'cookbook', version_constraint: constraint) }
|
8
|
+
|
9
|
+
subject { described_class.new(dependency) }
|
10
|
+
|
11
|
+
describe '#installed?' do
|
12
|
+
it 'is an abstract function' do
|
13
|
+
expect { subject.installed? }.to raise_error(AbstractFunction)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#install' do
|
18
|
+
it 'is an abstract function' do
|
19
|
+
expect { subject.install }.to raise_error(AbstractFunction)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#cached_cookbook' do
|
24
|
+
it 'is an abstract function' do
|
25
|
+
expect { subject.cached_cookbook }.to raise_error(AbstractFunction)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#to_lock' do
|
30
|
+
it 'is an abstract function' do
|
31
|
+
expect { subject.to_lock }.to raise_error(AbstractFunction)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#validate_cached!' do
|
36
|
+
context 'when the path is not a cookbook' do
|
37
|
+
before { CookbookOmnifetch.stub(:cookbook?).and_return(false) }
|
38
|
+
|
39
|
+
it 'raises an error' do
|
40
|
+
expect {
|
41
|
+
subject.validate_cached!('/foo/bar')
|
42
|
+
}.to raise_error(NotACookbook)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when the path is a cookbook' do
|
47
|
+
let(:cookbook) do
|
48
|
+
double('cookbook',
|
49
|
+
cookbook_name: 'cookbook',
|
50
|
+
version: '0.1.0',
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
before do
|
55
|
+
CookbookOmnifetch.stub(:cookbook?).and_return(true)
|
56
|
+
MockCachedCookbook.stub(:from_path).and_return(cookbook)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'raises an error if the constraint does not satisfy' do
|
60
|
+
constraint.stub(:satisfies?).with('0.1.0').and_return(false)
|
61
|
+
expect {
|
62
|
+
subject.validate_cached!(cookbook)
|
63
|
+
}.to raise_error(CookbookValidationFailure)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'raises an error if the names do not match' do
|
67
|
+
constraint.stub(:satisfies?).with('0.1.0').and_return(true)
|
68
|
+
cookbook.stub(:cookbook_name).and_return('different_name')
|
69
|
+
expect {
|
70
|
+
subject.validate_cached!(cookbook)
|
71
|
+
}.to raise_error(MismatchedCookbookName)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'returns true when the validation succeeds' do
|
75
|
+
constraint.stub(:satisfies?).with('0.1.0').and_return(true)
|
76
|
+
expect(subject.validate_cached!(cookbook)).to be true
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cookbook-omnifetch/git'
|
3
|
+
|
4
|
+
module CookbookOmnifetch
|
5
|
+
describe GitLocation do
|
6
|
+
let(:dependency) { double(name: 'bacon') }
|
7
|
+
|
8
|
+
subject do
|
9
|
+
described_class.new(dependency, git: 'https://repo.com', branch: 'ham',
|
10
|
+
tag: 'v1.2.3', ref: 'abc123', revision: 'defjkl123456', rel: 'hi')
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '.initialize' do
|
14
|
+
it 'sets the uri' do
|
15
|
+
instance = described_class.new(dependency, git: 'https://repo.com')
|
16
|
+
expect(instance.uri).to eq('https://repo.com')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'sets the branch' do
|
20
|
+
instance = described_class.new(dependency,
|
21
|
+
git: 'https://repo.com', branch: 'magic_new_feature')
|
22
|
+
expect(instance.branch).to eq('magic_new_feature')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'sets the tag' do
|
26
|
+
instance = described_class.new(dependency,
|
27
|
+
git: 'https://repo.com', tag: 'v1.2.3')
|
28
|
+
expect(instance.tag).to eq('v1.2.3')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'adds the ref' do
|
32
|
+
instance = described_class.new(dependency,
|
33
|
+
git: 'https://repo.com', ref: 'abc123')
|
34
|
+
expect(instance.ref).to eq('abc123')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'sets the revision' do
|
38
|
+
instance = described_class.new(dependency,
|
39
|
+
git: 'https://repo.com', revision: 'abcde12345')
|
40
|
+
expect(instance.revision).to eq('abcde12345')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'sets the rel' do
|
44
|
+
instance = described_class.new(dependency,
|
45
|
+
git: 'https://repo.com', rel: 'internal/path')
|
46
|
+
expect(instance.rel).to eq('internal/path')
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'rev_parse' do
|
50
|
+
def rev_parse(instance)
|
51
|
+
instance.instance_variable_get(:@rev_parse)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'uses the :ref option with priority' do
|
55
|
+
instance = described_class.new(dependency,
|
56
|
+
git: 'https://repo.com', ref: 'abc123', branch: 'magic_new_feature')
|
57
|
+
expect(rev_parse(instance)).to eq('abc123')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'uses the :branch option with priority' do
|
61
|
+
instance = described_class.new(dependency,
|
62
|
+
git: 'https://repo.com', branch: 'magic_new_feature', tag: 'v1.2.3')
|
63
|
+
expect(rev_parse(instance)).to eq('magic_new_feature')
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'uses the :tag option' do
|
67
|
+
instance = described_class.new(dependency,
|
68
|
+
git: 'https://repo.com', tag: 'v1.2.3')
|
69
|
+
expect(rev_parse(instance)).to eq('v1.2.3')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'uses "master" when none is given' do
|
73
|
+
instance = described_class.new(dependency, git: 'https://repo.com')
|
74
|
+
expect(rev_parse(instance)).to eq('master')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#cache_key" do
|
80
|
+
|
81
|
+
it "concatenates the name and revision" do
|
82
|
+
subject.stub(:revision).and_return("abcdef123456")
|
83
|
+
expect(subject.cache_key).to eq("bacon-abcdef123456")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#installed?' do
|
88
|
+
it 'returns false when there is no revision' do
|
89
|
+
subject.stub(:revision).and_return(nil)
|
90
|
+
expect(subject.installed?).to be false
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'returns false when the install_path does not exist' do
|
94
|
+
subject.stub(:revision).and_return('abcd1234')
|
95
|
+
subject.stub(:install_path).and_return(double(exist?: false))
|
96
|
+
expect(subject.installed?).to be false
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'returns true when the location is installed' do
|
100
|
+
subject.stub(:revision).and_return('abcd1234')
|
101
|
+
subject.stub(:install_path).and_return(double(exist?: true))
|
102
|
+
expect(subject.installed?).to be true
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#install' do
|
107
|
+
before do
|
108
|
+
File.stub(:chmod)
|
109
|
+
FileUtils.stub(:cp_r)
|
110
|
+
subject.stub(:validate_cached!)
|
111
|
+
subject.stub(:git)
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'when the repository is cached' do
|
115
|
+
it 'pulls a new version' do
|
116
|
+
Dir.stub(:chdir) { |args, &b| b.call } # Force eval the chdir block
|
117
|
+
|
118
|
+
subject.stub(:cached?).and_return(true)
|
119
|
+
expect(subject).to receive(:git).with(
|
120
|
+
'fetch --force --tags https://repo.com "refs/heads/*:refs/heads/*"'
|
121
|
+
)
|
122
|
+
subject.install
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'when the revision is not cached' do
|
127
|
+
it 'clones the repository' do
|
128
|
+
Dir.stub(:chdir) { |args, &b| b.call } # Force eval the chdir block
|
129
|
+
|
130
|
+
cache_path = subject.send(:cache_path)
|
131
|
+
subject.stub(:cached?).and_return(false)
|
132
|
+
expect(subject).to receive(:git).with(
|
133
|
+
%|clone https://repo.com "#{cache_path}" --bare --no-hardlinks|
|
134
|
+
)
|
135
|
+
subject.install
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#cached_cookbook' do
|
141
|
+
it 'returns nil if the cookbook is not installed' do
|
142
|
+
subject.stub(:installed?).and_return(false)
|
143
|
+
expect(subject.cached_cookbook).to be_nil
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'returns the cookbook at the install_path' do
|
147
|
+
subject.stub(:installed?).and_return(true)
|
148
|
+
MockCachedCookbook.stub(:from_path)
|
149
|
+
|
150
|
+
expect(MockCachedCookbook).to receive(:from_path).once
|
151
|
+
subject.cached_cookbook
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '#==' do
|
156
|
+
let(:other) { subject.dup }
|
157
|
+
|
158
|
+
it 'returns true when everything matches' do
|
159
|
+
expect(subject).to eq(other)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'returns false when the other location is not an GitLocation' do
|
163
|
+
other.stub(:is_a?).and_return(false)
|
164
|
+
expect(subject).to_not eq(other)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'returns false when the uri is different' do
|
168
|
+
other.stub(:uri).and_return('different')
|
169
|
+
expect(subject).to_not eq(other)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'returns false when the branch is different' do
|
173
|
+
other.stub(:branch).and_return('different')
|
174
|
+
expect(subject).to_not eq(other)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'returns false when the tag is different' do
|
178
|
+
other.stub(:tag).and_return('different')
|
179
|
+
expect(subject).to_not eq(other)
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'returns false when the ref is different' do
|
183
|
+
other.stub(:ref).and_return('different')
|
184
|
+
expect(subject).to_not eq(other)
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'returns false when the rel is different' do
|
188
|
+
other.stub(:rel).and_return('different')
|
189
|
+
expect(subject).to_not eq(other)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '#to_s' do
|
194
|
+
it 'prefers the tag' do
|
195
|
+
expect(subject.to_s).to eq('https://repo.com (at v1.2.3/hi)')
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'prefers the branch' do
|
199
|
+
subject.stub(:tag).and_return(nil)
|
200
|
+
expect(subject.to_s).to eq('https://repo.com (at ham/hi)')
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'falls back to the ref' do
|
204
|
+
subject.stub(:tag).and_return(nil)
|
205
|
+
subject.stub(:branch).and_return(nil)
|
206
|
+
expect(subject.to_s).to eq('https://repo.com (at abc123/hi)')
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'does not use the rel if missing' do
|
210
|
+
subject.stub(:rel).and_return(nil)
|
211
|
+
expect(subject.to_s).to eq('https://repo.com (at v1.2.3)')
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe '#to_lock' do
|
216
|
+
it 'includes all the information' do
|
217
|
+
expect(subject.to_lock).to eq <<-EOH.gsub(/^ {8}/, '')
|
218
|
+
git: https://repo.com
|
219
|
+
revision: defjkl123456
|
220
|
+
ref: abc123
|
221
|
+
branch: ham
|
222
|
+
tag: v1.2.3
|
223
|
+
rel: hi
|
224
|
+
EOH
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'does not include the branch if missing' do
|
228
|
+
subject.stub(:branch).and_return(nil)
|
229
|
+
expect(subject.to_lock).to_not include('branch')
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'does not include the tag if missing' do
|
233
|
+
subject.stub(:tag).and_return(nil)
|
234
|
+
expect(subject.to_lock).to_not include('tag')
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'does not include the rel if missing' do
|
238
|
+
subject.stub(:rel).and_return(nil)
|
239
|
+
expect(subject.to_lock).to_not include('rel')
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe '#git' do
|
244
|
+
before { described_class.send(:public, :git) }
|
245
|
+
|
246
|
+
it 'raises an error if Git is not installed' do
|
247
|
+
CookbookOmnifetch.stub(:which).and_return(false)
|
248
|
+
expect { subject.git('foo') }.to raise_error(GitNotInstalled)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'raises an error if the command fails' do
|
252
|
+
shell_out = double('shell_out', success?: false, stderr: nil)
|
253
|
+
MockShellOut.stub(:shell_out).and_return(shell_out)
|
254
|
+
expect { subject.git('foo') }.to raise_error(GitCommandError)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|