velcro-strap 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +83 -0
- data/Rakefile +5 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/bin/velcro +54 -0
- data/lib/ext/string.rb +41 -0
- data/lib/velcro.rb +42 -0
- data/lib/velcro/concerns/flags.rb +32 -0
- data/lib/velcro/concerns/shell.rb +20 -0
- data/lib/velcro/config.rb +54 -0
- data/lib/velcro/errors.rb +6 -0
- data/lib/velcro/installer/base.rb +57 -0
- data/lib/velcro/installer/linux.rb +13 -0
- data/lib/velcro/installer/mac.rb +41 -0
- data/lib/velcro/scaffold.rb +39 -0
- data/lib/velcro/setter/base.rb +79 -0
- data/lib/velcro/setter/linux.rb +7 -0
- data/lib/velcro/setter/mac.rb +26 -0
- data/lib/velcro/status/dotfiles.rb +20 -0
- data/lib/velcro/status/git.rb +20 -0
- data/lib/velcro/status/machine.rb +23 -0
- data/lib/velcro/status/ruby.rb +28 -0
- data/lib/velcro/status/symlinks.rb +27 -0
- data/lib/velcro/strap.rb +115 -0
- data/lib/velcro/symlinker.rb +53 -0
- data/lib/velcro/system.rb +35 -0
- data/lib/velcro/version.rb +4 -0
- data/velcro.gemspec +31 -0
- metadata +163 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f2738ef112881e8c79bcf913d655429191412270
|
4
|
+
data.tar.gz: a248225116a093e7cb4dcce655b4cd27efe91249
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c3256b26fef52d3519df9874f49a44b38e90f3b48b3c2a99b79457a1f77e9fbea62cf0002c4ae74bbba5c0ec9bbf62b7e361eb31eeae866f9bb2b1d2622730d4
|
7
|
+
data.tar.gz: 38f72bbb84daf9604a69829b935c8244805a631676c97399b071fa83319a182253cf8947afde0dde2aead0d186c8df8df283c7caac548a36ce71b321a914ed5a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Matthew Werner
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Velcro [![Build Status](https://travis-ci.org/mwerner/velcro.svg?branch=master)](https://travis-ci.org/mwerner/velcro)
|
2
|
+
|
3
|
+
Velcro is meant to be a very straight-forward declarative way to automate the
|
4
|
+
setup of a new machine. It requires a `.dotfiles` directory to be cloned and
|
5
|
+
is very opinionated about the structure.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install the gem on your machine
|
10
|
+
|
11
|
+
$ gem install velcro-strap
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
Velcro uses a command line interface with the following commands:
|
16
|
+
|
17
|
+
### `strap`
|
18
|
+
|
19
|
+
Strap is the bread and butter of velcro. With one command you should be able to fully install a system as you're accustomed to using.
|
20
|
+
|
21
|
+
$ velcro strap git@github.com:velcro/dotfiles.git
|
22
|
+
|
23
|
+
This will clone your dotfiles repo, load the `.velcrorc` file present in the cloned repo and process it on the current machine.
|
24
|
+
|
25
|
+
Options:
|
26
|
+
n, [--dryrun], [--no-dryrun] Don't make any changes, just log output
|
27
|
+
a, [--apps], [--no-apps] Only install specified apps
|
28
|
+
o, [--host], [--no-host] Only run host specific configuration
|
29
|
+
d, [--dotfiles], [--no-dotfiles] Only clone the repo
|
30
|
+
y, [--symlinks], [--no-symlinks] Only symlink files
|
31
|
+
c, [--scaffold], [--no-scaffold] Only generate filesystem scaffolding
|
32
|
+
s, [--settings], [--no-settings] Only apply settings for your system
|
33
|
+
|
34
|
+
### `install`
|
35
|
+
|
36
|
+
You can install apps ad-hoc on your machine through velcro. This doesn't use any `.velcrorc`, the apps are just passed in at the command line
|
37
|
+
|
38
|
+
$ velcro install zsh mysql
|
39
|
+
|
40
|
+
You can pass any number of app names to `install`. Velcro will look for matching names in `brew`, `cask` and `velcro` itself. You can look through the [installers directory] to find out more about velcro's installation method.
|
41
|
+
|
42
|
+
Options:
|
43
|
+
n, [--dryrun], [--no-dryrun] Don't make any changes, just log output
|
44
|
+
|
45
|
+
### `symlink`
|
46
|
+
|
47
|
+
Velcro makes the assumption that you keep `*.symlink` files in your dotfiles directory. This command symlinks these files into your `$HOME` directory with a `.` prefix.
|
48
|
+
|
49
|
+
$ velcro symlink
|
50
|
+
|
51
|
+
For example, if you had a file in your dotfiles repo such as `dotfiles/mysql/my.cnf.symlink` velcro would symlink that file to `~/.my.cnf`, right where it's supposed to be.
|
52
|
+
|
53
|
+
Options:
|
54
|
+
f, [--force] Overwrite existing symlinks in $HOME
|
55
|
+
n, [--dryrun], [--no-dryrun] Don't make any changes, just log output
|
56
|
+
|
57
|
+
### `status`
|
58
|
+
|
59
|
+
Running status will return various bits of information about the state of your machine. This is good to check what parts of the velcro process are done and which parts are not as you'd expect.
|
60
|
+
|
61
|
+
$ velcro status
|
62
|
+
|
63
|
+
Options:
|
64
|
+
g, [--git], [--no-git] Only report `git` information
|
65
|
+
s, [--symlinks], [--no-symlinks] Only show symlink mapping
|
66
|
+
d, [--dotfiles], [--no-dotfiles] Only check .dotfiles presence
|
67
|
+
r, [--ruby], [--no-ruby] Only report ruby version info
|
68
|
+
|
69
|
+
## Development
|
70
|
+
|
71
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
72
|
+
|
73
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
74
|
+
|
75
|
+
## Contributing
|
76
|
+
|
77
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/mwerner/velcro. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
78
|
+
|
79
|
+
|
80
|
+
## License
|
81
|
+
|
82
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
83
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'velcro'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/bin/velcro
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'velcro'
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module Velcro
|
6
|
+
# CLI Interface for Velcro
|
7
|
+
class Command < Thor
|
8
|
+
option :dryrun, type: :boolean, aliases: :n
|
9
|
+
option :apps, type: :boolean, aliases: :a
|
10
|
+
option :host, type: :boolean, aliases: :o
|
11
|
+
option :dotfiles, type: :boolean, aliases: :d
|
12
|
+
option :symlinks, type: :boolean, aliases: :y
|
13
|
+
option :scaffold, type: :boolean, aliases: :c
|
14
|
+
option :settings, type: :boolean, aliases: :s
|
15
|
+
desc 'strap [REPO]', 'Setup a blank system with your dotfiles'
|
16
|
+
def strap(repo = nil)
|
17
|
+
Strap.new(repo, options).run
|
18
|
+
rescue ArgumentError
|
19
|
+
puts 'ERROR: "velcro strap" must be provided a repo url when cloning dotfiles'
|
20
|
+
puts "Usage:\n velcro strap git@github.com:velcro/dotfiles.git"
|
21
|
+
puts "\nTo avoid cloning use the --no-dotfiles flag"
|
22
|
+
rescue Error::MissingDotfilesError
|
23
|
+
puts 'ERROR: "velcro strap" requires dotfiles to be present, it can\'t skip cloning at this time'
|
24
|
+
puts "Usage:\n velcro strap git@github.com:velcro/dotfiles.git"
|
25
|
+
end
|
26
|
+
|
27
|
+
option :dryrun, type: :boolean, aliases: :n
|
28
|
+
desc 'install [*APPS]', 'Install software on your machine'
|
29
|
+
def install(*targets)
|
30
|
+
installer = Installer::Base.installer(options)
|
31
|
+
targets.each do |target|
|
32
|
+
installer.install target
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
option :force, type: :boolean, aliases: :f
|
37
|
+
option :dryrun, type: :boolean, aliases: :n
|
38
|
+
desc 'symlink', 'Symlink .symlink files from your dotfiles dir to your home dir'
|
39
|
+
def symlink
|
40
|
+
Symlinker.new(options).symlink!
|
41
|
+
end
|
42
|
+
|
43
|
+
option :git, type: :boolean, aliases: :g
|
44
|
+
option :symlinks, type: :boolean, aliases: :s
|
45
|
+
option :dotfiles, type: :boolean, aliases: :d
|
46
|
+
option :ruby, type: :boolean, aliases: :r
|
47
|
+
desc 'status', 'Print the current state of your machine'
|
48
|
+
def status
|
49
|
+
Status::Machine.new(options).print
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Velcro::Command.start(ARGV)
|
data/lib/ext/string.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Extensions to the String class
|
2
|
+
# rubocop:disable Metrics/AbcSize
|
3
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
4
|
+
# rubocop:disable Metrics/MethodLength
|
5
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
6
|
+
class String
|
7
|
+
def constantize
|
8
|
+
names = split('::')
|
9
|
+
|
10
|
+
# Trigger a built-in NameError exception including the
|
11
|
+
# ill-formed constant in the message.
|
12
|
+
Object.const_get(self) if names.empty?
|
13
|
+
|
14
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
15
|
+
names.shift if names.size > 1 && names.first.empty?
|
16
|
+
|
17
|
+
names.inject(Object) do |constant, name|
|
18
|
+
if constant == Object
|
19
|
+
constant.const_get(name)
|
20
|
+
else
|
21
|
+
candidate = constant.const_get(name)
|
22
|
+
next candidate if constant.const_defined?(name, false)
|
23
|
+
next candidate unless Object.const_defined?(name)
|
24
|
+
|
25
|
+
# Go down the ancestors to check if it is owned directly. The check
|
26
|
+
# stops when we reach Object or the end of ancestors tree.
|
27
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
28
|
+
break const if ancestor == Object
|
29
|
+
break ancestor if ancestor.const_defined?(name, false)
|
30
|
+
end
|
31
|
+
|
32
|
+
# owner is in Object, so raise
|
33
|
+
constant.const_get(name, false)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
# rubocop:enable Metrics/AbcSize
|
39
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
40
|
+
# rubocop:enable Metrics/MethodLength
|
41
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
data/lib/velcro.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'ext/string'
|
2
|
+
require 'velcro/version'
|
3
|
+
require 'velcro/errors'
|
4
|
+
require 'velcro/system'
|
5
|
+
|
6
|
+
# Velcro Lib
|
7
|
+
module Velcro
|
8
|
+
include Velcro::System
|
9
|
+
include Velcro::Error
|
10
|
+
|
11
|
+
autoload :Config, 'velcro/config'
|
12
|
+
autoload :Symlinker, 'velcro/symlinker'
|
13
|
+
autoload :Scaffold, 'velcro/scaffold'
|
14
|
+
autoload :Strap, 'velcro/strap'
|
15
|
+
|
16
|
+
# Installer Classes
|
17
|
+
module Installer
|
18
|
+
autoload :Base, 'velcro/installer/base'
|
19
|
+
autoload :Mac, 'velcro/installer/mac'
|
20
|
+
autoload :Linux, 'velcro/installer/linux'
|
21
|
+
end
|
22
|
+
|
23
|
+
# Setter Classes
|
24
|
+
module Setter
|
25
|
+
autoload :Base, 'velcro/setter/base'
|
26
|
+
autoload :Mac, 'velcro/setter/mac'
|
27
|
+
autoload :Linux, 'velcro/setter/linux'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Status Classes
|
31
|
+
module Status
|
32
|
+
autoload :Machine, 'velcro/status/machine'
|
33
|
+
autoload :Dotfiles, 'velcro/status/dotfiles'
|
34
|
+
autoload :Git, 'velcro/status/git'
|
35
|
+
autoload :Ruby, 'velcro/status/ruby'
|
36
|
+
autoload :Symlinks, 'velcro/status/symlinks'
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.config
|
40
|
+
Velcro::Config.instance
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Velcro
|
2
|
+
# Parsing flag options passed in by the CLI
|
3
|
+
module Flags
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:attr_reader, :includes)
|
6
|
+
end
|
7
|
+
|
8
|
+
# rubocop:disable Metrics/AbcSize
|
9
|
+
def establish_inclusions(flags, options)
|
10
|
+
options = Hash[options.map{|k, v| [k.to_s, v] }]
|
11
|
+
inclusions = Hash[*flags.map { |k| [k, nil] }.flatten].merge(options).dup
|
12
|
+
|
13
|
+
if inclusions.values.compact.empty?
|
14
|
+
# If no options were specified include all options
|
15
|
+
inclusions.each{|k, _| inclusions[k] = true }
|
16
|
+
elsif inclusions.values.include?(true)
|
17
|
+
# If any options were specified as false, default the rest to true
|
18
|
+
inclusions.each{|k, _| inclusions[k] = false if inclusions[k].nil? }
|
19
|
+
else
|
20
|
+
# If options were specified, but not as false, default the rest to false
|
21
|
+
inclusions.each{|k, _| inclusions[k] = true if inclusions[k].nil? }
|
22
|
+
end
|
23
|
+
|
24
|
+
@includes = inclusions
|
25
|
+
end
|
26
|
+
# rubocop:enable Metrics/AbcSize
|
27
|
+
|
28
|
+
def included?(flag)
|
29
|
+
includes[flag.to_s]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Velcro
|
2
|
+
# Handle interactions with the shell
|
3
|
+
module Shell
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:attr_reader, :dryrun)
|
6
|
+
end
|
7
|
+
|
8
|
+
def shell(command)
|
9
|
+
dryrun? ? puts(command) : system(command)
|
10
|
+
end
|
11
|
+
|
12
|
+
def dryrun?
|
13
|
+
@dryrun == true
|
14
|
+
end
|
15
|
+
|
16
|
+
def dryrun!
|
17
|
+
@dryrun = true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Velcro
|
5
|
+
# Configuration settings for Velcro projects
|
6
|
+
class Config
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
@defaults = {
|
10
|
+
dotfiles: "#{Velcro.home}/.dotfiles",
|
11
|
+
repo_url: 'git@github.com:velcro/dotfiles'
|
12
|
+
}
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
setup
|
16
|
+
reset
|
17
|
+
end
|
18
|
+
|
19
|
+
def apply(config)
|
20
|
+
config.each_pair { |k, v| send("#{k}=", v) }
|
21
|
+
rescue NoMethodError => e
|
22
|
+
method = e.message.match(/`(.*)\=/)[1]
|
23
|
+
raise NoMethodError, "No configuration setting for :#{method} in #{default_options.join(', ')}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def reset
|
27
|
+
apply(defaults)
|
28
|
+
load_rc
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def load_rc
|
34
|
+
return unless File.exist?(rc_path)
|
35
|
+
apply(YAML.load_file(rc_path)['config'])
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup
|
39
|
+
defaults.each_pair{|k, _| self.class.send(:attr_accessor, k.to_sym) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def defaults
|
43
|
+
self.class.instance_variable_get(:"@defaults")
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_options
|
47
|
+
@default_options ||= defaults.keys.map{|k| ":#{k}" }
|
48
|
+
end
|
49
|
+
|
50
|
+
def rc_path
|
51
|
+
File.join(dotfiles, '.velcrorc')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Velcro
|
2
|
+
module Installer
|
3
|
+
# Parent class for velcro installers
|
4
|
+
class Base
|
5
|
+
attr_reader :dryrun
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@dryrun = options[:dryrun] || false
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.installer(options = {})
|
12
|
+
return Installer::Mac.new(options) if Velcro.osx?
|
13
|
+
return Installer::Linux.new(options) if Velcro.linux?
|
14
|
+
|
15
|
+
fail UnkownOperatingSystem, 'Velcro cannot recognize your OS'
|
16
|
+
end
|
17
|
+
|
18
|
+
def install(target)
|
19
|
+
package_manager = manager_name(target)
|
20
|
+
if package_manager.nil?
|
21
|
+
puts "Uknown install procedure for #{target}"
|
22
|
+
return
|
23
|
+
else
|
24
|
+
puts "Installing #{target} via #{package_manager}..."
|
25
|
+
end
|
26
|
+
|
27
|
+
return if dryrun
|
28
|
+
# Resolves to something like:
|
29
|
+
# self.brew_install("mysql")
|
30
|
+
send "#{package_manager}_install", target
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def manager_name(target)
|
36
|
+
return :velcro if respond_to?(target.to_sym, true)
|
37
|
+
return :brew if brew?(target)
|
38
|
+
return :cask if cask?(target)
|
39
|
+
end
|
40
|
+
|
41
|
+
def velcro_install(target)
|
42
|
+
send(target.to_sym)
|
43
|
+
end
|
44
|
+
|
45
|
+
def rvm
|
46
|
+
`gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3`
|
47
|
+
`curl -sSL https://get.rvm.io | bash -s stable`
|
48
|
+
`. #{Velco.home}/.rvm/scripts/rvm`
|
49
|
+
# `rvm install #{Velcro.config.ruby_version}`
|
50
|
+
end
|
51
|
+
|
52
|
+
def oh_my_zsh
|
53
|
+
`curl -L http://install.ohmyz.sh | sh`
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'json'
|
2
|
+
module Velcro
|
3
|
+
module Installer
|
4
|
+
# OSX Specific installations
|
5
|
+
class Mac < Installer::Base
|
6
|
+
private
|
7
|
+
|
8
|
+
def brew
|
9
|
+
`ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
|
10
|
+
`brew install caskroom/cask/brew-cask`
|
11
|
+
`brew tap phinze/homebrew-cask`
|
12
|
+
`brew install brew-cask`
|
13
|
+
`brew tap caskroom/versions`
|
14
|
+
`brew tap caskroom/fonts`
|
15
|
+
end
|
16
|
+
|
17
|
+
def brew_install(target)
|
18
|
+
puts 'Formula found via brew'
|
19
|
+
`brew install #{target}`
|
20
|
+
end
|
21
|
+
|
22
|
+
def cask_install(target)
|
23
|
+
puts 'Formula found via cask'
|
24
|
+
`brew cask install --appdir=/Applications #{target}`
|
25
|
+
end
|
26
|
+
|
27
|
+
def brew?(name)
|
28
|
+
begin
|
29
|
+
JSON.parse `brew info #{name} --json=v1`
|
30
|
+
rescue JSON::ParserError
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def cask?(name)
|
37
|
+
`brew cask info #{name}`.match(/No available Cask/).nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Velcro
|
4
|
+
# Class to build out the filesystem on the host machine
|
5
|
+
class Scaffold
|
6
|
+
attr_reader :dryrun
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@dryrun = options[:dryrun] || false
|
10
|
+
end
|
11
|
+
|
12
|
+
def install(config)
|
13
|
+
create_directories config['dirs']
|
14
|
+
generate_files config['files']
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def create_directories(dirs)
|
20
|
+
return if (dirs ||= []).empty?
|
21
|
+
|
22
|
+
puts "\nCreating directories:"
|
23
|
+
dirs.each do |dir|
|
24
|
+
path = "#{Velcro.home}/#{dir}"
|
25
|
+
dryrun ? puts("mkdir -p #{path}") : FileUtils.mkdir_p(path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate_files(files)
|
30
|
+
return if (files ||= []).empty?
|
31
|
+
|
32
|
+
puts "\nTouching Files:"
|
33
|
+
files.each do |file|
|
34
|
+
path = "#{Velcro.home}/#{file}"
|
35
|
+
dryrun ? puts("touch #{path}") : FileUtils.touch(path)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Velcro
|
2
|
+
module Setter
|
3
|
+
# Core logic for configuring the host system settings
|
4
|
+
class Base
|
5
|
+
attr_reader :dryrun
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@dryrun = options[:dryrun] || false
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.setter(options = {})
|
12
|
+
return Setter::Mac.new(options) if Velcro.osx?
|
13
|
+
return Setter::Linux.new(options) if Velcro.linux?
|
14
|
+
|
15
|
+
fail UnkownOperatingSystem, 'Velcro cannot recognize your OS'
|
16
|
+
end
|
17
|
+
|
18
|
+
def apply(setting)
|
19
|
+
method, args = setting, nil
|
20
|
+
|
21
|
+
if setting.is_a?(Hash)
|
22
|
+
method = setting.keys.first
|
23
|
+
args = setting.values.first
|
24
|
+
end
|
25
|
+
|
26
|
+
unless respond_to?(method.to_sym, true)
|
27
|
+
puts "Uknown procedure to apply setting: #{setting}"
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
send(method, args)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def apply_with_velcro(target)
|
37
|
+
send(target.to_sym)
|
38
|
+
end
|
39
|
+
|
40
|
+
def ssh(*_args)
|
41
|
+
if File.exist?("#{Velcro.home}/.ssh/id_rsa.pub")
|
42
|
+
puts 'id_rsa.pub exists. Skipping ssh keygen'
|
43
|
+
else
|
44
|
+
command = 'ssh-keygen'
|
45
|
+
dryrun ? puts(command) : system(command)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# rubocop:disable Metrics/AbcSize
|
50
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
51
|
+
# rubocop:disable Metrics/MethodLength
|
52
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
53
|
+
def git(*args)
|
54
|
+
options = args.first || {}
|
55
|
+
if options['name']
|
56
|
+
command = "git config --global user.name \"#{options['name']}\""
|
57
|
+
dryrun ? puts(command) : system(command)
|
58
|
+
end
|
59
|
+
|
60
|
+
if options['email']
|
61
|
+
command = "git config --global user.email \"#{options['email']}\""
|
62
|
+
dryrun ? puts(command) : system(command)
|
63
|
+
end
|
64
|
+
|
65
|
+
servers = [options['server'], options['servers']].flatten.compact
|
66
|
+
return unless servers.any?
|
67
|
+
|
68
|
+
servers.each do |server|
|
69
|
+
command = "cat ~/.ssh/id_rsa.pub | ssh #{server} \"mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys\""
|
70
|
+
dryrun ? puts(command) : system(command)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
# rubocop:enable Metrics/AbcSize
|
74
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
75
|
+
# rubocop:enable Metrics/MethodLength
|
76
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Velcro
|
4
|
+
module Setter
|
5
|
+
# Class that handles setting OSX settings
|
6
|
+
class Mac < Setter::Base
|
7
|
+
private
|
8
|
+
|
9
|
+
def git(*args)
|
10
|
+
super(*args)
|
11
|
+
|
12
|
+
options = args.first || {}
|
13
|
+
return unless options['editor']
|
14
|
+
|
15
|
+
command = "git config --global core.editor \"#{options['editor']}\""
|
16
|
+
dryrun ? puts(command) : system(command)
|
17
|
+
end
|
18
|
+
|
19
|
+
def keyboard_repeat(*args)
|
20
|
+
speed = args.first || 0
|
21
|
+
command = "defaults write NSGlobalDomain KeyRepeat -int #{speed}"
|
22
|
+
dryrun ? puts(command) : system(command)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Velcro
|
2
|
+
module Status
|
3
|
+
# Find the current status of your dotfiles directory
|
4
|
+
class Dotfiles
|
5
|
+
def self.print
|
6
|
+
printf '## Dotfiles - '
|
7
|
+
if installed?
|
8
|
+
puts 'Installed'
|
9
|
+
puts "=> #{Velcro.config.dotfiles}"
|
10
|
+
else
|
11
|
+
puts 'Not Installed'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.installed?
|
16
|
+
File.exist? Velcro.config.dotfiles
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Velcro
|
2
|
+
module Status
|
3
|
+
# Provide information about the git installation
|
4
|
+
class Git
|
5
|
+
def self.print
|
6
|
+
printf '## Git - '
|
7
|
+
if installed?
|
8
|
+
puts 'Installed'
|
9
|
+
puts `git --version`
|
10
|
+
else
|
11
|
+
puts 'Not Installed'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.installed?
|
16
|
+
(`which git` =~ /not found/).nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'velcro/concerns/flags'
|
2
|
+
|
3
|
+
module Velcro
|
4
|
+
module Status
|
5
|
+
# Provide information about all systems on the host
|
6
|
+
class Machine
|
7
|
+
include Velcro::Flags
|
8
|
+
|
9
|
+
FLAGS = %w(git dotfiles symlinks ruby).freeze
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
establish_inclusions(FLAGS, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def print
|
16
|
+
includes.select{|_, v| v }.each_pair do |key, _|
|
17
|
+
puts unless key == aspects.keys.first
|
18
|
+
"Velcro::Status::#{key.capitalize}".constantize.print
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Velcro
|
2
|
+
module Status
|
3
|
+
# Provide information about the ruby installation
|
4
|
+
class Ruby
|
5
|
+
def self.print
|
6
|
+
printf '## RVM - '
|
7
|
+
if !installed?
|
8
|
+
puts 'Not Installed'
|
9
|
+
elsif rubies.empty?
|
10
|
+
puts "Installed\n No Rubies Installed"
|
11
|
+
else
|
12
|
+
puts 'Installed'
|
13
|
+
rubies.each{|r| puts r }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.installed?
|
18
|
+
(`which rvm` =~ /not found/).nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def rubies
|
24
|
+
`rvm list`.split("\n").select{|str| str =~ /ruby-/}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Velcro
|
2
|
+
module Status
|
3
|
+
# Provide information about the symlinked dotfiles
|
4
|
+
class Symlinks
|
5
|
+
def self.print
|
6
|
+
linker = Velcro::Symlinker.new
|
7
|
+
symlinks = linker.symlinks
|
8
|
+
puts "## Symlinks - #{symlinks.length} symlink files:"
|
9
|
+
length = symlinks.group_by(&:size).max.last[0].length
|
10
|
+
|
11
|
+
linker.symlinks.each do |symlink|
|
12
|
+
state = linker.symlinked?(symlink) ? "~/.#{File.basename(symlink)}" : 'Unlinked!'
|
13
|
+
print_pair(length, symlink, state, '=>')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.installed?
|
18
|
+
linker = Velcro::Symlinker.new
|
19
|
+
linker.symlinks.select{|s| !linker.symlinked?(s) }.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.print_pair(length, first, second, delim = '')
|
23
|
+
printf "%-#{length}s #{delim} %s\n", first, second
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/velcro/strap.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'yaml'
|
3
|
+
require 'velcro/concerns/flags'
|
4
|
+
require 'velcro/concerns/shell'
|
5
|
+
|
6
|
+
module Velcro
|
7
|
+
# The main entry point for velcro
|
8
|
+
class Strap
|
9
|
+
include Velcro::Flags
|
10
|
+
include Velcro::Shell
|
11
|
+
|
12
|
+
attr_reader :rcfile
|
13
|
+
|
14
|
+
FLAGS = %w(apps host dotfiles symlinks scaffold settings).freeze
|
15
|
+
|
16
|
+
def initialize(repo, options = {})
|
17
|
+
establish_inclusions(FLAGS, options)
|
18
|
+
@dryrun = options[:dryrun] || false
|
19
|
+
|
20
|
+
fail ArgumentError if repo.nil? && included?(:dotfiles)
|
21
|
+
Velcro.config.repo_url = repo if repo
|
22
|
+
end
|
23
|
+
|
24
|
+
# rubocop:disable Metrics/AbcSize
|
25
|
+
def run
|
26
|
+
install_dotfiles
|
27
|
+
|
28
|
+
Symlinker.new(dryrun: dryrun?).symlink! if included?(:symlinks)
|
29
|
+
|
30
|
+
install_scaffold(rcfile)
|
31
|
+
install_apps(rcfile['apps'])
|
32
|
+
apply_settings(rcfile['settings'])
|
33
|
+
|
34
|
+
install_host if included?(:host)
|
35
|
+
end
|
36
|
+
# rubocop:enable Metrics/AbcSize
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def install_apps(apps)
|
41
|
+
return unless included?(:apps)
|
42
|
+
return if (apps ||= []).empty?
|
43
|
+
|
44
|
+
puts "\nInstalling apps:"
|
45
|
+
apps.each{|app| installer.install(app) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def apply_settings(settings)
|
49
|
+
return unless included?(:settings)
|
50
|
+
return if (settings ||= []).empty?
|
51
|
+
|
52
|
+
puts "\nApplying settings:"
|
53
|
+
settings.each{|setting| setter.apply(setting) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def install_scaffold(config)
|
57
|
+
return unless included?(:scaffold)
|
58
|
+
scaffolder.install(config)
|
59
|
+
end
|
60
|
+
|
61
|
+
def install_host
|
62
|
+
return unless host
|
63
|
+
|
64
|
+
puts "\nSetting up #{host['name']}:"
|
65
|
+
install_scaffold(host)
|
66
|
+
install_apps(host['apps'])
|
67
|
+
apply_settings(host['settings'])
|
68
|
+
end
|
69
|
+
|
70
|
+
def install_dotfiles
|
71
|
+
if included?(:dotfiles)
|
72
|
+
tmpdir = clone_dotfiles
|
73
|
+
@rcfile = load_rcfile(tmpdir)
|
74
|
+
|
75
|
+
shell("mv #{tmpdir} #{Velcro.config.dotfiles}")
|
76
|
+
puts "Dotfiles installed: #{Velcro.config.dotfiles}"
|
77
|
+
else
|
78
|
+
fail MissingDotfilesError unless Status::Dotfiles.installed?
|
79
|
+
@rcfile = load_rcfile(Velcro.config.dotfiles)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def clone_dotfiles
|
84
|
+
tmpdir = Dir.mktmpdir
|
85
|
+
shell("git clone -q #{Velcro.config.repo_url} #{tmpdir}")
|
86
|
+
tmpdir
|
87
|
+
end
|
88
|
+
|
89
|
+
def load_rcfile(dotfiles_dir)
|
90
|
+
file = YAML.load_file(File.join(dotfiles_dir, '.velcrorc'))
|
91
|
+
Velcro.config.apply file['config']
|
92
|
+
file
|
93
|
+
end
|
94
|
+
|
95
|
+
def installer
|
96
|
+
@installer ||= Installer::Base.installer(dryrun: dryrun)
|
97
|
+
end
|
98
|
+
|
99
|
+
def setter
|
100
|
+
@setter ||= Setter::Base.setter(dryrun: dryrun)
|
101
|
+
end
|
102
|
+
|
103
|
+
def scaffolder
|
104
|
+
@scaffolder ||= Scaffold.new(dryrun: dryrun)
|
105
|
+
end
|
106
|
+
|
107
|
+
def host
|
108
|
+
return @host if defined?(@host)
|
109
|
+
@host = rcfile['hosts'].detect{|n| n['name'] == Velcro.hostname }
|
110
|
+
puts "No host settings found for: #{Velcro.hostname}" if host.nil?
|
111
|
+
|
112
|
+
@host
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Velcro
|
2
|
+
# Symlink files from your dotfiles directory to $HOME
|
3
|
+
class Symlinker
|
4
|
+
attr_reader :dryrun, :force
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@dryrun = options[:dryrun]
|
8
|
+
@force = options[:force]
|
9
|
+
end
|
10
|
+
|
11
|
+
# In any subdirectory of your .dotfiles repo,
|
12
|
+
# create a file with the .symlink extension
|
13
|
+
# which will be stripped when copied to your
|
14
|
+
# home diretory with a "." prefix
|
15
|
+
#
|
16
|
+
# ex: ~/.dotfiles/irb/irbrc.symlink -> ~/.irbrc
|
17
|
+
def symlink!
|
18
|
+
symlinks.each do |symlink|
|
19
|
+
filename = File.basename(symlink, '.symlink')
|
20
|
+
target = File.join(Velcro.home, ".#{filename}")
|
21
|
+
next if skip?(target)
|
22
|
+
|
23
|
+
puts "Symlinking #{target}"
|
24
|
+
unless dryrun
|
25
|
+
FileUtils.rm_rf(target) if force
|
26
|
+
`ln -s "#{symlink}" "#{target}"`
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def symlinked?(symlink)
|
32
|
+
filename = File.basename(symlink, '.symlink')
|
33
|
+
target = File.join(Velcro.home, ".#{filename}")
|
34
|
+
File.exist?(target)
|
35
|
+
end
|
36
|
+
|
37
|
+
def skip?(target)
|
38
|
+
return false unless File.exist?(target)
|
39
|
+
|
40
|
+
if force
|
41
|
+
puts "#{target} exists. Forcing removal"
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
|
45
|
+
puts "#{target} exists. Skipping"
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def symlinks
|
50
|
+
@symlinks ||= Dir.glob File.join(Velcro.config.dotfiles, '/*/**{.symlink}')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Velcro
|
2
|
+
# Host machine helper for the Velcro class
|
3
|
+
module System
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:extend, self::ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Class methods for Velcro
|
9
|
+
module ClassMethods
|
10
|
+
def osx?
|
11
|
+
uname == 'Darwin'
|
12
|
+
end
|
13
|
+
|
14
|
+
def linux?
|
15
|
+
uname == 'Linux'
|
16
|
+
end
|
17
|
+
|
18
|
+
def home
|
19
|
+
ENV['HOME']
|
20
|
+
end
|
21
|
+
|
22
|
+
def ls(dir)
|
23
|
+
`ls -al #{dir}`.split("\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
def uname
|
27
|
+
`uname`.rstrip
|
28
|
+
end
|
29
|
+
|
30
|
+
def hostname
|
31
|
+
`hostname`.rstrip
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/velcro.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'velcro/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'velcro-strap'
|
8
|
+
spec.version = Velcro::VERSION
|
9
|
+
spec.authors = ['Matthew Werner']
|
10
|
+
spec.email = ['m@mjw.io']
|
11
|
+
|
12
|
+
spec.summary = 'Bootstraps are complicated'
|
13
|
+
spec.description = 'Bootstraps for dummies'
|
14
|
+
spec.homepage = ''
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = 'exe'
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_dependency 'thor'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
27
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
28
|
+
spec.add_development_dependency 'rspec'
|
29
|
+
spec.add_development_dependency 'rubocop'
|
30
|
+
spec.add_development_dependency 'simplecov'
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: velcro-strap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew Werner
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.10'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Bootstraps for dummies
|
98
|
+
email:
|
99
|
+
- m@mjw.io
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".rubocop.yml"
|
107
|
+
- ".travis.yml"
|
108
|
+
- CODE_OF_CONDUCT.md
|
109
|
+
- Gemfile
|
110
|
+
- LICENSE.txt
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- bin/console
|
114
|
+
- bin/setup
|
115
|
+
- bin/velcro
|
116
|
+
- lib/ext/string.rb
|
117
|
+
- lib/velcro.rb
|
118
|
+
- lib/velcro/concerns/flags.rb
|
119
|
+
- lib/velcro/concerns/shell.rb
|
120
|
+
- lib/velcro/config.rb
|
121
|
+
- lib/velcro/errors.rb
|
122
|
+
- lib/velcro/installer/base.rb
|
123
|
+
- lib/velcro/installer/linux.rb
|
124
|
+
- lib/velcro/installer/mac.rb
|
125
|
+
- lib/velcro/scaffold.rb
|
126
|
+
- lib/velcro/setter/base.rb
|
127
|
+
- lib/velcro/setter/linux.rb
|
128
|
+
- lib/velcro/setter/mac.rb
|
129
|
+
- lib/velcro/status/dotfiles.rb
|
130
|
+
- lib/velcro/status/git.rb
|
131
|
+
- lib/velcro/status/machine.rb
|
132
|
+
- lib/velcro/status/ruby.rb
|
133
|
+
- lib/velcro/status/symlinks.rb
|
134
|
+
- lib/velcro/strap.rb
|
135
|
+
- lib/velcro/symlinker.rb
|
136
|
+
- lib/velcro/system.rb
|
137
|
+
- lib/velcro/version.rb
|
138
|
+
- velcro.gemspec
|
139
|
+
homepage: ''
|
140
|
+
licenses:
|
141
|
+
- MIT
|
142
|
+
metadata: {}
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 2.4.8
|
160
|
+
signing_key:
|
161
|
+
specification_version: 4
|
162
|
+
summary: Bootstraps are complicated
|
163
|
+
test_files: []
|