From 4718a0cb163d43d9dea4a349b9a59750686c8301 Mon Sep 17 00:00:00 2001 From: seenmyfate Date: Fri, 2 Aug 2013 18:04:16 +0100 Subject: [PATCH] Implement `lock` feature Ensure a Capistrano version by including a `lock` directive in your Capfile: lock '~> 3.0.0' An error will be raised if the loaded version of Capistrano does not meet the dependency specified. --- lib/capistrano.rb | 1 + lib/capistrano/dsl.rb | 4 + lib/capistrano/version_validator.rb | 37 +++++++ spec/lib/capistrano/version_validator_spec.rb | 103 ++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 lib/capistrano/version_validator.rb create mode 100644 spec/lib/capistrano/version_validator_spec.rb diff --git a/lib/capistrano.rb b/lib/capistrano.rb index 51267861..03f873c0 100644 --- a/lib/capistrano.rb +++ b/lib/capistrano.rb @@ -4,6 +4,7 @@ require 'sshkit' Rake.application.options.trace = true require 'capistrano/version' +require 'capistrano/version_validator' require 'capistrano/i18n' require 'capistrano/dsl' require 'capistrano/application' diff --git a/lib/capistrano/dsl.rb b/lib/capistrano/dsl.rb index 9765754e..df80e1e8 100644 --- a/lib/capistrano/dsl.rb +++ b/lib/capistrano/dsl.rb @@ -39,6 +39,10 @@ module Capistrano `whoami` end + def lock(locked_version) + VersionValidator.new(locked_version).verify + end + end end self.extend Capistrano::DSL diff --git a/lib/capistrano/version_validator.rb b/lib/capistrano/version_validator.rb new file mode 100644 index 00000000..ff610399 --- /dev/null +++ b/lib/capistrano/version_validator.rb @@ -0,0 +1,37 @@ +module Capistrano + class VersionValidator + + def initialize(version) + @version = version + end + + def verify + if match? + self + else + fail "Capfile locked at #{version}, but #{current_version} is loaded" + end + end + + private + attr_reader :version + + + def match? + available =~ requested + end + + def current_version + VERSION + end + + def available + Gem::Dependency.new('cap', version) + end + + def requested + Gem::Dependency.new('cap', current_version) + end + + end +end diff --git a/spec/lib/capistrano/version_validator_spec.rb b/spec/lib/capistrano/version_validator_spec.rb new file mode 100644 index 00000000..64385815 --- /dev/null +++ b/spec/lib/capistrano/version_validator_spec.rb @@ -0,0 +1,103 @@ +require 'spec_helper' + +module Capistrano + + describe VersionValidator do + let(:validator) { VersionValidator.new(version) } + let(:version) { stub } + + describe '#new' do + it 'takes a version' do + expect(validator) + end + end + + describe '#verify' do + let(:current_version) { '3.0.1' } + + subject { validator.verify } + + before do + validator.stubs(:current_version).returns(current_version) + end + + context 'with exact version' do + context 'valid' do + let(:version) { '3.0.1' } + it { should be_true } + end + + context 'invalid - lower' do + let(:version) { '3.0.0' } + + it 'fails' do + expect { subject }.to raise_error + end + end + + context 'invalid - higher' do + let(:version) { '3.0.2' } + + it 'fails' do + expect { subject }.to raise_error + end + end + + end + + context 'with optimistic versioning' do + context 'valid' do + let(:version) { '>= 3.0.0' } + it { should be_true } + end + + context 'invalid - lower' do + let(:version) { '<= 2.0.0' } + + it 'fails' do + expect { subject }.to raise_error + end + end + end + + + + context 'with pessimistic versioning' do + context '2 decimal places' do + context 'valid' do + let(:version) { '~> 3.0.0' } + it { should be_true } + end + + context 'invalid' do + let(:version) { '~> 3.1.0' } + + it 'fails' do + expect { subject }.to raise_error + end + end + end + + context '1 decimal place' do + let(:current_version) { '3.5.0' } + + context 'valid' do + let(:version) { '~> 3.1' } + it { should be_true } + end + + context 'invalid' do + let(:version) { '~> 3.6' } + it 'fails' do + expect { subject }.to raise_error + end + end + end + + end + + end + + end + +end