exogenesis 0.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.hound.yml +117 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +6 -0
- data/README.md +70 -8
- data/Rakefile +6 -1
- data/exogenesis.gemspec +10 -8
- data/lib/exogenesis.rb +14 -6
- data/lib/exogenesis/passengers/dotfile.rb +28 -0
- data/lib/exogenesis/passengers/fonts.rb +44 -0
- data/lib/exogenesis/passengers/git_repo.rb +36 -0
- data/lib/exogenesis/passengers/homebrew.rb +78 -0
- data/lib/exogenesis/passengers/homebrew_cask.rb +70 -0
- data/lib/exogenesis/passengers/npm.rb +43 -0
- data/lib/exogenesis/passengers/python.rb +37 -0
- data/lib/exogenesis/passengers/rbenv.rb +51 -0
- data/lib/exogenesis/passengers/rvm.rb +55 -0
- data/lib/exogenesis/passengers/vundle.rb +37 -0
- data/lib/exogenesis/support/executor.rb +195 -0
- data/lib/exogenesis/support/output.rb +93 -0
- data/lib/exogenesis/support/passenger.rb +57 -0
- data/lib/exogenesis/support/ship.rb +30 -0
- data/lib/exogenesis/support/spacesuit.rb +31 -0
- data/lib/exogenesis/support/task_skipped.rb +9 -0
- data/lib/exogenesis/version.rb +1 -1
- data/spec/spec_helper.rb +20 -0
- data/spec/support/executor_double.rb +28 -0
- data/spec/unit/dotfile_spec.rb +40 -0
- data/spec/unit/fonts_spec.rb +54 -0
- data/spec/unit/git_repo_spec.rb +44 -0
- data/spec/unit/homebrew_cask_spec.rb +96 -0
- data/spec/unit/homebrew_spec.rb +107 -0
- data/spec/unit/npm_spec.rb +58 -0
- data/spec/unit/python_spec.rb +64 -0
- data/spec/unit/rbenv_spec.rb +52 -0
- data/spec/unit/rvm_spec.rb +79 -0
- data/spec/unit/vundle_spec.rb +62 -0
- metadata +89 -30
- data/lib/exogenesis/abstract_package_manager.rb +0 -25
- data/lib/exogenesis/dotfile.rb +0 -45
- data/lib/exogenesis/homebrew.rb +0 -45
- data/lib/exogenesis/oh-my-zsh.rb +0 -28
- data/lib/exogenesis/rvm.rb +0 -32
- data/lib/exogenesis/vundle.rb +0 -53
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 85feab0e9949fef0074531c9400d1b105f690571
|
4
|
+
data.tar.gz: c3ae68824eeb4007c9548313a3d2ceb81b50256e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a02b6e88da9d019bc7fbb1cfd9091f3d6cd8d355a66a51a80275f6d639701671662600bb65c750424449225bec5ab0507a3b23c30556ee065b29d4fa4efbca0d
|
7
|
+
data.tar.gz: f02c877d2e01d492e86cf036950770a53ccab2ad7730d18bfcfc6f3bfcdb86df625b2bab99419b48a4299caba82d579774021566e4c624edaf4b419e1a98bb15
|
data/.hound.yml
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
AllCops:
|
2
|
+
Include:
|
3
|
+
- '../**/*.rake'
|
4
|
+
- 'Gemfile'
|
5
|
+
- 'Guardfile'
|
6
|
+
- 'Rakefile'
|
7
|
+
Exclude:
|
8
|
+
- !ruby/regexp /spec\/setup/
|
9
|
+
|
10
|
+
# Avoid parameter lists longer than five parameters.
|
11
|
+
ParameterLists:
|
12
|
+
Max: 4
|
13
|
+
CountKeywordArgs: true
|
14
|
+
|
15
|
+
# Avoid more than `Max` levels of nesting.
|
16
|
+
BlockNesting:
|
17
|
+
Max: 3
|
18
|
+
|
19
|
+
# Align with the style guide.
|
20
|
+
CollectionMethods:
|
21
|
+
PreferredMethods:
|
22
|
+
collect: 'map'
|
23
|
+
inject: 'reduce'
|
24
|
+
find: 'detect'
|
25
|
+
find_all: 'select'
|
26
|
+
|
27
|
+
HashSyntax:
|
28
|
+
Enabled: true
|
29
|
+
|
30
|
+
StringLiterals:
|
31
|
+
Enabled: true
|
32
|
+
|
33
|
+
Void:
|
34
|
+
Enabled: true
|
35
|
+
|
36
|
+
MethodLength:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
LineLength:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
DotPosition:
|
43
|
+
EnforcedStyle: 'leading'
|
44
|
+
|
45
|
+
SpaceInsideHashLiteralBraces:
|
46
|
+
Enabled: true
|
47
|
+
|
48
|
+
AlignParameters:
|
49
|
+
Enabled: true
|
50
|
+
|
51
|
+
# I don't agree with this
|
52
|
+
Blocks:
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
NumericLiterals:
|
56
|
+
Enabled: true
|
57
|
+
|
58
|
+
SpaceInsideBrackets:
|
59
|
+
Enabled: true
|
60
|
+
|
61
|
+
WordArray:
|
62
|
+
Enabled: true
|
63
|
+
|
64
|
+
Lambda:
|
65
|
+
Enabled: true
|
66
|
+
|
67
|
+
RegexpLiteral:
|
68
|
+
Enabled: true
|
69
|
+
|
70
|
+
# Don't agree
|
71
|
+
ConstantName:
|
72
|
+
Enabled: false
|
73
|
+
|
74
|
+
TrivialAccessors:
|
75
|
+
Enabled: true
|
76
|
+
ExactNameMatch: true
|
77
|
+
|
78
|
+
Alias:
|
79
|
+
Enabled: true
|
80
|
+
|
81
|
+
Loop:
|
82
|
+
Enabled: false
|
83
|
+
|
84
|
+
# Do not agree at all
|
85
|
+
AndOr:
|
86
|
+
Enabled: false
|
87
|
+
|
88
|
+
# This is done by YARD Stick
|
89
|
+
Documentation:
|
90
|
+
Enabled: false
|
91
|
+
|
92
|
+
# Braces can be really, really useful for clarity
|
93
|
+
BracesAroundHashParameters:
|
94
|
+
Enabled: false
|
95
|
+
|
96
|
+
# I prefer raise over fail
|
97
|
+
SignalException:
|
98
|
+
EnforcedStyle: only_raise
|
99
|
+
|
100
|
+
ClassLength:
|
101
|
+
CountComments: false
|
102
|
+
Max: 140
|
103
|
+
|
104
|
+
# The suggested style does not match the common ruby way of aligning the content of a hash
|
105
|
+
IndentHash:
|
106
|
+
Enabled: false
|
107
|
+
|
108
|
+
# This cop seems to not work correctly. Also we don't agree with it.
|
109
|
+
FileName:
|
110
|
+
Enabled: false
|
111
|
+
|
112
|
+
# Double negations are extremely useful
|
113
|
+
DoubleNegation:
|
114
|
+
Enabled: false
|
115
|
+
|
116
|
+
Output:
|
117
|
+
Enabled: false
|
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
before_install: gem install bundler -v 1.6
|
2
|
+
language: ruby
|
3
|
+
rvm:
|
4
|
+
- 1.9.3
|
5
|
+
- 2.0.0
|
6
|
+
- jruby-19mode
|
7
|
+
- jruby-head
|
8
|
+
- rbx-2.2.3
|
9
|
+
- ruby-head
|
10
|
+
matrix:
|
11
|
+
allow_failures:
|
12
|
+
- rvm: ruby-head
|
13
|
+
- rvm: jruby-19mode
|
14
|
+
- rvm: jruby-head
|
15
|
+
- rvm: rbx-2.2.3
|
16
|
+
script: "bundle exec rake"
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,23 +1,85 @@
|
|
1
1
|
# Exogenesis
|
2
2
|
|
3
|
-
|
3
|
+
| Project | Exogenesis
|
4
|
+
|:----------------|:--------------------------------------------------
|
5
|
+
| Homepage | https://github.com/moonglum/exogenesis
|
6
|
+
| CI | [![Build Status](http://img.shields.io/travis/moonglum/exogenesis.svg)](http://travis-ci.org/moonglum/exogenesis)
|
7
|
+
| Code Metrics | [![Code Climate](http://img.shields.io/codeclimate/github/moonglum/exogenesis.svg)](https://codeclimate.com/github/moonglum/exogenesis) [![Code Climate Coverage](http://img.shields.io/codeclimate/coverage/github/moonglum/exogenesis.svg)](https://codeclimate.com/github/moonglum/exogenesis)
|
8
|
+
| Gem Version | [![Gem Version](http://img.shields.io/gem/v/exogenesis.svg)](http://rubygems.org/gems/exogenesis)
|
9
|
+
| Dependencies | [![Dependency Status](http://img.shields.io/gemnasium/moonglum/exogenesis.svg)](https://gemnasium.com/moonglum/exogenesis)
|
10
|
+
|
11
|
+
|
12
|
+
A collection of classes that help you install, update and teardown package managers and other things useful for your dotfiles. It's something like a meta package manager (package manager is the wrong word... still searching for a better one). After setting it up you can do the following:
|
13
|
+
|
14
|
+
* `rake up`: Setup, install and update your software
|
15
|
+
* `rake down`: Remove everything installed by Exogenesis
|
16
|
+
* `rake clean`: Run cleanup tasks
|
17
|
+
|
18
|
+
It creates a beautiful output if you want it to (see Configuration). For a little [demonstration](http://ascii.io/a/2491) (a little updated) see this asciicast of my `rake install` running on my (already installed :wink:) system.
|
4
19
|
|
5
20
|
**Please read the source code of this gem before you use it. I give no guarantee that this will not destroy your computer entirely.**
|
6
21
|
|
22
|
+
## How to use it
|
23
|
+
|
24
|
+
The current best practice is to create a Rakefile in your dotfile repo that looks something like this:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
#!/usr/bin/env rake
|
28
|
+
require "yaml"
|
29
|
+
require "exogenesis"
|
30
|
+
|
31
|
+
Output.fancy
|
32
|
+
packages_file = YAML.load_file("packages.yml")
|
33
|
+
ship = Ship.new(packages_file)
|
34
|
+
|
35
|
+
[:up, :down, :clean].each do |task_name|
|
36
|
+
desc "#{task_name.capitalize} the Dotfiles"
|
37
|
+
task task_name do
|
38
|
+
ship.public_send task_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
You can find a list of real-world usage of this gem [here](https://github.com/moonglum/exogenesis/wiki/List-of-Users). There are links to the actual install files there, so you can see how they did it.
|
44
|
+
|
45
|
+
## If you use it...
|
46
|
+
|
47
|
+
...and you really like it, you can add the exogenesis badge to the title of your dotfile's README and link to this project:
|
48
|
+
|
49
|
+
![badge](http://img.shields.io/badge/%F0%9F%9A%80-Created_with_Exogenesis-be1d77.svg)
|
50
|
+
|
51
|
+
```markdown
|
52
|
+
[![badge](http://img.shields.io/badge/%F0%9F%9A%80-Created_with_Exogenesis-be1d77.svg)](https://github.com/moonglum/exogenesis)
|
53
|
+
```
|
54
|
+
|
7
55
|
## The Interface of the classes
|
8
56
|
|
9
57
|
Every class has the following methods (with the exception of `initialize` they all take no arguments):
|
10
58
|
|
11
59
|
* `initialize`: The arguments are arbitrary, please see the individual files for it
|
12
|
-
* `
|
13
|
-
* `
|
14
|
-
* `
|
15
|
-
* `cleanup`: Starts a clean-up process
|
16
|
-
* `teardown`: Uninstalls all packages and the package manager itself
|
60
|
+
* `up`: Installs the package manager itself, all packages and updates the package manager itself and all packages
|
61
|
+
* `clean`: Starts a clean-up process
|
62
|
+
* `down`: Uninstalls all packages and the package manager itself
|
17
63
|
|
18
64
|
Not all package managers will need all of the methods. Just do not implement them.
|
19
65
|
|
66
|
+
## Supported Managers
|
67
|
+
|
68
|
+
* **Dotfile:** Link/Unlink your dotfiles
|
69
|
+
* **Fonts:** Manage your fonts
|
70
|
+
* **Homebrew:** Install/Uninstall/Update Homebrew and its packages
|
71
|
+
* **HomebrewCask:** Install/Tap [Homebrew Cask](http://caskroom.io) and its packages
|
72
|
+
* **RVM:** Install/Uninstall/Update RVM and Rubies
|
73
|
+
* **Rbenv:** Install/Uninstall/Update Rbenv+Ruby-Build and Rubies
|
74
|
+
* **Vundle:** Install/Uninstall/Update Vundle and its packages
|
75
|
+
* **GitRepo:** Clone/Pull Git Repos to certain paths
|
76
|
+
* **NPM**: Install/Uninstall NPM and its packages
|
77
|
+
|
20
78
|
## Contributing
|
21
79
|
|
22
|
-
Additions of new classes are more than welcome, even if they are complimentary to the ones already provided. If you want to contribute a new class, please see the interface section and inherit from `
|
23
|
-
|
80
|
+
Additions of new classes are more than welcome, even if they are complimentary to the ones already provided. If you want to contribute a new class, please see the interface section and inherit from `Passenger`. Please use the Executor singleton for communicating the status with the user and for executing shell scripts.
|
81
|
+
|
82
|
+
So far, the following people have contributed to the project:
|
83
|
+
|
84
|
+
* Bodo Tasche aka @bitboxer
|
85
|
+
* Felix Schäfer aka @thegcat
|
data/Rakefile
CHANGED
data/exogenesis.gemspec
CHANGED
@@ -4,20 +4,22 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'exogenesis/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'exogenesis'
|
8
8
|
spec.version = Exogenesis::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['moonglum']
|
10
|
+
spec.email = ['moonglum@moonbeamlabs.com']
|
11
11
|
spec.description = %q{Build your dotfile installer, updater and teardown}
|
12
12
|
spec.summary = %q{A collection of classes that help you install, update and teardown package managers and other things useful for your dotfiles.}
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
13
|
+
spec.homepage = 'https://github.com/moonglum/exogenesis'
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.
|
22
|
-
spec.add_development_dependency
|
21
|
+
spec.add_dependency 'megingiard', '~> 0.1.0'
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.6.0'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.3.2'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.0.0'
|
23
25
|
end
|
data/lib/exogenesis.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
1
|
+
require 'exogenesis/version'
|
2
|
+
require 'exogenesis/passengers/dotfile'
|
3
|
+
require 'exogenesis/passengers/homebrew'
|
4
|
+
require 'exogenesis/passengers/homebrew_cask'
|
5
|
+
require 'exogenesis/passengers/rvm'
|
6
|
+
require 'exogenesis/passengers/rbenv'
|
7
|
+
require 'exogenesis/passengers/vundle'
|
8
|
+
require 'exogenesis/passengers/fonts'
|
9
|
+
require 'exogenesis/passengers/python'
|
10
|
+
require 'exogenesis/passengers/git_repo'
|
11
|
+
require 'exogenesis/passengers/npm'
|
12
|
+
require 'exogenesis/support/output'
|
13
|
+
require 'exogenesis/support/executor'
|
14
|
+
require 'exogenesis/support/ship'
|
7
15
|
|
8
16
|
module Exogenesis
|
9
17
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'exogenesis/support/passenger'
|
2
|
+
|
3
|
+
# Links all files in the given directory to your home directory
|
4
|
+
class Dotfile < Passenger
|
5
|
+
register_as :dotfile
|
6
|
+
needs :directory_name
|
7
|
+
with_emoji :house
|
8
|
+
|
9
|
+
def up
|
10
|
+
each_dotfile do |source, destination|
|
11
|
+
ln_s source, destination
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def down
|
16
|
+
each_dotfile do |_source, destination|
|
17
|
+
rm_rf destination
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def each_dotfile
|
24
|
+
get_path_in_working_directory(directory_name).each_child do |source|
|
25
|
+
yield source, get_path_in_home(".#{source.basename}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'exogenesis/support/passenger'
|
2
|
+
|
3
|
+
# Installs and Removes Fonts
|
4
|
+
class Fonts < Passenger
|
5
|
+
register_as :fonts
|
6
|
+
needs :fonts_path
|
7
|
+
with_emoji :book
|
8
|
+
|
9
|
+
def up
|
10
|
+
install_all_fonts
|
11
|
+
end
|
12
|
+
|
13
|
+
def down
|
14
|
+
collect_fonts do |file|
|
15
|
+
rm_rf target_font_path(file)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def install_all_fonts
|
22
|
+
collect_fonts do |file|
|
23
|
+
install_font(file)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def collect_fonts
|
28
|
+
Dir.glob(File.join(fonts_path, '**/*.{ttf,otf}')).each do |file|
|
29
|
+
yield file
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def install_font(file)
|
34
|
+
if File.exist? target_font_path(file)
|
35
|
+
skip_task "Copying #{File.basename file}", 'Already copied'
|
36
|
+
else
|
37
|
+
execute "Copying #{File.basename file}", "cp #{file} #{target_font_path(file)}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def target_font_path(file)
|
42
|
+
File.join(ENV['HOME'], 'Library/Fonts', File.basename(file))
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'exogenesis/support/passenger'
|
2
|
+
|
3
|
+
# Clone, Update and Delete Git Repos
|
4
|
+
# REQUIRES: git
|
5
|
+
class GitRepo < Passenger
|
6
|
+
register_as :git_repo
|
7
|
+
needs :repos
|
8
|
+
with_emoji :arrow_down
|
9
|
+
|
10
|
+
# Clone the Repo if it doesn't exist
|
11
|
+
# Pull the Repo if it does
|
12
|
+
def up
|
13
|
+
each_repo_and_target do |git_repo, target|
|
14
|
+
if target.exist?
|
15
|
+
pull_repo(git_repo, target)
|
16
|
+
else
|
17
|
+
clone_repo(git_repo, target)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Delete the Repos
|
23
|
+
def down
|
24
|
+
each_repo_and_target do |_, target|
|
25
|
+
rm_rf(target)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def each_repo_and_target
|
32
|
+
repos.each_pair do |git_repo, raw_target|
|
33
|
+
yield git_repo, get_path_for(raw_target)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'exogenesis/support/passenger'
|
2
|
+
|
3
|
+
# Manages Homebrew - the premier package manager for Mac OS
|
4
|
+
class Homebrew < Passenger
|
5
|
+
INSTALL_SCRIPT = 'https://raw.github.com/mxcl/homebrew/go'
|
6
|
+
TEARDOWN_SCRIPT = 'https://gist.github.com/mxcl/1173223/raw/a833ba44e7be8428d877e58640720ff43c59dbad/uninstall_homebrew.sh'
|
7
|
+
|
8
|
+
register_as :homebrew
|
9
|
+
needs :brews
|
10
|
+
with_emoji :beer
|
11
|
+
|
12
|
+
def up
|
13
|
+
install_homebrew
|
14
|
+
install_missing_brews
|
15
|
+
update_existing_brews
|
16
|
+
end
|
17
|
+
|
18
|
+
def clean
|
19
|
+
execute 'Clean Up', 'brew cleanup'
|
20
|
+
end
|
21
|
+
|
22
|
+
def down
|
23
|
+
execute 'Teardown', "\\curl -L #{TEARDOWN_SCRIPT} | bash -s"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def install_homebrew
|
29
|
+
if command_exists? 'brew'
|
30
|
+
skip_task 'Install Homebrew'
|
31
|
+
else
|
32
|
+
execute_interactive 'Install Homebrew', "ruby -e \"$(curl -fsSL #{INSTALL_SCRIPT})\""
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def install_missing_brews
|
37
|
+
each_brew_to_install do |brew, options|
|
38
|
+
install_package brew, options
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def update_existing_brews
|
43
|
+
execute 'Updating Homebrew', 'brew update'
|
44
|
+
|
45
|
+
if outdated_brews.length == 0
|
46
|
+
skip_task 'Upgrade Brews'
|
47
|
+
else
|
48
|
+
info 'Outdated Brews', outdated_brews.join(', ')
|
49
|
+
execute 'Upgrade Brews', 'brew upgrade'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def each_brew_to_install
|
54
|
+
brews.each do |brew|
|
55
|
+
if brew.class == String
|
56
|
+
name = brew
|
57
|
+
options = []
|
58
|
+
else
|
59
|
+
name = brew.keys.first
|
60
|
+
options = brew[name]
|
61
|
+
end
|
62
|
+
|
63
|
+
yield name, options unless installed_brews.include? name
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def installed_brews
|
68
|
+
@installed_brews ||= silent_execute('brew ls').split(/\s/)
|
69
|
+
end
|
70
|
+
|
71
|
+
def outdated_brews
|
72
|
+
@outdated_brews ||= silent_execute('brew outdated').split(/\s/)
|
73
|
+
end
|
74
|
+
|
75
|
+
def install_package(name, options)
|
76
|
+
execute "Installing #{name}", "brew install #{name} #{options.join}"
|
77
|
+
end
|
78
|
+
end
|