hardhat 0.0.1
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.
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +152 -0
- data/Rakefile +8 -0
- data/bin/bootstrap +50 -0
- data/bin/hardhat +50 -0
- data/example/blueprint.rb +52 -0
- data/hardhat.gemspec +24 -0
- data/lib/hardhat.rb +33 -0
- data/lib/hardhat/dependency.rb +38 -0
- data/lib/hardhat/ext.rb +1 -0
- data/lib/hardhat/ext/string.rb +16 -0
- data/lib/hardhat/installer.rb +53 -0
- data/lib/hardhat/repository.rb +18 -0
- data/lib/hardhat/repository/git.rb +11 -0
- data/lib/hardhat/repository/svn.rb +11 -0
- data/lib/hardhat/system.rb +19 -0
- data/lib/hardhat/version.rb +3 -0
- data/spec/dependency_spec.rb +55 -0
- data/spec/installer_spec.rb +178 -0
- data/spec/repository/git_spec.rb +9 -0
- data/spec/repository/svn_spec.rb +9 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/shared_examples_for_repository.rb +29 -0
- data/spec/system_spec.rb +32 -0
- data/spec/version_spec.rb +22 -0
- metadata +130 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --order rand
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Nathan Lilienthal
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# Hardhat
|
2
|
+
|
3
|
+
...
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
...
|
8
|
+
|
9
|
+
## CLI
|
10
|
+
|
11
|
+
...
|
12
|
+
|
13
|
+
# Documentation
|
14
|
+
|
15
|
+
Hardhat is essentially a collection of helper classes and modules for
|
16
|
+
performing actions common to a build. Things like installing dependencies,
|
17
|
+
downloading code from version control, moving files into place, patching
|
18
|
+
files, running daemons, and even making images.
|
19
|
+
|
20
|
+
|
21
|
+
## Installing Dependencies
|
22
|
+
|
23
|
+
Projects have a collection of dependencies, some are for a single purpose,
|
24
|
+
and some a required for many purposes. By grouping these dependencies up by
|
25
|
+
what they are required for it make managing them easier.
|
26
|
+
|
27
|
+
Dependency lists should look like this:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
breakfast_deps = [
|
31
|
+
Dependency.new "milk",
|
32
|
+
Dependency.new "cereal",
|
33
|
+
Dependency.new "bowl",
|
34
|
+
Dependency.new "spoon",
|
35
|
+
]
|
36
|
+
```
|
37
|
+
|
38
|
+
Then to install the dependencies:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
meal_installer = Installer.new "mealer"
|
42
|
+
meal_installer.install breakfast_deps
|
43
|
+
```
|
44
|
+
|
45
|
+
By default this translates to:
|
46
|
+
|
47
|
+
```
|
48
|
+
mealer install milk
|
49
|
+
mealer install cereal
|
50
|
+
mealer install bowl
|
51
|
+
mealer install spoon
|
52
|
+
```
|
53
|
+
|
54
|
+
#### Hardhat::Dependency
|
55
|
+
|
56
|
+
Class for defining dependencies for the project. The first argument is the
|
57
|
+
name of the dependency, and is used to tell the package manager how to install.
|
58
|
+
The second argument is an optional hash, where you can define `:installer` to
|
59
|
+
limit what installers can deal with this dependency, `:sudo` to define if
|
60
|
+
this needs to be run as sudo to install, and `:flags` to pass command line
|
61
|
+
flags to the package manager.
|
62
|
+
|
63
|
+
Examples:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
# must install with gem
|
67
|
+
@rails = Dependency.new("rails", :installer => "gem")
|
68
|
+
@highline = Dependency.new("highline", :sudo => false, :installer => "gem")
|
69
|
+
@bundler = Dependency.new("bundler", :sudo => true, :installer => "gem")
|
70
|
+
|
71
|
+
# doesn't care what you install with
|
72
|
+
@foo = Dependency.new('foo', :flags => "-noop")
|
73
|
+
@bar = Dependency.new('bar', :sudo => false, :flags => "--verbose -q")
|
74
|
+
@baz = Dependency.new('baz', :sudo => true, :flags => "-qweF=1")
|
75
|
+
|
76
|
+
# can install with array of installer names
|
77
|
+
@git = Dependency.new("git", :installer => ["apt-get", "yum"])
|
78
|
+
@ack = Dependency.new("ack", :sudo => false, :installer => ["apt-get", "yum"])
|
79
|
+
@curl = Dependency.new("curl", :sudo => true, :installer => ["apt-get", "yum"])
|
80
|
+
```
|
81
|
+
|
82
|
+
#### Hardhat::Installer
|
83
|
+
|
84
|
+
Class for defining system programs to install dependencies. The first argument
|
85
|
+
is the name of the program to run, `apt-get` for example. The second argument
|
86
|
+
is an optional hash much like for `Dependency`. You can specify `:sudo` to
|
87
|
+
make all dependencies handled by this installer done so as root. `:flags` to
|
88
|
+
pass command line flags to the program for all dependencies.
|
89
|
+
|
90
|
+
Installers have 3 main methods, `install`, `uninstall` and `remove`. By
|
91
|
+
default `Installer.new('gem').install ...` will call `gem install ...`.
|
92
|
+
|
93
|
+
__Custom commands__
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
Installer.new('apt-get', :uninstall => :remove).uninstall ...
|
97
|
+
apt-get remove ...
|
98
|
+
|
99
|
+
Installer.new('foo', :update => :bar).update ...
|
100
|
+
foo bar ...
|
101
|
+
```
|
102
|
+
|
103
|
+
|
104
|
+
## Getting Code from Version Control
|
105
|
+
|
106
|
+
When building on a new system often times the code will not be there yet,
|
107
|
+
`Hardhat::Repository` defines the how to pull code down from VC. It is a
|
108
|
+
module currently with 2 classes the include it, `Hardhat::Repository::Git`
|
109
|
+
and `Hardhat::Repository::Svn`.
|
110
|
+
|
111
|
+
Classes that include `Hardhat::Repository` must define a `get` and a `branch`
|
112
|
+
method.
|
113
|
+
|
114
|
+
#### Hardhat::Repository::Git
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
repo = Repository::Git.new "https://gist.github.com/4772101.git", "/tmp/hh"
|
118
|
+
repo.get # downloads the repo to /tmp/hh
|
119
|
+
```
|
120
|
+
|
121
|
+
#### Hardhat::Repository::Svn
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
repo = Repository::Svn.new "http://svn.apache.org/repos/asf/spamassassin/trunk", "/tmp/hh"
|
125
|
+
repo.get # downloads the repo to /tmp/hh
|
126
|
+
```
|
127
|
+
|
128
|
+
|
129
|
+
## Other Useful Code
|
130
|
+
|
131
|
+
Miscellaneous helper methods and classes.
|
132
|
+
|
133
|
+
#### main
|
134
|
+
|
135
|
+
How to print to the user from Hardhat:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
inform "something to tell the user"
|
139
|
+
warn "a thing to be weary of"
|
140
|
+
error "oh god something broke"
|
141
|
+
```
|
142
|
+
|
143
|
+
#### Hardhat::System
|
144
|
+
|
145
|
+
Helper module for interacting with the operating system.
|
146
|
+
|
147
|
+
__::has? -> boolean__
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
Hardhat::System.has?('git') => true
|
151
|
+
Hardhat::System.has?(['git', 'svn']) => false
|
152
|
+
```
|
data/Rakefile
ADDED
data/bin/bootstrap
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# __ ____ __ __
|
3
|
+
# _/ / _/_/ /_ ____ ____ / /______/ /__________ _____
|
4
|
+
# / __/ _/_// __ \/ __ \/ __ \/ __/ ___/ __/ ___/ __ `/ __ \
|
5
|
+
# (_ ) _ _/_/ / /_/ / /_/ / /_/ / /_(__ ) /_/ / / /_/ / /_/ /
|
6
|
+
# / _/ (_)_/ /_.___/\____/\____/\__/____/\__/_/ \__,_/ .___/
|
7
|
+
# /_/ /_/
|
8
|
+
#
|
9
|
+
# Installs what is required to have a sane system for building
|
10
|
+
# our application.
|
11
|
+
#
|
12
|
+
# Sane requires:
|
13
|
+
# * Git
|
14
|
+
# * Ruby interpreter with
|
15
|
+
# * rubygems (included in 1.9.3)
|
16
|
+
# * bundler
|
17
|
+
# * Hardhat
|
18
|
+
#
|
19
|
+
|
20
|
+
# Whitelist platforms we've tested this script on, and plan
|
21
|
+
# to support. This is the output of `uname -mrs`
|
22
|
+
SUPPORTED_PLATFORMS=(
|
23
|
+
"Linux 2.6.32-33-generic-pae i686"
|
24
|
+
)
|
25
|
+
is_supported_platform() {
|
26
|
+
for s in "${SUPPORTED_PLATFORMS[@]}"; do
|
27
|
+
if [ "$s" == "$(uname -mrs)" ]; then
|
28
|
+
return 0
|
29
|
+
fi
|
30
|
+
done
|
31
|
+
echo unsupported platform please use one of:
|
32
|
+
echo ${SUPPORTED_PLATFORMS[@]}
|
33
|
+
return 1
|
34
|
+
}
|
35
|
+
# exit if the user is on unsupported platform.
|
36
|
+
if ! is_supported_platform; then
|
37
|
+
exit 1
|
38
|
+
fi
|
39
|
+
|
40
|
+
# We'll need this for building anything (ruby in this case).
|
41
|
+
echo "installing build-essential..."
|
42
|
+
sudo apt-get install -qqy build-essential zlib1g zlib1g-dev
|
43
|
+
|
44
|
+
# Install Git
|
45
|
+
echo "installing git-core..."
|
46
|
+
sudo apt-get install -qqy git-core
|
47
|
+
|
48
|
+
# Install RVM & ruby (might not use rvm in the future)
|
49
|
+
sudo apt-get install -qqy curl # needed for RVM
|
50
|
+
\curl -L https://get.rvm.io | bash -s stable --ruby
|
data/bin/hardhat
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
3
|
+
require 'hardhat'
|
4
|
+
require 'trollop'
|
5
|
+
|
6
|
+
class Hardhat::Runner
|
7
|
+
instance_methods.each do |m|
|
8
|
+
undef_method(m) unless %w(__send__ __id__ send class inspect instance_eval instance_variables object_id).include?(m.to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
include Hardhat
|
12
|
+
# Given a file path, open the file, and eval within the context of
|
13
|
+
# this module.
|
14
|
+
#
|
15
|
+
def self.eval(file, options = {})
|
16
|
+
new.instance_eval(File.read(file), file)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
SUB_COMMANDS = %w(build)
|
21
|
+
global_options = Trollop::options do
|
22
|
+
banner <<-EOF
|
23
|
+
d:) hardhat
|
24
|
+
|
25
|
+
Usage:
|
26
|
+
hardhat [options] [subcommand]
|
27
|
+
|
28
|
+
where [subcommand]s are
|
29
|
+
build
|
30
|
+
|
31
|
+
where [options] are:
|
32
|
+
EOF
|
33
|
+
stop_on SUB_COMMANDS
|
34
|
+
end
|
35
|
+
|
36
|
+
command = ARGV.shift
|
37
|
+
case command
|
38
|
+
|
39
|
+
when "build"
|
40
|
+
options = Trollop::options do
|
41
|
+
opt :blueprint, "Specify a file path for a blueprint", :short => "-b",
|
42
|
+
:default => 'blueprint.rb'
|
43
|
+
end
|
44
|
+
Trollop::die "blueprint must exist" unless File.exist?(options[:blueprint]) if options[:blueprint]
|
45
|
+
Hardhat::Runner.eval(options[:blueprint])
|
46
|
+
|
47
|
+
|
48
|
+
else
|
49
|
+
Trollop::die "unknown subcommand #{command.inspect}"
|
50
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# if we want to chroot
|
2
|
+
|
3
|
+
# Prompt for password here to get it out of the way.
|
4
|
+
System.prompt_sudo("Starting build")
|
5
|
+
|
6
|
+
deps = [
|
7
|
+
"cryptsetup","ssh","subversion","nfs-common","libssl-dev","tftpd-hpa",
|
8
|
+
"tftp-hpa","libipc-shareable-perl","libgd-graph-perl",
|
9
|
+
"libshell-posix-select-perl","unzip","traceroute",
|
10
|
+
"libbusiness-onlinepayment-authorizenet-perl",
|
11
|
+
"speedy-cgi-perl","djbdns","libxml2-dev","apache2-threaded-dev","apache2",
|
12
|
+
"ethtool","g++","libxmlrpc-c3","libxmlrpc-c3-dev","libpopt-dev","smbfs",
|
13
|
+
"acpid","libboost-dev","watchdog","curl","libcurl4-openssl-dev","snmpd",
|
14
|
+
"snmp","imagemagick","beanstalkd","build-essential","bison","openssl",
|
15
|
+
"libreadline6","libreadline6-dev","curl","git-core","zlib1g","zlib1g-dev",
|
16
|
+
"libssl-dev","libyaml-dev","libsqlite3-0","libsqlite3-dev","sqlite3",
|
17
|
+
"libxml2-dev","libxslt-dev","autoconf","libc6-dev","libqt4-dev","postgresql",
|
18
|
+
"postgresql-server-dev-8.4","postgresql-client-common","libtool",
|
19
|
+
].map { |e| Dependency.new(e, :installer => 'apt-get') }
|
20
|
+
|
21
|
+
inform "Installing system dependencies"
|
22
|
+
apt_get = Installer.new("apt-get", :sudo => true, :flags => "-qqy")
|
23
|
+
apt_get.update
|
24
|
+
apt_get.install deps
|
25
|
+
|
26
|
+
inform "Installing perl dependencies"
|
27
|
+
# add env setting to installer
|
28
|
+
`PERL_MM_USE_DEFAULT=1 cpan DBI Convert:ASN1 Digest:MD5 Digest:SHA1 Digest:HMAC IO Storable Cache:Mmap NetAddr:IP Text:CSV_XS Time:HiRes XML:Parser Crypt:DES Net:SNMP NetPacket Net_SSLeay IO:Socket:SSL Digest:MD4 Crypt:CBC perl:ldap Apache:AuthenNTLM Crypt:SSLeay Frontier:RPC HTML:Tagset HTML:Parser MIME:Base64 URI libwww:perl Bit:Vector Date:Calc TimeDate File:Tail GD GDTextUtil perlipq Authen:Krb5:Simple Filter XML:Dumper Config:Properties Text:Balanced Compress:Zlib Business:OnlinePayment Business:OnlinePayment:AuthorizeNet Class:Accessor HTML:Tree JSON JSON:Syck Module:Build HTML:Prototype Mail:Sender Mail:Sender:Easy IO:Tty Expect Business:OnlinePayment:CyberSource Switch Proc:Reliable Business:CreditCard Business:CreditCard:Object`
|
29
|
+
`PERL_MM_USE_DEFAULT=1 cpan Archive::Zip Test::Warn SOAP:Lite Class:C3:XS JSON:XS XML:LibXML:Common XML:NamespaceSupport XML:SAX XML:LibXML Data:Dumper:Simple Tie:IxHash XML:Simple YAML SQL:Abstract SQL:Abstract:Limit Algorithm:C3 Class:C3 Class:Inspector Class:C3:Componentised Module:Find MRO:Compat Carp:Clan Scope:Guard Class:Accessor:Grouped Class:Accessor:Chained Data:Page DBIx:Class Class:Data:Inheritable Devel:StackTrace Exception:Class Tree JSON:RPC Email:Public Authen::SASL XML::SAX::Writer XML::Filter::BufferText Net::LDAP CGI Text::Autoformat Data::Dump List::MoreUtils Mail::POP3Client`
|
30
|
+
`PERL_MM_USE_DEFAULT=1 cpan Sort::Versions File::chdir`
|
31
|
+
`PERL_MM_USE_DEFAULT=1 cpan DBD::Pg Beanstalk::Client Redis`
|
32
|
+
|
33
|
+
inform "Creating user - blueserver"
|
34
|
+
# System.add_user('blueserver')
|
35
|
+
useradd -m blueserver
|
36
|
+
su - blueserver
|
37
|
+
|
38
|
+
# get fresh vcommon from svn
|
39
|
+
petri = Repository::Svn.new "https://trac.eng.bluesocket.com/repos/petri/branches/vwlan-2_3", "~/petri"
|
40
|
+
petri.get
|
41
|
+
|
42
|
+
# run vmware-install.pl
|
43
|
+
|
44
|
+
# copy rootfs
|
45
|
+
|
46
|
+
|
47
|
+
# copy/append files with headers
|
48
|
+
|
49
|
+
# make C from build blue
|
50
|
+
|
51
|
+
# migrate and seed database
|
52
|
+
|
data/hardhat.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hardhat/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "hardhat"
|
8
|
+
gem.version = Hardhat::VERSION
|
9
|
+
gem.authors = ["Nathan Lilienthal"]
|
10
|
+
gem.email = ["nathanl@ccs.neu.edu"]
|
11
|
+
gem.description = %q{Elegant DSL for managing build dependencies and project builds.}
|
12
|
+
gem.summary = %q{Construction for your project.}
|
13
|
+
gem.homepage = "https://github.com/nathan/hardhat"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables << 'hardhat'
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency('trollop')
|
21
|
+
|
22
|
+
gem.add_development_dependency('rake')
|
23
|
+
gem.add_development_dependency('rspec')
|
24
|
+
end
|
data/lib/hardhat.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Hardhat
|
2
|
+
|
3
|
+
# Prefix to be printed before every message.
|
4
|
+
PREFIX = "d:) ->"
|
5
|
+
|
6
|
+
# Printing methods:
|
7
|
+
# * inform : info about the build.
|
8
|
+
# * warn : non critical errors.
|
9
|
+
# * error : blocking errors.
|
10
|
+
#
|
11
|
+
# Use these methods for interacting with STDOUT exclusively,
|
12
|
+
# to help keep the build process feel uniform.
|
13
|
+
#
|
14
|
+
def inform(string)
|
15
|
+
puts "#{PREFIX.magenta} #{string}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def warn(string)
|
19
|
+
puts "#{PREFIX.magenta} #{"WARNING:".yellow} #{string}".yellow
|
20
|
+
end
|
21
|
+
|
22
|
+
def error(string)
|
23
|
+
puts "#{PREFIX.magenta} #{"ERROR:".red} #{string}".red
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
require "hardhat/dependency"
|
29
|
+
require "hardhat/ext"
|
30
|
+
require "hardhat/installer"
|
31
|
+
require "hardhat/repository"
|
32
|
+
require "hardhat/system"
|
33
|
+
require "hardhat/version"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Hardhat::Dependency
|
2
|
+
|
3
|
+
attr_reader :name, :installers, :flags
|
4
|
+
|
5
|
+
def initialize(name, options={})
|
6
|
+
unless options.is_a? Hash
|
7
|
+
raise ArgumentError.new "options should be a hash"
|
8
|
+
end
|
9
|
+
@name = name
|
10
|
+
@installers = ([] << options[:installer]).flatten.compact
|
11
|
+
@sudo = options[:sudo]
|
12
|
+
@flags = options[:flags]
|
13
|
+
end
|
14
|
+
|
15
|
+
# sudo? -> Boolean
|
16
|
+
# Returns a boolean indicating if this dependency needs to
|
17
|
+
# be handled as root. This will overide installer defaults.
|
18
|
+
#
|
19
|
+
def sudo?
|
20
|
+
!!@sudo
|
21
|
+
end
|
22
|
+
|
23
|
+
# to_s -> String
|
24
|
+
# Returns the name of this dependency.
|
25
|
+
# This is used when formatting the system call
|
26
|
+
#
|
27
|
+
def to_s
|
28
|
+
name
|
29
|
+
end
|
30
|
+
|
31
|
+
# inspect -> String
|
32
|
+
# Debugging output for this dependency
|
33
|
+
#
|
34
|
+
def inspect
|
35
|
+
"#<#{self.class}: #{self.name}>"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/hardhat/ext.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "hardhat/ext/string"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
def colorize(color_code)
|
4
|
+
"\e[#{color_code}m#{self}\e[0m"
|
5
|
+
end
|
6
|
+
|
7
|
+
def black; self.colorize(30); end
|
8
|
+
def red; self.colorize(31); end
|
9
|
+
def green; self.colorize(32); end
|
10
|
+
def yellow; self.colorize(33); end
|
11
|
+
def blue; self.colorize(34); end
|
12
|
+
def magenta; self.colorize(35); end
|
13
|
+
def cyan; self.colorize(36); end
|
14
|
+
def white; self.colorize(37); end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Hardhat::Installer
|
2
|
+
COMMANDS = [:install, :uninstall, :update]
|
3
|
+
|
4
|
+
attr_reader :program, :flags
|
5
|
+
|
6
|
+
def initialize(program, options={})
|
7
|
+
unless options.is_a? Hash
|
8
|
+
raise ArgumentError.new "options should be a hash"
|
9
|
+
end
|
10
|
+
unless Hardhat::System.has? program
|
11
|
+
raise ArgumentError.new "program not found: #{program}"
|
12
|
+
end
|
13
|
+
@program = program
|
14
|
+
@sudo = options[:sudo]
|
15
|
+
@flags = options[:flags]
|
16
|
+
|
17
|
+
# dynamicly create a method for each COMMAND.
|
18
|
+
metaclass = class << self; self; end
|
19
|
+
COMMANDS.each do |cmd|
|
20
|
+
if options.key? cmd
|
21
|
+
instance_variable_set("@#{cmd}", options[cmd])
|
22
|
+
else
|
23
|
+
instance_variable_set("@#{cmd}", cmd)
|
24
|
+
end
|
25
|
+
metaclass.send(:define_method, cmd) do |dependency = nil, options = {}|
|
26
|
+
if cmd != :update && dependency.nil?
|
27
|
+
raise ArgumentError.new("requires a dependency")
|
28
|
+
end
|
29
|
+
run instance_variable_get("@#{cmd}"), dependency, options
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Always returns a valid bolean
|
35
|
+
def sudo?
|
36
|
+
!!@sudo
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# HACK: This code below really needs to be cleaned up,
|
42
|
+
# and broken into helper function.
|
43
|
+
def run(command, dependency, options={})
|
44
|
+
[dependency].flatten.each do |d|
|
45
|
+
unless !d || d.installers.empty? || d.installers.include?(program)
|
46
|
+
raise "bad installer"
|
47
|
+
end
|
48
|
+
s = options[:sudo].nil? ? sudo? || (d.sudo? if d) : options[:sudo]
|
49
|
+
f = options[:flags].nil? ? "#{flags+' ' if flags}#{d.flags if d}" : options[:flags]
|
50
|
+
system "#{'sudo ' if s}#{program} #{command} #{f+' ' unless f.to_s == ''}#{d}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Hardhat::Repository
|
2
|
+
attr_accessor :url, :path
|
3
|
+
|
4
|
+
def initialize(url, path, options={})
|
5
|
+
@url = url
|
6
|
+
@path = File.expand_path(path)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Implementations of a repository (Classes that include this module)
|
10
|
+
# MUST define the following methods.
|
11
|
+
# * get : Downloads the latest code from @url to @path
|
12
|
+
# * branch : Switches the active branch of this repo.
|
13
|
+
#
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'hardhat/repository/git'
|
18
|
+
require 'hardhat/repository/svn'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Hardhat::System
|
2
|
+
extend Hardhat
|
3
|
+
|
4
|
+
def self.has?(command)
|
5
|
+
[*command].map do |cmd|
|
6
|
+
system "command -v #{cmd} > /dev/null 2>&1"
|
7
|
+
end.all?
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.prompt_sudo(string)
|
11
|
+
if system "sudo -k true"
|
12
|
+
inform string
|
13
|
+
else
|
14
|
+
error "couldn't execute sudo"
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dependency do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
# must install with gem
|
7
|
+
@rails = Dependency.new("rails", :installer => "gem")
|
8
|
+
@highline = Dependency.new("highline", :sudo => false, :installer => "gem")
|
9
|
+
@bundler = Dependency.new("bundler", :sudo => true, :installer => "gem")
|
10
|
+
|
11
|
+
# doesn't care what you install with
|
12
|
+
@foo = Dependency.new('foo', :flags => "-noop")
|
13
|
+
@bar = Dependency.new('bar', :sudo => false, :flags => "--verbose -q")
|
14
|
+
@baz = Dependency.new('baz', :sudo => true, :flags => "-qweF=1")
|
15
|
+
|
16
|
+
# can install with array of installer names
|
17
|
+
@git = Dependency.new("git", :installer => ["apt-get", "yum"])
|
18
|
+
@ack = Dependency.new("ack", :sudo => false, :installer => ["apt-get", "yum"])
|
19
|
+
@curl = Dependency.new("curl", :sudo => true, :installer => ["apt-get", "yum"])
|
20
|
+
|
21
|
+
@deps = [@rails, @highline, @bundler, @foo, @bar, @baz, @git, @ack, @curl]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "requires a hash as the 2nd argument" do
|
25
|
+
expect { Dependency.new("gem", "string") }.to raise_error(ArgumentError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "has a name" do
|
29
|
+
names = ["rails", "highline", "bundler", "foo", "bar", "baz", "git", "ack", "curl"]
|
30
|
+
@deps.zip(names).each do |dep, name|
|
31
|
+
dep.name.should == name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "has an array of installers" do
|
36
|
+
@deps.each do |dep|
|
37
|
+
dep.installers.should be_an Array
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "has a sudo? method" do
|
42
|
+
@deps.each do |dep|
|
43
|
+
bool = dep.sudo?
|
44
|
+
bool.should == !!bool # is_a Boolean
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "support flags" do
|
49
|
+
@rails.flags.should be_nil
|
50
|
+
@foo.flags.should == "-noop"
|
51
|
+
@bar.flags.should == "--verbose -q"
|
52
|
+
@baz.flags.should == "-qweF=1"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Installer do
|
4
|
+
|
5
|
+
# Stub out System.has? to allow us to use fake installers.
|
6
|
+
# Installer.new checks to see if the OS has that program.
|
7
|
+
#
|
8
|
+
before :all do
|
9
|
+
module Hardhat::System
|
10
|
+
class << self
|
11
|
+
alias _has? has?
|
12
|
+
def has?(program)
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
after :all do
|
20
|
+
module Hardhat::System
|
21
|
+
class << self
|
22
|
+
alias has? _has?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
before :each do
|
28
|
+
@gem_i = Installer.new('gem')
|
29
|
+
@apt_i = Installer.new('apt-get', :uninstall => :remove)
|
30
|
+
@flag_i = Installer.new('fman', :flags => '-qqy')
|
31
|
+
@sudo_i = Installer.new('sman', :sudo => true)
|
32
|
+
|
33
|
+
# must install with gem
|
34
|
+
@rails = Dependency.new("rails", :installer => "gem")
|
35
|
+
@highline = Dependency.new("highline", :sudo => false, :installer => "gem")
|
36
|
+
@bundler = Dependency.new("bundler", :sudo => true, :installer => "gem")
|
37
|
+
@gems = [@rails, @highline, @bundler]
|
38
|
+
|
39
|
+
# doesn't care what you install with
|
40
|
+
@foo = Dependency.new('foo')
|
41
|
+
@bar = Dependency.new('bar', :sudo => false, :flags => "--verbose -q")
|
42
|
+
@baz = Dependency.new('baz', :sudo => true, :flags => "-qweF=1")
|
43
|
+
@random = [@foo, @bar, @baz]
|
44
|
+
|
45
|
+
# can install with array of installer names
|
46
|
+
@git = Dependency.new("git", :installer => ["apt-get", "yum"])
|
47
|
+
@ack = Dependency.new("ack", :sudo => false, :installer => ["apt-get", "yum"])
|
48
|
+
@curl = Dependency.new("curl", :sudo => true, :installer => ["apt-get", "yum"])
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should have a program to run" do
|
52
|
+
@gem_i.program.should be_a String
|
53
|
+
@gem_i.program.should == "gem"
|
54
|
+
@apt_i.program.should == "apt-get"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should allow custom command mappings" do
|
58
|
+
@apt_i.should_receive(:system).with(/remove/).once
|
59
|
+
@apt_i.uninstall(@foo)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should have a method for each in COMMANDS, that calls system" do
|
63
|
+
Installer::COMMANDS.each do |cmd|
|
64
|
+
@gem_i.should_receive(:system).with("gem #{cmd} foo").once
|
65
|
+
@gem_i.public_send(cmd, @foo)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# update should be able to be called without args
|
70
|
+
|
71
|
+
it "should handle noarg update" do
|
72
|
+
@gem_i.should_receive(:system).with(/gem update/).once
|
73
|
+
@gem_i.update
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should still require dependencies for other commands" do
|
77
|
+
expect { @gem_i.install }.to raise_error(ArgumentError)
|
78
|
+
end
|
79
|
+
|
80
|
+
# dep array
|
81
|
+
|
82
|
+
it "should handle an array of dependencies" do
|
83
|
+
Installer::COMMANDS.each do |cmd|
|
84
|
+
@gem_i.should_receive(:system).with(/gem #{cmd}/).exactly(3).times
|
85
|
+
@gem_i.public_send(cmd, @gems)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# sudo
|
90
|
+
|
91
|
+
it "should support sudo in installer" do
|
92
|
+
Installer::COMMANDS.each do |cmd|
|
93
|
+
@sudo_i.should_receive(:system).with(/sudo/).once
|
94
|
+
@sudo_i.public_send(cmd, @foo)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should support sudo from dependencies" do
|
99
|
+
Installer::COMMANDS.each do |cmd|
|
100
|
+
@gem_i.should_receive(:system).with(/sudo/).once
|
101
|
+
@gem_i.public_send(cmd, @bundler)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should support sudo when calling commands" do
|
106
|
+
Installer::COMMANDS.each do |cmd|
|
107
|
+
@gem_i.should_receive(:system).with(/sudo/).once
|
108
|
+
@gem_i.public_send(cmd, @foo, :sudo => true)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should respect flags of command arguments over installer" do
|
113
|
+
Installer::COMMANDS.each do |cmd|
|
114
|
+
@sudo_i.should_not_receive(:system).with(/sudo/)
|
115
|
+
@sudo_i.public_send(cmd, @foo, :sudo => false)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should respect flags of command arguments over dependency" do
|
120
|
+
Installer::COMMANDS.each do |cmd|
|
121
|
+
@gem_i.should_receive(:system).with(/sudo/)
|
122
|
+
@gem_i.public_send(cmd, @bar, :sudo => true)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# flags
|
127
|
+
|
128
|
+
it "should support flags in installer" do
|
129
|
+
Installer::COMMANDS.each do |cmd|
|
130
|
+
@flag_i.should_receive(:system).with(/-qqy/).once
|
131
|
+
@flag_i.public_send(cmd, @foo)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should support flags from dependencies" do
|
136
|
+
Installer::COMMANDS.each do |cmd|
|
137
|
+
@gem_i.should_receive(:system).with(/--verbose -q/).once
|
138
|
+
@gem_i.public_send(cmd, @bar)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should support flags arguments when calling commands" do
|
143
|
+
Installer::COMMANDS.each do |cmd|
|
144
|
+
@gem_i.should_receive(:system).with(/--quite/).once
|
145
|
+
@gem_i.public_send(cmd, @foo, :flags => '--quite')
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should respect flags of command arguments over installer" do
|
150
|
+
Installer::COMMANDS.each do |cmd|
|
151
|
+
@flag_i.should_not_receive(:system).with(/-qqy/)
|
152
|
+
@flag_i.public_send(cmd, @foo, :flags => '-lol')
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should respect flags of command arguments over dependency" do
|
157
|
+
Installer::COMMANDS.each do |cmd|
|
158
|
+
@flag_i.should_not_receive(:system).with(/--verbose -q/)
|
159
|
+
@flag_i.public_send(cmd, @bar, :flags => '-lol')
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# allowable installer
|
164
|
+
|
165
|
+
it "should not install a dependency without itself in array of installers" do
|
166
|
+
Installer::COMMANDS.each do |cmd|
|
167
|
+
@gem_i.should_not_receive(:system) # no sys calls in tests
|
168
|
+
expect { @gem_i.public_send(cmd, @git) }.to raise_error
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should not install a dependency without itself as the installer" do
|
173
|
+
Installer::COMMANDS.each do |cmd|
|
174
|
+
expect { @flag_i.public_send(cmd, @rails) }.to raise_error
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
include Hardhat
|
5
|
+
shared_examples_for Repository do
|
6
|
+
|
7
|
+
after :each do
|
8
|
+
FileUtils.rm_rf host.path
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have a url" do
|
12
|
+
host.should respond_to(:url)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have a path" do
|
16
|
+
host.should respond_to(:path)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should redefine the get method" do
|
20
|
+
host.should respond_to(:get)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should download a project with `get`" do
|
24
|
+
raise "#{host.path} already exists" if Dir.exists? host.path
|
25
|
+
host.get
|
26
|
+
Dir.exists?(host.path).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/system_spec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe System do
|
4
|
+
|
5
|
+
describe "::has?" do
|
6
|
+
it "should check for installed programs" do
|
7
|
+
System.has?(:ls).should be_true
|
8
|
+
System.has?([:ls, :cd, :rm]).should be_true
|
9
|
+
System.has?(:foobarbaz).should be_false
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "::prompt_sudo" do
|
14
|
+
context "with correct password" do
|
15
|
+
it "prompts user for sudo password and informs given string" do
|
16
|
+
string = "hello friend"
|
17
|
+
System.should_receive(:system).with(/sudo -k/).and_return(true)
|
18
|
+
$stdout.should_receive(:puts).with(/#{string}/)
|
19
|
+
System.prompt_sudo(string)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "with incorrect password" do
|
24
|
+
it "prompts user for sudo then errors and exits" do
|
25
|
+
System.should_receive(:system).with(/sudo -k/).and_return(false)
|
26
|
+
$stdout.should_receive(:puts).with(/couldn't execute sudo/)
|
27
|
+
expect { System.prompt_sudo("hello") }.to raise_error(SystemExit)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Hardhat do
|
4
|
+
describe "::VERSION" do
|
5
|
+
|
6
|
+
it "should be a String" do
|
7
|
+
Hardhat::VERSION.should be_a(String)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should have valid version numbers" do
|
11
|
+
version = Hardhat::VERSION.split('.')
|
12
|
+
version.each do |part|
|
13
|
+
expect { Integer(part) }.to_not raise_error
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should only have 3 parts" do
|
18
|
+
Hardhat::VERSION.split('.').should have(3).items
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hardhat
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nathan Lilienthal
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: trollop
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Elegant DSL for managing build dependencies and project builds.
|
63
|
+
email:
|
64
|
+
- nathanl@ccs.neu.edu
|
65
|
+
executables:
|
66
|
+
- hardhat
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- .gitignore
|
71
|
+
- .rspec
|
72
|
+
- Gemfile
|
73
|
+
- LICENSE.txt
|
74
|
+
- README.md
|
75
|
+
- Rakefile
|
76
|
+
- bin/bootstrap
|
77
|
+
- bin/hardhat
|
78
|
+
- example/blueprint.rb
|
79
|
+
- hardhat.gemspec
|
80
|
+
- lib/hardhat.rb
|
81
|
+
- lib/hardhat/dependency.rb
|
82
|
+
- lib/hardhat/ext.rb
|
83
|
+
- lib/hardhat/ext/string.rb
|
84
|
+
- lib/hardhat/installer.rb
|
85
|
+
- lib/hardhat/repository.rb
|
86
|
+
- lib/hardhat/repository/git.rb
|
87
|
+
- lib/hardhat/repository/svn.rb
|
88
|
+
- lib/hardhat/system.rb
|
89
|
+
- lib/hardhat/version.rb
|
90
|
+
- spec/dependency_spec.rb
|
91
|
+
- spec/installer_spec.rb
|
92
|
+
- spec/repository/git_spec.rb
|
93
|
+
- spec/repository/svn_spec.rb
|
94
|
+
- spec/spec_helper.rb
|
95
|
+
- spec/support/shared_examples_for_repository.rb
|
96
|
+
- spec/system_spec.rb
|
97
|
+
- spec/version_spec.rb
|
98
|
+
homepage: https://github.com/nathan/hardhat
|
99
|
+
licenses: []
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 1.8.23
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: Construction for your project.
|
122
|
+
test_files:
|
123
|
+
- spec/dependency_spec.rb
|
124
|
+
- spec/installer_spec.rb
|
125
|
+
- spec/repository/git_spec.rb
|
126
|
+
- spec/repository/svn_spec.rb
|
127
|
+
- spec/spec_helper.rb
|
128
|
+
- spec/support/shared_examples_for_repository.rb
|
129
|
+
- spec/system_spec.rb
|
130
|
+
- spec/version_spec.rb
|