revamp 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +4 -0
- data/.rubocop.yml +29 -0
- data/.rubocop_todo.yml +0 -0
- data/.travis.yml +15 -0
- data/Gemfile +30 -0
- data/Gemfile.ruby19 +1 -0
- data/LICENSE.txt +202 -0
- data/README.md +41 -0
- data/Rakefile +63 -0
- data/bin/revamp +13 -0
- data/lib/revamp/application.rb +33 -0
- data/lib/revamp/cli.rb +98 -0
- data/lib/revamp/filter/puppetver2rpmreq.rb +98 -0
- data/lib/revamp/mapper/puppet-name-slugger.rb +8 -0
- data/lib/revamp/model/puppet-module.rb +79 -0
- data/lib/revamp/parser/puppet-tarball.rb +78 -0
- data/lib/revamp/persister/rpm-spec.erb +28 -0
- data/lib/revamp/persister/rpm.rb +156 -0
- data/lib/revamp/version.rb +35 -0
- data/lib/revamp.rb +61 -0
- data/revamp.gemspec +29 -0
- data/spec/file_matchers.rb +5 -0
- data/spec/fixtures/coi-sample-0.1.1.tar.gz +0 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/unit/revamp/cli_spec.rb +120 -0
- data/spec/unit/revamp/filter/puppetver2rpmreq_spec.rb +96 -0
- data/spec/unit/revamp/parser/puppet-tarball_spec.rb +53 -0
- data/spec/unit/revamp/persister/rpm_spec.rb +32 -0
- data/spec/unit/revamp/version_spec.rb +13 -0
- data/spec/unit/revamp_spec.rb +21 -0
- metadata +133 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'revamp'
|
2
|
+
require 'revamp/mapper/puppet-name-slugger'
|
3
|
+
|
4
|
+
# This class describes a puppet dependency
|
5
|
+
class Revamp::Model::PuppetDependency
|
6
|
+
attr_accessor :name, :version
|
7
|
+
|
8
|
+
def initialize(hash)
|
9
|
+
@name = hash['name']
|
10
|
+
versions = normalize(hash['version_requirement'])
|
11
|
+
@version = Gem::Requirement.new(versions)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def normalize(versionreq)
|
17
|
+
re = /^(([><=~]+)?\s*([\dx]+(?:\.[\dx]+(?:\.[\dx]+)?)?))(.*)/
|
18
|
+
m = re.match(versionreq.strip)
|
19
|
+
first = m[1].strip
|
20
|
+
second = m[4].strip
|
21
|
+
reqs = [first]
|
22
|
+
reqs << second unless second.empty?
|
23
|
+
reqs
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# This class describes a puppet module
|
28
|
+
class Revamp::Model::PuppetModule
|
29
|
+
def self.puppet_accessor(*vars)
|
30
|
+
@attributes ||= []
|
31
|
+
@attributes.concat vars
|
32
|
+
attr_accessor(*vars)
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
attr_reader :attributes
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_accessor :files
|
40
|
+
attr_accessor :metadata
|
41
|
+
attr_accessor :name
|
42
|
+
|
43
|
+
puppet_accessor :dependencies
|
44
|
+
puppet_accessor :source
|
45
|
+
puppet_accessor :author
|
46
|
+
puppet_accessor :version
|
47
|
+
puppet_accessor :license
|
48
|
+
puppet_accessor :summary
|
49
|
+
puppet_accessor :project_page
|
50
|
+
|
51
|
+
def initialize
|
52
|
+
@files = {}
|
53
|
+
@metadata = nil
|
54
|
+
@dependencies = []
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_file(path, content)
|
58
|
+
@files[path] = content
|
59
|
+
end
|
60
|
+
|
61
|
+
def attributes
|
62
|
+
self.class.attributes
|
63
|
+
end
|
64
|
+
|
65
|
+
def dependencies=(deps)
|
66
|
+
@dependencies = []
|
67
|
+
deps.each do |dep|
|
68
|
+
@dependencies << Revamp::Model::PuppetDependency.new(dep)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def slugname
|
73
|
+
Revamp::Mapper::PuppetNameSlugger.new.map(name)
|
74
|
+
end
|
75
|
+
|
76
|
+
def rawname
|
77
|
+
name.split('/')[-1]
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'revamp'
|
2
|
+
require 'zlib'
|
3
|
+
require 'json'
|
4
|
+
require 'rubygems/package'
|
5
|
+
require 'revamp/model/puppet-module'
|
6
|
+
|
7
|
+
# This class is a parser for Puppet's tarballs format
|
8
|
+
class Revamp::Parser::PuppetTarball
|
9
|
+
def initialize(tarball_file)
|
10
|
+
@tarball = tarball_file
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse
|
14
|
+
model = nil
|
15
|
+
File.open(@tarball, 'rb') do |file|
|
16
|
+
Zlib::GzipReader.wrap(file) do |gz|
|
17
|
+
Gem::Package::TarReader.new(gz) do |tar|
|
18
|
+
model = Revamp::Model::PuppetModule.new
|
19
|
+
tar.each do |tarfile|
|
20
|
+
entry = Entry.new(tarfile)
|
21
|
+
parse_metadata(model, entry) if entry.metadata?
|
22
|
+
model.add_file(entry.name, entry.content) if entry.file?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
normalize(model)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def normalize(model)
|
33
|
+
strip = "#{model.slugname}-#{model.version}/"
|
34
|
+
model.files = Hash[model.files.map { |file, content| [file.gsub(strip, ''), content] }]
|
35
|
+
model
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_metadata(model, entry)
|
39
|
+
data = JSON.parse(entry.content)
|
40
|
+
model.metadata = data
|
41
|
+
model.name = data['name'].tr('-', '/') if data['name']
|
42
|
+
model.attributes.each do |attr|
|
43
|
+
value = data[attr.to_s]
|
44
|
+
fail ArgumentError, "No #{attr} module metadata provided for #{name}" unless value
|
45
|
+
parse_dependencies(attr, value)
|
46
|
+
model.send(attr.to_s + '=', value)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_dependencies(attr, value)
|
51
|
+
return unless attr == :dependencies
|
52
|
+
value.tap do |dependencies|
|
53
|
+
dependencies.each do |dep|
|
54
|
+
dep['version_requirement'] ||= dep['versionRequirement'] || '>= 0.0.0'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# An entry from tarball
|
60
|
+
class Entry
|
61
|
+
attr_accessor :content
|
62
|
+
attr_accessor :name
|
63
|
+
def initialize(tarfile)
|
64
|
+
@tarfile = tarfile
|
65
|
+
@name = tarfile.full_name
|
66
|
+
@content = nil
|
67
|
+
@content = tarfile.read unless @tarfile.directory?
|
68
|
+
end
|
69
|
+
|
70
|
+
def metadata?
|
71
|
+
!@tarfile.directory? && name.end_with?('metadata.json')
|
72
|
+
end
|
73
|
+
|
74
|
+
def file?
|
75
|
+
!content.nil?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Name: <%= name %>
|
2
|
+
Version: <%= model.version %>
|
3
|
+
Release: <%= release %>
|
4
|
+
Summary: <%= model.summary %>
|
5
|
+
Source0: <%= rpm %>.tar.gz
|
6
|
+
License: <%= model.license %>
|
7
|
+
Group: Development
|
8
|
+
BuildArch: noarch
|
9
|
+
Provides: puppetmodule(<%= model.slugname %>)
|
10
|
+
<% if has_requirements %>Requires: <%= requirements %><% end %>
|
11
|
+
%description
|
12
|
+
<%= model.summary %>
|
13
|
+
%prep
|
14
|
+
%setup
|
15
|
+
%build
|
16
|
+
%install
|
17
|
+
rm -rf $RPM_BUILD_ROOT
|
18
|
+
mkdir -p ${RPM_BUILD_ROOT}/etc/puppet/modules
|
19
|
+
cp -r %{_builddir}/<%= rpm %> ${RPM_BUILD_ROOT}%{_sysconfdir}/puppet/modules
|
20
|
+
mv ${RPM_BUILD_ROOT}%{_sysconfdir}/puppet/modules/<%= rpm %> ${RPM_BUILD_ROOT}%{_sysconfdir}/puppet/modules/<%= model.rawname %>
|
21
|
+
%clean
|
22
|
+
%post
|
23
|
+
%files
|
24
|
+
%dir %{_sysconfdir}/puppet
|
25
|
+
%dir %{_sysconfdir}/puppet/modules
|
26
|
+
%dir %{_sysconfdir}/puppet/modules/<%= model.rawname %>
|
27
|
+
<% filenames.each do |file| %>%{_sysconfdir}/puppet/modules/<%= model.rawname %>/<%= file %>
|
28
|
+
<% end %>
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'revamp'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'erb'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'rbconfig'
|
6
|
+
require 'revamp/filter/puppetver2rpmreq'
|
7
|
+
|
8
|
+
# A main RPM persister
|
9
|
+
class Revamp::Persister::Rpm
|
10
|
+
def initialize
|
11
|
+
@options = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :options
|
15
|
+
|
16
|
+
def persist(model)
|
17
|
+
dir = File.expand_path('~')
|
18
|
+
workdir = Pathname.new(dir).join('rpmbuild')
|
19
|
+
builder = Builder.new(model, workdir, options)
|
20
|
+
builder.make_structure
|
21
|
+
builder.write_spec
|
22
|
+
builder.write_sources
|
23
|
+
produced = builder.produce
|
24
|
+
builder.cleanup if options[:cleanup]
|
25
|
+
produced
|
26
|
+
end
|
27
|
+
|
28
|
+
# A command line executor for command line
|
29
|
+
class CommandLine
|
30
|
+
class << self
|
31
|
+
def execute(command, directory, verbose)
|
32
|
+
Revamp.logger.debug("Executing: '#{command}' in directory: '#{directory}'")
|
33
|
+
out = '/dev/null'
|
34
|
+
out = $stdout if verbose
|
35
|
+
pid = Process.spawn(command, chdir: directory, out: out, err: out)
|
36
|
+
Process.wait pid
|
37
|
+
$? # rubocop:disable SpecialGlobalVars
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# A builder for RPM's packages
|
43
|
+
class Builder
|
44
|
+
SOURCES = 'SOURCES'
|
45
|
+
SPECS = 'SPECS'
|
46
|
+
RPMS = 'RPMS'
|
47
|
+
SELFDIR = Pathname.new(__FILE__).dirname
|
48
|
+
ATTRS = [
|
49
|
+
:name, :version, :filename, :rpm,
|
50
|
+
:model, :tmpdir, :release, :filenames,
|
51
|
+
:specfile, :has_requirements,
|
52
|
+
:requirements, :options
|
53
|
+
]
|
54
|
+
ATTRS.each { |attr| attr_accessor(attr) }
|
55
|
+
|
56
|
+
def initialize(model, dir, options)
|
57
|
+
@options = options
|
58
|
+
@name = "puppetmodule_#{model.slugname}"
|
59
|
+
@release = options[:release]
|
60
|
+
@version = model.version
|
61
|
+
@filename = "#{name}-#{version}-#{release}.noarch.rpm"
|
62
|
+
@rpm = "#{name}-#{version}"
|
63
|
+
@specfile = rpm + '.spec'
|
64
|
+
@model = model
|
65
|
+
@tmpdir = dir
|
66
|
+
@filenames = model.files.keys
|
67
|
+
@has_requirements = model.dependencies.any?
|
68
|
+
@requirements = configure_rpm_requirements_line
|
69
|
+
end
|
70
|
+
|
71
|
+
def configure_rpm_requirements_line
|
72
|
+
req = []
|
73
|
+
model.dependencies.each do |dep|
|
74
|
+
req += Revamp::Filter::PuppetVerToRpmReq.new.filter(dep)
|
75
|
+
end
|
76
|
+
req.join(', ')
|
77
|
+
end
|
78
|
+
|
79
|
+
def make_structure
|
80
|
+
FileUtils.mkdir_p(tmpdir.join(SOURCES))
|
81
|
+
FileUtils.mkdir_p(tmpdir.join(SPECS))
|
82
|
+
end
|
83
|
+
|
84
|
+
def erbize(template, vars)
|
85
|
+
values = OpenStruct.new(vars).instance_eval { binding }
|
86
|
+
ERB.new(template).result(values)
|
87
|
+
end
|
88
|
+
|
89
|
+
def write_spec
|
90
|
+
tpl = SELFDIR.join('rpm-spec.erb')
|
91
|
+
values = Hash[ATTRS.map { |key| [key, send(key)] }]
|
92
|
+
spec = erbize(tpl.read, values)
|
93
|
+
File.open(specfile_path, 'w') { |file| file.write(spec) }
|
94
|
+
end
|
95
|
+
|
96
|
+
def write_sources
|
97
|
+
pathsufix = Pathname.new(rpm)
|
98
|
+
File.open(sources_tgz_path, 'wb') do |tgz|
|
99
|
+
Zlib::GzipWriter.wrap(tgz) do |gz|
|
100
|
+
Gem::Package::TarWriter.new(gz) do |tar|
|
101
|
+
model.files.each do |file, content|
|
102
|
+
full = pathsufix.join(file).to_s
|
103
|
+
tar.add_file_simple(full, 0644, content.length) { |io| io.write(content) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def sources_tgz_path
|
111
|
+
sources = tmpdir.join(SOURCES)
|
112
|
+
sources.join("#{rpm}.tar.gz")
|
113
|
+
end
|
114
|
+
|
115
|
+
def specfile_path
|
116
|
+
tmpdir.join(SPECS).join(specfile)
|
117
|
+
end
|
118
|
+
|
119
|
+
def target
|
120
|
+
outdir = options[:outdir]
|
121
|
+
Pathname.new(outdir).join(filename)
|
122
|
+
end
|
123
|
+
|
124
|
+
def produce
|
125
|
+
Revamp.logger.info("Converting to RPM package #{target}...")
|
126
|
+
cmd = "rpmbuild -ba #{SPECS}/#{specfile}"
|
127
|
+
verbose = options[:verbose]
|
128
|
+
ret = Revamp::Persister::Rpm::CommandLine.execute(cmd, tmpdir, verbose)
|
129
|
+
fail "RPM Build failed with retcode = #{ret.exitstatus}" unless ret.success?
|
130
|
+
move_produced
|
131
|
+
target
|
132
|
+
end
|
133
|
+
|
134
|
+
def move_produced
|
135
|
+
produced = tmpdir.join(RPMS).join('noarch').join(filename)
|
136
|
+
Revamp.logger.debug("Produced RPM in build dir: #{produced}")
|
137
|
+
FileUtils.mv(produced, target)
|
138
|
+
end
|
139
|
+
|
140
|
+
def cleanup
|
141
|
+
arch = RbConfig::CONFIG['arch'].gsub('-linux', '')
|
142
|
+
cleanup_files [
|
143
|
+
sources_tgz_path, specfile_path, tmpdir.join('BUILD').join(rpm),
|
144
|
+
tmpdir.join('BUILDROOT').join("#{rpm}-#{release}.#{arch}")
|
145
|
+
]
|
146
|
+
end
|
147
|
+
|
148
|
+
def cleanup_files(files)
|
149
|
+
Revamp.logger.debug("Files to be cleaned up: #{files}")
|
150
|
+
readable = files.reject { |path| !path.readable? }
|
151
|
+
readable.each do |path|
|
152
|
+
path.directory? ? FileUtils.rm_r(path) : path.unlink
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Top level module for Revamp
|
2
|
+
module Revamp
|
3
|
+
# Prepare version
|
4
|
+
#
|
5
|
+
# @param desired [String] a desired version
|
6
|
+
# @return [String] a prepared version
|
7
|
+
def self.version_prep(desired)
|
8
|
+
version = desired
|
9
|
+
if desired.match(/[^0-9\.]+/)
|
10
|
+
git = `git describe --tags --dirty --always`
|
11
|
+
version += '.' + git.tr('-', '.')
|
12
|
+
end
|
13
|
+
version.strip
|
14
|
+
end
|
15
|
+
|
16
|
+
# Version for Herald
|
17
|
+
VERSION = version_prep '1.0.0'
|
18
|
+
# Lincense for Herald
|
19
|
+
LICENSE = 'Apache-2.0'
|
20
|
+
# Project name
|
21
|
+
NAME = 'Revamp'
|
22
|
+
# Package (gem) for Herald
|
23
|
+
PACKAGE = 'revamp'
|
24
|
+
# A summary info
|
25
|
+
SUMMARY = 'Converts puppet module file to valid RPM or DEB package'
|
26
|
+
# A homepage for Herald
|
27
|
+
HOMEPAGE = 'https://github.com/coi-gov-pl/gem-revamp'
|
28
|
+
# A description info
|
29
|
+
DESCRIPTION = <<-eos
|
30
|
+
This module can convert standard puppet module file in form of tarball to
|
31
|
+
valid RPM or DEB package with all dependencies as references to other
|
32
|
+
system packages. The dependencies can be packaged inside the final system
|
33
|
+
package or just referenced as dependencies.
|
34
|
+
eos
|
35
|
+
end
|
data/lib/revamp.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'pry'
|
5
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
6
|
+
# Do nothing here
|
7
|
+
end
|
8
|
+
|
9
|
+
# Top level module for Revamp
|
10
|
+
module Revamp
|
11
|
+
@logger = Logger.new($stdout)
|
12
|
+
@logger.formatter = proc { |severity, _datetime, _progname, msg| "#{severity}: #{msg}\n" }
|
13
|
+
class << self
|
14
|
+
# Logger for CLI interface
|
15
|
+
# @return [Logger] logger for CLI
|
16
|
+
attr_reader :logger
|
17
|
+
|
18
|
+
# Reports a bug in desired format
|
19
|
+
#
|
20
|
+
# @param ex [Exception] an exception that was thrown
|
21
|
+
# @return [Hash] a hash with info about bug to be displayed to user
|
22
|
+
def bug(ex)
|
23
|
+
file = Tempfile.new(['revamp-bug', '.log'])
|
24
|
+
filepath = file.path
|
25
|
+
file.close
|
26
|
+
file.unlink
|
27
|
+
message = "v#{Revamp::VERSION}-#{ex.class}: #{ex.message}"
|
28
|
+
contents = message + "\n\n" + ex.backtrace.join("\n") + "\n"
|
29
|
+
File.write(filepath, contents)
|
30
|
+
bugo = {
|
31
|
+
message: message,
|
32
|
+
homepage: Revamp::HOMEPAGE,
|
33
|
+
bugfile: filepath,
|
34
|
+
help: "Please report this bug to #{Revamp::HOMEPAGE} by passing contents of bug file: #{filepath}"
|
35
|
+
}
|
36
|
+
bugo
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# A module for modeles
|
42
|
+
module Revamp::Model
|
43
|
+
end
|
44
|
+
|
45
|
+
# A module for mapper
|
46
|
+
module Revamp::Mapper
|
47
|
+
end
|
48
|
+
|
49
|
+
# A module for persister
|
50
|
+
module Revamp::Persister
|
51
|
+
end
|
52
|
+
|
53
|
+
# Parser module
|
54
|
+
module Revamp::Parser
|
55
|
+
end
|
56
|
+
|
57
|
+
# A module for filters of persiters
|
58
|
+
module Revamp::Filter
|
59
|
+
end
|
60
|
+
|
61
|
+
require 'revamp/version'
|
data/revamp.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'revamp/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = Revamp::PACKAGE
|
8
|
+
spec.version = Revamp::VERSION
|
9
|
+
spec.authors = [
|
10
|
+
'Centralny Ośrodek Informatyki',
|
11
|
+
'Suszyński Krzysztof'
|
12
|
+
]
|
13
|
+
spec.email = ['krzysztof.suszynski@coi.gov.pl']
|
14
|
+
spec.summary = Revamp::SUMMARY
|
15
|
+
spec.description = Revamp::DESCRIPTION
|
16
|
+
spec.homepage = Revamp::HOMEPAGE
|
17
|
+
spec.license = Revamp::LICENSE
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_runtime_dependency 'micro-optparse', '~> 1.2.0'
|
27
|
+
|
28
|
+
spec.required_ruby_version = '>= 1.9'
|
29
|
+
end
|
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rspec/its'
|
2
|
+
|
3
|
+
begin
|
4
|
+
gem 'simplecov'
|
5
|
+
require 'simplecov'
|
6
|
+
formatters = []
|
7
|
+
formatters << SimpleCov::Formatter::HTMLFormatter
|
8
|
+
|
9
|
+
begin
|
10
|
+
gem 'coveralls'
|
11
|
+
require 'coveralls'
|
12
|
+
formatters << Coveralls::SimpleCov::Formatter if ENV['TRAVIS']
|
13
|
+
rescue Gem::LoadError
|
14
|
+
# do nothing
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
gem 'codeclimate-test-reporter'
|
19
|
+
require 'codeclimate-test-reporter'
|
20
|
+
formatters << CodeClimate::TestReporter::Formatter if (ENV['TRAVIS'] and ENV['CODECLIMATE_REPO_TOKEN'])
|
21
|
+
rescue Gem::LoadError
|
22
|
+
# do nothing
|
23
|
+
end
|
24
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[*formatters]
|
25
|
+
SimpleCov.start do
|
26
|
+
add_filter "/spec/"
|
27
|
+
add_filter "/.vendor/"
|
28
|
+
add_filter "/vendor/"
|
29
|
+
add_filter "/gems/"
|
30
|
+
minimum_coverage 95
|
31
|
+
refuse_coverage_drop
|
32
|
+
end
|
33
|
+
rescue Gem::LoadError
|
34
|
+
# do nothing
|
35
|
+
end
|
36
|
+
|
37
|
+
begin
|
38
|
+
gem 'pry'
|
39
|
+
require 'pry'
|
40
|
+
rescue Gem::LoadError
|
41
|
+
# do nothing
|
42
|
+
end
|
43
|
+
|
44
|
+
RSpec.configure do |c|
|
45
|
+
c.tty = true unless ENV['JENKINS_URL'].nil?
|
46
|
+
c.mock_with :rspec do |mock|
|
47
|
+
mock.syntax = [:expect]
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'revamp/cli'
|
3
|
+
require 'revamp/application'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
describe Revamp::CLI do
|
7
|
+
let(:instance) { described_class.new }
|
8
|
+
describe '.run!' do
|
9
|
+
before :each do
|
10
|
+
@level = Revamp.logger.level
|
11
|
+
Revamp.logger.level = 100
|
12
|
+
end
|
13
|
+
after :each do
|
14
|
+
Revamp.logger.level = @level
|
15
|
+
end
|
16
|
+
context 'while ARGV is equal to' do
|
17
|
+
let (:argv) { self.class.description.split(/\s+/) }
|
18
|
+
subject { instance.run!(argv) }
|
19
|
+
describe '--invalid-option' do
|
20
|
+
it do
|
21
|
+
expect { subject }.to raise_error(SystemExit, 'exit') { |error|
|
22
|
+
expect(error).not_to be_success
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
context 'while catching STDOUT' do
|
27
|
+
before :each do
|
28
|
+
@stringio = StringIO.new
|
29
|
+
$stdout = @stringio
|
30
|
+
end
|
31
|
+
after :each do
|
32
|
+
$stdout = STDOUT
|
33
|
+
end
|
34
|
+
describe '--help' do
|
35
|
+
it do
|
36
|
+
begin
|
37
|
+
subject
|
38
|
+
rescue SystemExit
|
39
|
+
end
|
40
|
+
expect(@stringio.string).to include('Revamp v', 'Usage:', '-h, --help')
|
41
|
+
end
|
42
|
+
it do
|
43
|
+
expect { subject }.to raise_error(SystemExit, 'exit') { |error|
|
44
|
+
expect(error).to be_success
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
describe '--version' do
|
49
|
+
it do
|
50
|
+
begin
|
51
|
+
subject
|
52
|
+
rescue SystemExit
|
53
|
+
end
|
54
|
+
expect(@stringio.string).to match(/^\d+\.\d+\.\d+/)
|
55
|
+
end
|
56
|
+
it do
|
57
|
+
expect { subject }.to raise_error(SystemExit, 'exit') { |error|
|
58
|
+
expect(error).to be_success
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'mocking to return' do
|
65
|
+
before :each do
|
66
|
+
app = Revamp::Application.new({})
|
67
|
+
expect(app).to receive(:run!).and_return(:mock_return)
|
68
|
+
expect(Revamp::Application).to receive(:new).and_return(app)
|
69
|
+
end
|
70
|
+
describe '-f spec/fixtures/coi-sample-0.1.1.tar.gz' do
|
71
|
+
it { expect(subject).to eq(0) }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
context 'mocking to raise error' do
|
75
|
+
before :each do
|
76
|
+
app = Revamp::Application.new({})
|
77
|
+
expect(app).to receive(:run!).and_raise(StandardError, 'mock-ex')
|
78
|
+
expect(Revamp::Application).to receive(:new).and_return(app)
|
79
|
+
end
|
80
|
+
describe '-f spec/fixtures/coi-sample-0.1.1.tar.gz' do
|
81
|
+
it { expect(subject).to eq(1) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
context 'performing real operation' do
|
85
|
+
before :each do
|
86
|
+
require 'revamp/persister/rpm'
|
87
|
+
ret = double(success?: true)
|
88
|
+
expect(Revamp::Persister::Rpm::CommandLine).to receive(:execute).and_return(ret)
|
89
|
+
expect(FileUtils).to receive(:mv)
|
90
|
+
end
|
91
|
+
describe '-f spec/fixtures/coi-sample-0.1.1.tar.gz -o /tmp' do
|
92
|
+
it { expect(subject).to eq(0) }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '.parse' do
|
99
|
+
let (:argv) { eval(self.class.description) }
|
100
|
+
subject { instance.send(:parse, argv) }
|
101
|
+
describe([].inspect) do
|
102
|
+
it { expect { subject }.to raise_error(ArgumentError, /You must pass filenames with `-f`/) }
|
103
|
+
end
|
104
|
+
describe(['-f', 'abc-lib-1.0.0.tar.gz'].inspect) do
|
105
|
+
it { expect { subject }.to raise_error(ArgumentError, 'Can\'t read file given: abc-lib-1.0.0.tar.gz') }
|
106
|
+
end
|
107
|
+
describe(['-f', 'spec/fixtures/coi-sample-0.1.1.tar.gz', '-o', Dir.tmpdir].inspect) do
|
108
|
+
it do
|
109
|
+
expect(subject).to eq({
|
110
|
+
release: "1",
|
111
|
+
epoch: "6",
|
112
|
+
outdir: "/tmp",
|
113
|
+
filenames: ["spec/fixtures/coi-sample-0.1.1.tar.gz"],
|
114
|
+
verbose: false,
|
115
|
+
cleanup: true
|
116
|
+
})
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|