librarian-puppet-simple 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ data.tar.gz: e70ab85f22c10e06549a8e4084512224a7a85de8
4
+ metadata.gz: cfad763618e6817a981167e95edaf026908b8ea8
5
+ SHA512:
6
+ data.tar.gz: 8450ff50735e8083b294e379a9652175688ac9ef27454e00c519d5842d0331131891aad460dc112f02508de7082c57451b2d0e7e61deee4eaed1ee100992c706
7
+ metadata.gz: 1f1fe4db05d288c0eb566f2e9e39eef07cea6264e312b1b0bff07d084d4855ada399f70429b8d1bdfc3dece7c283ba74c258ff64f6ee907f820027f66847fbfd
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rspec
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ vendor/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ Apache License 2.0
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # librarian-puppet-simple
2
+
3
+ This project was created out of my frustration with dependency management in librarian-puppet, some people need external dependencies, I just need to be able to pin revisions for a collection of modules, and I found the dependency managment features of librarian-puppet too heavy for my simple use case.
4
+
5
+ This project just has fewer commands, but they should be compatible with the original librarian-puppet:
6
+
7
+ ### Clean
8
+ Remove the directory where the modules will be installed. At the moment the supported options are:
9
+ * `--verbose` display progress messages
10
+ * `--path` override the default `./modules` where modules will be installed
11
+
12
+ ```
13
+ librarian-puppet clean [--verbose] [--path]
14
+ ```
15
+
16
+ ### Install
17
+ Iterates through your Puppetfile and installs git sources. At the moment the supported options are:
18
+ * `--verbose` display progress messages
19
+ * `--clean` remove the directory before installing modules
20
+ * `--path` override the default `./modules` where modules will be installed
21
+ * `--puppetfile` override the default `./Puppetfile` used to find the modules
22
+
23
+ ```
24
+ librarian-puppet install [--verbose] [--clean] [--path] [--puppetfile]
25
+ ```
26
+
27
+ ## Puppetfile
28
+ The processed Puppetfile may contain two different types of modules, `git` and `tarball`. The `git` option accepts an optional `ref` parameter.
29
+
30
+ The module names can be namespaced, but the created directory will only contain the last part of the name. For example, a module named `puppetlabs/ntp` will generate a directory `ntp`, and so will a module simply named `ntp`.
31
+
32
+ Here's an example of a valid Puppetfile showcasing all valid options:
33
+
34
+ ```
35
+ mod "puppetlabs/ntp",
36
+ :git => "git://github.com/puppetlabs/puppetlabs-ntp.git",
37
+ :ref => "99bae40f225db0dd052efbf1d4078a21f0333331"
38
+
39
+ mod "apache",
40
+ :tarball => "https://forge.puppetlabs.com/puppetlabs/apache/0.6.0.tar.gz"
41
+ ```
42
+
43
+ ## Setting up for development and running the specs
44
+ Just clone the repo and run the following commands:
45
+ ```
46
+ bundle exec install --path=vendor
47
+ bundle exec rspec
48
+ ```
49
+
50
+ Beware that the functional tests will download files from GitHub and PuppetForge and will break if either is unavailable.
51
+
52
+ ## License
53
+
54
+ See [LICENSE](/LICENSE)
55
+
56
+ ## Credits
57
+ The untar and ungzip methods came from https://gist.github.com/sinisterchipmunk/1335041
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'thor'
4
+ lib = File.expand_path('../../lib', __FILE__)
5
+ $:.unshift(lib) unless $:.include?(lib)
6
+ require 'librarian/puppet/simple/cli'
7
+
8
+ Librarian::Puppet::Simple::CLI.bin!
@@ -0,0 +1,87 @@
1
+ require 'librarian/puppet/simple/installer'
2
+ require 'librarian/puppet/simple/iterator'
3
+ require 'fileutils'
4
+
5
+ module Librarian
6
+ module Puppet
7
+ module Simple
8
+ class CLI < Thor
9
+
10
+ include Librarian::Puppet::Simple::Installer
11
+ include Librarian::Puppet::Simple::Iterator
12
+ class_option :verbose, :type => :boolean,
13
+ :desc => 'verbose output for executed commands'
14
+
15
+ class_option :path, :type => :string,
16
+ :desc => "overrides target directory, default is ./modules"
17
+ class_option :puppetfile, :type => :string,
18
+ :desc => "overrides used Puppetfile",
19
+ :default => './Puppetfile'
20
+
21
+
22
+ def self.bin!
23
+ start
24
+ end
25
+
26
+ desc 'install', 'installs all git sources from your Puppetfile'
27
+ method_option :clean, :type => :boolean, :desc => "calls clean before executing install"
28
+ def install
29
+ @verbose = options[:verbose]
30
+ clean if options[:clean]
31
+ @custom_module_path = options[:path]
32
+ # evaluate the file to populate @modules
33
+ eval(File.read(File.expand_path(options[:puppetfile])))
34
+ install!
35
+ end
36
+
37
+ desc 'clean', 'clean modules directory'
38
+ def clean
39
+ target_directory = options[:path] || File.expand_path("./modules")
40
+ puts "Target Directory: #{target_directory}" if options[:verbose]
41
+ FileUtils.rm_rf target_directory
42
+ end
43
+
44
+ desc 'git_status', 'determine the current status of checked out git repos'
45
+ def git_status
46
+ @custom_module_path = options[:path]
47
+ # polulate @modules
48
+ eval(File.read(File.expand_path(options[:puppetfile])))
49
+ each_module_of_type(:git) do |repo|
50
+ Dir.chdir(File.join(module_path, repo[:name])) do
51
+ status = system_cmd('git status')
52
+ if status.include?('nothing to commit (working directory clean)')
53
+ puts "Module #{repo[:name]} has not changed" if options[:verbose]
54
+ else
55
+ puts "Uncommitted changes for: #{repo[:name]}"
56
+ puts " #{status.join("\n ")}"
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ desc 'dev_setup', 'adds development r/w remotes to each repo (assumes remote has the same name as current repo)'
63
+ method_option :remote, :type => :string, :desc => "Account name of remote to add"
64
+ def dev_setup(remote_name)
65
+ each_module_of_type(:git) do |repo|
66
+ remotes = system_cmd('git remote')
67
+ if remotes.include?(remote_name)
68
+ puts "Did not have to add remote #{remote_name} to #{repo[:name]}"
69
+ elsif ! remotes.include?('origin')
70
+ raise(TestException, "Repo #{repo[:name]} has no remote called origin, failing")
71
+ else
72
+ remote_url = git_cmd('remote show origin').detect {|x| x =~ /\s+Push\s+URL: / }
73
+ if remote_url =~ /(git|https?):\/\/(.+)\/(.+)?\/(.+)/
74
+ url = "git@#{$2}:#{remote_name}/#{$4}"
75
+ else
76
+ puts "remote_url #{remote_url} did not have the expected format. weird..."
77
+ end
78
+ puts "Adding remote #{remote_name} as #{url}"
79
+ git_cmd("remote add #{remote_name} #{url}")
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,106 @@
1
+ require 'fileutils'
2
+ require 'rubygems/package'
3
+ require 'zlib'
4
+ require 'open-uri'
5
+ require 'librarian/puppet/simple/util'
6
+ require 'librarian/puppet/simple/iterator'
7
+
8
+ # This is an extremely simple file that can consume
9
+ # a Puppet file with git references
10
+ #
11
+ # It does absolutely no dependency resolution by design.
12
+ #
13
+ module Librarian
14
+ module Puppet
15
+ module Simple
16
+ module Installer
17
+
18
+ include Librarian::Puppet::Simple::Util
19
+ include Librarian::Puppet::Simple::Iterator
20
+
21
+ # installs modules using the each_module method from our
22
+ # iterator mixin
23
+ def install!
24
+ each_module do |repo|
25
+
26
+ print_verbose "\n##### processing module #{repo[:name]}..."
27
+
28
+ case
29
+ when repo[:git]
30
+ install_git module_path, repo[:name], repo[:git], repo[:ref]
31
+ when repo[:tarball]
32
+ install_tarball module_path, repo[:name], repo[:tarball]
33
+ else
34
+ abort('only the :git and :tarball provider are currently supported')
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def install_git(module_path, module_name, repo, ref = nil)
42
+ module_dir = File.join(module_path, module_name)
43
+
44
+ Dir.chdir(module_path) do
45
+ print_verbose "cloning #{repo}"
46
+ system_cmd("git clone #{repo} #{module_name}")
47
+ Dir.chdir(module_dir) do
48
+ system_cmd('git branch -r')
49
+ system_cmd("git checkout #{ref}") if ref
50
+ end
51
+ end
52
+ end
53
+
54
+ def install_tarball(module_path, module_name, remote_tarball)
55
+ Dir.mktmpdir do |tmp|
56
+ temp_file = File.join(tmp,"downloaded_module.tar.gz")
57
+ File.open(temp_file, "w+b") do |saved_file|
58
+ print_verbose "Downloading #{remote_tarball}..."
59
+ open(remote_tarball, 'rb') do |read_file|
60
+ saved_file.write(read_file.read)
61
+ end
62
+ saved_file.rewind
63
+
64
+ target_directory = File.join(module_path, module_name)
65
+ print_verbose "Extracting #{remote_tarball} to #{target_directory}..."
66
+ unzipped_target = ungzip(saved_file)
67
+ tarfile_full_name = untar(unzipped_target, module_path)
68
+ FileUtils.mv File.join(module_path, tarfile_full_name), target_directory
69
+ end
70
+ end
71
+ end
72
+
73
+ # un-gzips the given IO, returning the
74
+ # decompressed version as a StringIO
75
+ def ungzip(tarfile)
76
+ z = Zlib::GzipReader.new(tarfile)
77
+ unzipped = StringIO.new(z.read)
78
+ z.close
79
+ unzipped
80
+ end
81
+
82
+ # untars the given IO into the specified
83
+ # directory
84
+ def untar(io, destination)
85
+ tarfile_full_name = nil
86
+ Gem::Package::TarReader.new io do |tar|
87
+ tar.each do |tarfile|
88
+ tarfile_full_name ||= tarfile.full_name
89
+ destination_file = File.join destination, tarfile.full_name
90
+ if tarfile.directory?
91
+ FileUtils.mkdir_p destination_file
92
+ else
93
+ destination_directory = File.dirname(destination_file)
94
+ FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
95
+ File.open destination_file, "wb" do |f|
96
+ f.write tarfile.read
97
+ end
98
+ end
99
+ end
100
+ end
101
+ tarfile_full_name
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,47 @@
1
+ require 'librarian/puppet/simple/util'
2
+
3
+ module Librarian
4
+ module Puppet
5
+ module Simple
6
+ module Iterator
7
+
8
+ # evaluate a module and add it our @modules instance variable
9
+ def mod(name, options = {})
10
+ @modules ||= {}
11
+ module_name = name.split('/', 2).last
12
+
13
+ case
14
+ when options[:git]
15
+ @modules[:git] ||= []
16
+ @modules[:git].push(options.merge(:name => module_name))
17
+ when options[:tarball]
18
+ @modules[:tarball] ||= []
19
+ @modules[:tarball].push(options.merge(:name => module_name))
20
+ else
21
+ @modules[:forge] ||= []
22
+ @modules[:forge].push(options.merge(:name => module_name))
23
+ #abort('only the :git and :tarball providers are currently supported')
24
+ end
25
+ end
26
+
27
+ # iterate through all modules
28
+ def each_module(&block)
29
+ (@modules || {}).each do |type, repos|
30
+ (repos || []).each do |repo|
31
+ yield repo
32
+ end
33
+ end
34
+ end
35
+
36
+ # loop over each module of a certain type
37
+ def each_module_of_type(type, &block)
38
+ abort("undefined type #{type}") unless [:git, :tarball].include?(type)
39
+ ((@modules || {})[type] || []).each do |repo|
40
+ yield repo
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,45 @@
1
+ #
2
+ # this module contains all of the base helper methods
3
+ # used by the other actions
4
+ #
5
+ module Librarian
6
+ module Puppet
7
+ module Simple
8
+ module Util
9
+
10
+ # figure out what directory we are working out og
11
+ def base_dir
12
+ @base_dir ||= Dir.pwd
13
+ end
14
+
15
+ # figure out what the modulepath is
16
+ def module_path(dir=base_dir)
17
+ unless @module_path
18
+ if @custom_module_path
19
+ @module_path = File.expand_path @custom_module_path
20
+ else
21
+ @module_path = File.join(dir, 'modules')
22
+ end
23
+ Dir.mkdir(@module_path) unless File.exists?(@module_path)
24
+ end
25
+ @module_path
26
+ end
27
+
28
+ # run a command on the system
29
+ def system_cmd (cmd)
30
+ print_verbose "Running cmd: #{cmd}"
31
+ output = `#{cmd}`.split("\n")
32
+ print_verbose output
33
+ raise(StandardError, "Cmd #{cmd} failed") unless $?.success?
34
+ output
35
+ end
36
+
37
+ private
38
+ def print_verbose(text)
39
+ puts text if @verbose
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ module Librarian
2
+ module Puppet
3
+ module Simple
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require "librarian/puppet/simple/version"
2
+
3
+ module Librarian
4
+ module Puppet
5
+ module Simple
6
+ # Your code goes here...
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require 'librarian/puppet/simple/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'librarian-puppet-simple'
7
+ s.version = Librarian::Puppet::Simple::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Dan Bode']
10
+ s.email = ['bodepd@gmail.com']
11
+ s.homepage = 'https://github.com/bodepd/librarian-puppet-simple'
12
+ s.summary = 'Bundler for your Puppet modules'
13
+ s.description = 'Simplify deployment of your Puppet infrastructure by
14
+ automatically pulling in modules from the forge and git repositories with
15
+ a single command.'
16
+ s.license = 'Apache v2.0'
17
+
18
+ s.files = `git ls-files`.split($/)
19
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
21
+ s.require_paths = ["lib"]
22
+
23
+ s.add_dependency "thor", "~> 0.15"
24
+
25
+ s.add_development_dependency "rspec", "~> 2.13"
26
+ end
@@ -0,0 +1,6 @@
1
+ mod "puppetlabs/ntp",
2
+ :git => "git://github.com/puppetlabs/puppetlabs-ntp.git",
3
+ :ref => "99bae40f225db0dd052efbf1d4078a21f0333331"
4
+
5
+ mod "apache",
6
+ :tarball => "https://forge.puppetlabs.com/puppetlabs/apache/0.6.0.tar.gz"
@@ -0,0 +1,42 @@
1
+ require 'spec/spec_helper'
2
+
3
+ require 'tmpdir'
4
+
5
+ describe "Functional - Clean" do
6
+ it "displays install help message" do
7
+ output, status = execute_captured("bin/librarian-puppet help clean")
8
+ output.should_not include("ERROR")
9
+ output.should_not include("Could not find command")
10
+ status.should == 0
11
+ end
12
+
13
+ describe "when running 'librarian-puppet clean'" do
14
+ temp_directory = nil
15
+
16
+ before :each do
17
+ temp_directory = Dir.mktmpdir
18
+ Dir.entries(temp_directory).should =~ ['.', '..']
19
+ FileUtils.touch File.join(temp_directory, 'trashfile')
20
+ Dir.entries(temp_directory).should =~ ['.', '..', 'trashfile']
21
+ end
22
+
23
+ after :each do
24
+ FileUtils.rm_rf temp_directory if File.exist?(temp_directory)
25
+ end
26
+
27
+ it "with --path it cleans the directory" do
28
+ output, status = execute_captured("bin/librarian-puppet clean --path=#{temp_directory}")
29
+
30
+ status.should == 0
31
+ # Using File.exist? to be compatible with Ruby 1.8.7
32
+ File.exist?(temp_directory).should be_false
33
+ end
34
+
35
+ it "with --verbose it shows progress messages" do
36
+ output, status = execute_captured("bin/librarian-puppet clean --verbose --path=#{temp_directory}")
37
+
38
+ status.should == 0
39
+ output.should include("Target Directory: #{temp_directory}")
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec/spec_helper'
2
+
3
+ require 'tmpdir'
4
+
5
+ describe "Functional - Install" do
6
+ before :all do
7
+ warning_message = "ATTENTION: these tests download information from github.com and forge.puppetlabs.com"
8
+ puts '*' * warning_message.length
9
+ puts warning_message
10
+ puts '*' * warning_message.length
11
+ end
12
+
13
+ it "displays install help message" do
14
+ output, status = execute_captured("bin/librarian-puppet help install")
15
+ output.should_not include("ERROR")
16
+ output.should_not include("Could not find command")
17
+ status.should == 0
18
+ end
19
+
20
+ describe "when running 'librarian-puppet install'" do
21
+ temp_directory = nil
22
+
23
+ before :each do
24
+ temp_directory = Dir.mktmpdir
25
+ Dir.entries(temp_directory).should =~ ['.', '..']
26
+ FileUtils.touch File.join(temp_directory, 'trashfile')
27
+ Dir.entries(temp_directory).should =~ ['.', '..', 'trashfile']
28
+ end
29
+
30
+ after :each do
31
+ FileUtils.rm_rf temp_directory
32
+ end
33
+
34
+ it "install the modules in a temp directory" do
35
+ output, status = execute_captured("bin/librarian-puppet install --path=#{temp_directory} --puppetfile=spec/fixtures/Puppetfile")
36
+
37
+ status.should == 0
38
+ Dir.entries(temp_directory).should =~ ['.', '..', 'apache', 'ntp', 'trashfile']
39
+ end
40
+
41
+ it "with --clean it cleans the directory before installing the modules in a temp directory" do
42
+ output, status = execute_captured("bin/librarian-puppet install --clean --path=#{temp_directory} --puppetfile=spec/fixtures/Puppetfile")
43
+
44
+ status.should == 0
45
+ Dir.entries(temp_directory).should =~ ['.', '..', 'apache', 'ntp']
46
+ end
47
+
48
+ it "with --verbose it outputs progress messages" do
49
+ output, status = execute_captured("bin/librarian-puppet install --verbose --path=#{temp_directory} --puppetfile=spec/fixtures/Puppetfile")
50
+
51
+ status.should == 0
52
+ output.should include('##### processing module apache')
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,25 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require 'open3'
8
+
9
+ RSpec.configure do |config|
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+
14
+ # Run specs in random order to surface order dependencies. If you find an
15
+ # order dependency and want to debug it, you can fix the order by providing
16
+ # the seed, which is printed after each run.
17
+ # --seed 1234
18
+ config.order = 'random'
19
+
20
+ def execute_captured(command)
21
+ stdin, stdout, stderr = Open3.popen3(command)
22
+ condensed = stdout.readlines.join + stderr.readlines.join
23
+ [condensed, $?.exitstatus]
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: librarian-puppet-simple
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dan Bode
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2013-05-23 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: "0.15"
22
+ type: :runtime
23
+ version_requirements: *id001
24
+ - !ruby/object:Gem::Dependency
25
+ name: rspec
26
+ prerelease: false
27
+ requirement: &id002 !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ~>
30
+ - !ruby/object:Gem::Version
31
+ version: "2.13"
32
+ type: :development
33
+ version_requirements: *id002
34
+ description: |-
35
+ Simplify deployment of your Puppet infrastructure by
36
+ automatically pulling in modules from the forge and git repositories with
37
+ a single command.
38
+ email:
39
+ - bodepd@gmail.com
40
+ executables:
41
+ - librarian-puppet
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - LICENSE
50
+ - README.md
51
+ - bin/librarian-puppet
52
+ - lib/librarian/puppet/simple.rb
53
+ - lib/librarian/puppet/simple/cli.rb
54
+ - lib/librarian/puppet/simple/installer.rb
55
+ - lib/librarian/puppet/simple/iterator.rb
56
+ - lib/librarian/puppet/simple/util.rb
57
+ - lib/librarian/puppet/simple/version.rb
58
+ - librarian-puppet-simple.gemspec
59
+ - spec/fixtures/Puppetfile
60
+ - spec/functional/clean_spec.rb
61
+ - spec/functional/install_spec.rb
62
+ - spec/spec_helper.rb
63
+ homepage: https://github.com/bodepd/librarian-puppet-simple
64
+ licenses:
65
+ - Apache v2.0
66
+ metadata: {}
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - &id003
76
+ - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - *id003
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 2.0.3
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Bundler for your Puppet modules
89
+ test_files:
90
+ - spec/fixtures/Puppetfile
91
+ - spec/functional/clean_spec.rb
92
+ - spec/functional/install_spec.rb
93
+ - spec/spec_helper.rb
94
+ has_rdoc: