mac_setup 0.7.2 → 0.8.0
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.
- checksums.yaml +4 -4
- data/exe/mac_setup +8 -9
- data/lib/mac_setup/configuration.rb +79 -9
- data/lib/mac_setup/git_repo_installer.rb +3 -3
- data/lib/mac_setup/homebrew_installer.rb +3 -9
- data/lib/mac_setup/homebrew_runner.rb +40 -0
- data/lib/mac_setup/plugin.rb +17 -0
- data/lib/mac_setup/plugins/keybase.rb +32 -0
- data/lib/mac_setup/plugins/mac_app_store.rb +75 -0
- data/lib/mac_setup/shell.rb +25 -19
- data/lib/mac_setup/version.rb +1 -1
- data/lib/mac_setup.rb +60 -36
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05b25fd9b18c84ceab8c35345f58607111782d0c
|
4
|
+
data.tar.gz: 3683dd0949e472f501f9624145ed97f695450f9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81bd2abe212ca77282c59023e5d1505f6e803715da8791ee94caa9f1046690b7469d152c0a96ef4f2111d177f01cbd5044cd0b712e2f7f5f684a54cb772a48ba
|
7
|
+
data.tar.gz: a61fad4936463e8d1e737feb2069f11209733847af307e638e80c9f85169f9376b9d65a9aa3ada6503baa0e5e2a528e143840f80e6787692b0b69d47520dbcfc
|
data/exe/mac_setup
CHANGED
@@ -2,22 +2,21 @@
|
|
2
2
|
|
3
3
|
require "mac_setup"
|
4
4
|
|
5
|
-
DEFAULT_CONFIG_PATH = "~/.dotfiles/mac_setup/config.yml"
|
6
|
-
|
7
5
|
command = ARGV.shift
|
8
6
|
options = ARGV.select { |arg| arg.start_with?("--") }
|
7
|
+
config_path = (ARGV - options).first || File.expand_path(DEFAULT_CONFIG_PATH)
|
9
8
|
|
10
9
|
case command
|
11
10
|
when "bootstrap"
|
12
|
-
MacSetup.bootstrap(ARGV
|
11
|
+
MacSetup.bootstrap(ARGV.take(2))
|
13
12
|
when "install"
|
14
|
-
config_path = (ARGV - options)[0] || File.expand_path(DEFAULT_CONFIG_PATH)
|
13
|
+
# config_path = (ARGV - options)[0] || File.expand_path(DEFAULT_CONFIG_PATH)
|
15
14
|
|
16
|
-
if File.exist?(config_path)
|
17
|
-
MacSetup.install(config_path, options)
|
18
|
-
else
|
19
|
-
|
20
|
-
end
|
15
|
+
# if File.exist?(config_path)
|
16
|
+
MacSetup.install # (config_path, options)
|
17
|
+
# else
|
18
|
+
# puts "You must specify a path to config file or create one at #{DEFAULT_CONFIG_PATH}"
|
19
|
+
# end
|
21
20
|
when "encrypt"
|
22
21
|
MacSetup.encrypt
|
23
22
|
else
|
@@ -1,36 +1,106 @@
|
|
1
1
|
require "yaml"
|
2
|
+
require "set"
|
2
3
|
|
3
4
|
module MacSetup
|
4
5
|
class Configuration
|
5
|
-
|
6
|
+
InvalidConfigError = Class.new(StandardError)
|
7
|
+
DEFAULT_KEYS = [:plugins, :git_repos, :symlinks, :brews, :fonts, :casks, :quicklook, :mas]
|
6
8
|
|
7
9
|
def initialize(config_path)
|
8
10
|
@config_path = config_path
|
9
11
|
load_config
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
|
14
|
+
def require_value(key)
|
15
|
+
value = @config.fetch(key.to_s) do
|
16
|
+
raise InvalidConfigError, "Missing config value for #{key}!"
|
17
|
+
end
|
18
|
+
|
19
|
+
define_singleton_method(key) { value }
|
20
|
+
allowed_keys << key.to_sym
|
14
21
|
end
|
15
22
|
|
16
|
-
def
|
17
|
-
|
23
|
+
def add(type, value)
|
24
|
+
add_method = "add_#{type}"
|
25
|
+
|
26
|
+
if respond_to?(add_method, include_private: true)
|
27
|
+
send(add_method, value)
|
28
|
+
else
|
29
|
+
collection = public_send(type)
|
30
|
+
|
31
|
+
case collection
|
32
|
+
when Set
|
33
|
+
collection << value.to_s
|
34
|
+
when Hash
|
35
|
+
collection.merge(value) do |key, oldval, newval|
|
36
|
+
raise InvalidConfigError, "#{key} is defined twice!: #{oldval}, #{newval}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
18
40
|
end
|
19
41
|
|
20
|
-
def
|
21
|
-
(@config["
|
42
|
+
def plugins
|
43
|
+
@plugins ||= Set.new(@config["plugins"])
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate!
|
47
|
+
extra_keys = @config.keys.map(&:to_i) - allowed_keys
|
48
|
+
|
49
|
+
return if extra_keys.none?
|
50
|
+
|
51
|
+
raise InvalidConfigError, "Extra keys in config: #{extra_keys.join(", ")}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def dotfiles_repo
|
55
|
+
@config.fetch("repo")
|
22
56
|
end
|
23
57
|
|
24
58
|
def git_repos
|
25
|
-
|
59
|
+
@git_repos ||= @config["git_repos"] || {}
|
26
60
|
end
|
27
61
|
|
28
62
|
def symlinks
|
29
|
-
|
63
|
+
@symlinks ||= @config["symlinks"] || {}
|
64
|
+
end
|
65
|
+
|
66
|
+
def brews
|
67
|
+
@brews ||= (@config["brews"] || []).reduce({}) do |merged, item|
|
68
|
+
add_brews(item, merged)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def fonts
|
73
|
+
@fonts ||= Set.new(@config["fonts"])
|
74
|
+
end
|
75
|
+
|
76
|
+
def casks
|
77
|
+
@casks ||= Set.new(@config["casks"])
|
78
|
+
end
|
79
|
+
|
80
|
+
def quicklook
|
81
|
+
@quicklook ||= Set.new(@config["quicklook"])
|
82
|
+
end
|
83
|
+
|
84
|
+
def mas
|
85
|
+
@mas ||= @config["mas"] || {}
|
30
86
|
end
|
31
87
|
|
32
88
|
private
|
33
89
|
|
90
|
+
def add_brews(item, existing_brews = brews)
|
91
|
+
existing_brews.merge(brew_value(item)) do |key, oldval, newval|
|
92
|
+
raise InvalidConfigError, "#{key} is defined twice!: #{oldval}, #{newval}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def brew_value(item)
|
97
|
+
item.is_a?(Hash) ? item : { item.to_s => {} }
|
98
|
+
end
|
99
|
+
|
100
|
+
def allowed_keys
|
101
|
+
@allowed_keys ||= Set.new(DEFAULT_KEYS)
|
102
|
+
end
|
103
|
+
|
34
104
|
def load_config
|
35
105
|
@config = YAML.load_file(@config_path)
|
36
106
|
end
|
@@ -16,8 +16,8 @@ module MacSetup
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.install_repo(repo, install_path,
|
20
|
-
new(repo, install_path, tracking_key:
|
19
|
+
def self.install_repo(repo, install_path, track: nil, status: nil)
|
20
|
+
new(repo, install_path, tracking_key: track, status: status).install_or_update
|
21
21
|
end
|
22
22
|
|
23
23
|
def initialize(repo, install_path, tracking_key: nil, status: nil)
|
@@ -44,7 +44,7 @@ module MacSetup
|
|
44
44
|
|
45
45
|
def update
|
46
46
|
unless can_update?
|
47
|
-
|
47
|
+
MacSetup.log "Can't update. Unstaged changes in #{install_path}"
|
48
48
|
return
|
49
49
|
end
|
50
50
|
|
@@ -5,19 +5,13 @@ module MacSetup
|
|
5
5
|
BREW_INSTALL_URL = "https://raw.githubusercontent.com/Homebrew/install/master/install"
|
6
6
|
|
7
7
|
def self.run
|
8
|
-
if
|
8
|
+
if Shell.command_present?("brew")
|
9
|
+
MacSetup.log "Homebrew already installed. Skipping..."
|
10
|
+
else
|
9
11
|
MacSetup.log "Installing Homebrew" do
|
10
12
|
Shell.run(%{/usr/bin/ruby -e "$(curl -fsSL #{BREW_INSTALL_URL})"})
|
11
13
|
end
|
12
|
-
else
|
13
|
-
MacSetup.log "Homebrew already installed. Updating" do
|
14
|
-
Shell.run("brew update")
|
15
|
-
end
|
16
14
|
end
|
17
15
|
end
|
18
|
-
|
19
|
-
def self.homebrew_missing?
|
20
|
-
Shell.run("which brew").empty?
|
21
|
-
end
|
22
16
|
end
|
23
17
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module MacSetup
|
2
|
+
class HomebrewRunner
|
3
|
+
def self.run(config, _status)
|
4
|
+
brewfile = build_brewfile(config)
|
5
|
+
|
6
|
+
cmd = [
|
7
|
+
"echo << EOF | brew bundle install --file=-",
|
8
|
+
brewfile,
|
9
|
+
"EOF"
|
10
|
+
]
|
11
|
+
|
12
|
+
Shell.run(cmd.join("\n"))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.install_cask(cask)
|
16
|
+
Shell.run("brew cask install #{cask}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.build_brewfile(config)
|
20
|
+
brews = config.brews.map do |name, opts|
|
21
|
+
[%(brew "#{name}"), print_args(opts)].compact.join(", ")
|
22
|
+
end
|
23
|
+
|
24
|
+
casks = (config.fonts + config.casks + config.quicklook).map do |name|
|
25
|
+
"cask #{name}"
|
26
|
+
end
|
27
|
+
|
28
|
+
(brews + casks).join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.print_args(opts)
|
32
|
+
args = opts["args"]
|
33
|
+
|
34
|
+
return unless args
|
35
|
+
|
36
|
+
args_str = args.sort.map { |arg| %("#{arg}") }.join(", ")
|
37
|
+
"args: [#{args_str}]"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MacSetup
|
2
|
+
module Plugins
|
3
|
+
class Keybase < MacSetup::Plugin
|
4
|
+
def self.bootstrap(config)
|
5
|
+
add_requirements(config)
|
6
|
+
install
|
7
|
+
login(config.keybase)
|
8
|
+
install_volume
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.add_requirements(config)
|
12
|
+
config.require_value(:keybase)
|
13
|
+
config.add(:casks, :keybase)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def self.install
|
19
|
+
HomebrewRunner.install_cask(:keybase)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.login(username)
|
23
|
+
Shell.run("keybase login #{username}")
|
24
|
+
end
|
25
|
+
|
26
|
+
# TODO: Investigate making this work with kext permissions
|
27
|
+
def self.install_volume
|
28
|
+
Shell.run("keybase install --components=helper,fuse,mountdir,kbfs")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module MacSetup
|
2
|
+
module Plugins
|
3
|
+
class MacAppStore < MacSetup::Plugin
|
4
|
+
attr_reader :config, :status
|
5
|
+
|
6
|
+
def self.add_requirements(config)
|
7
|
+
config.add(:brews, :mas)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.get_status(status)
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.run(config, status)
|
15
|
+
new(config, status).run
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(config, status)
|
19
|
+
@config = config
|
20
|
+
@status = status
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
set_up_mas
|
25
|
+
install_brewfile
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def set_up_mas
|
31
|
+
return unless brewfile.read =~ /^mas /
|
32
|
+
|
33
|
+
install_mas
|
34
|
+
sign_in_to_mas
|
35
|
+
end
|
36
|
+
|
37
|
+
def install_mas
|
38
|
+
MacSetup.log "Installing mas" do
|
39
|
+
Shell.run("brew install mas")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def sign_in_to_mas
|
44
|
+
if mas_signed_in?
|
45
|
+
MacSetup.log "Already signed into Mac App Store. Skipping."
|
46
|
+
else
|
47
|
+
apple_id = Shell.ask("What is your Apple ID?")
|
48
|
+
Shell.run("mas signin --dialog #{apple_id}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def mas_signed_in?
|
53
|
+
Shell.success?("mas account")
|
54
|
+
end
|
55
|
+
|
56
|
+
def install_brewfile
|
57
|
+
MacSetup.log "Installing Brewfile" do
|
58
|
+
Shell.run("brew bundle --global")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def mas_installed?
|
63
|
+
Shell.command_present?("mas")
|
64
|
+
end
|
65
|
+
|
66
|
+
def bundle_already_tapped?
|
67
|
+
status.installed_taps.include?(BUNDLE_TAP)
|
68
|
+
end
|
69
|
+
|
70
|
+
def brewfile
|
71
|
+
@brewfile ||= Pathname.new("~/.Brewfile").expand_path
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/mac_setup/shell.rb
CHANGED
@@ -3,29 +3,35 @@ require "io/console"
|
|
3
3
|
|
4
4
|
module MacSetup
|
5
5
|
class Shell
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
class << self
|
7
|
+
def run(command)
|
8
|
+
`#{sanitize_command(command)}`
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def ask(question)
|
12
|
+
puts question
|
13
|
+
gets.strip
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def password
|
17
|
+
puts "Enter Password"
|
18
|
+
STDIN.noecho(&:gets).strip
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
def success?(command)
|
22
|
+
system(sanitize_command(command))
|
23
|
+
end
|
24
|
+
|
25
|
+
def command_present?(command)
|
26
|
+
success?("command -v #{command} >/dev/null 2>&1")
|
27
|
+
end
|
23
28
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
def sanitize_command(command)
|
30
|
+
if command.respond_to?(:each)
|
31
|
+
Shellwords.join(command)
|
32
|
+
else
|
33
|
+
command
|
34
|
+
end
|
29
35
|
end
|
30
36
|
end
|
31
37
|
end
|
data/lib/mac_setup/version.rb
CHANGED
data/lib/mac_setup.rb
CHANGED
@@ -1,58 +1,82 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
1
3
|
require "mac_setup/version"
|
2
4
|
require "mac_setup/configuration"
|
3
5
|
require "mac_setup/system_status"
|
6
|
+
require "mac_setup/shell"
|
7
|
+
require "mac_setup/homebrew_runner"
|
4
8
|
require "mac_setup/secrets"
|
5
|
-
require "mac_setup/command_line_tools_installer"
|
6
9
|
require "mac_setup/homebrew_installer"
|
7
10
|
require "mac_setup/git_repo_installer"
|
8
|
-
require "mac_setup/
|
9
|
-
require "mac_setup/
|
10
|
-
require "mac_setup/
|
11
|
-
require "mac_setup/services_installer"
|
12
|
-
require "mac_setup/secrets_installer"
|
11
|
+
require "mac_setup/plugin"
|
12
|
+
require "mac_setup/plugins/keybase"
|
13
|
+
require "mac_setup/plugins/mac_app_store"
|
13
14
|
|
14
15
|
module MacSetup
|
15
|
-
|
16
|
+
DEFAULT_DOTFILES_PATH = File.expand_path("~/.dotfiles")
|
17
|
+
DEFAULT_CONFIG_PATH = File.join(DEFAULT_DOTFILES_PATH, "mac_setup/config.yml")
|
16
18
|
|
17
19
|
INSTALLERS = [
|
18
20
|
GitRepoInstaller,
|
19
|
-
SecretsInstaller,
|
20
21
|
SymlinkInstaller,
|
21
|
-
|
22
|
-
ServicesInstaller,
|
23
|
-
ScriptInstaller
|
22
|
+
HomebrewRunner
|
24
23
|
]
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
DEFAULT_PLUGINS = [
|
26
|
+
Plugins::MacAppStore,
|
27
|
+
Plugins::Keybase
|
28
|
+
]
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
class << self
|
31
|
+
def bootstrap(dotfiles_repo)
|
32
|
+
GitRepoInstaller.install_repo(dotfiles_repo, dotfiles_path)
|
33
|
+
HomebrewInstaller.run
|
34
34
|
|
35
|
-
|
36
|
-
CommandLineToolsInstaller.run
|
37
|
-
GitRepoInstaller.install_repo(dotfiles_repo, DOTFILES_PATH)
|
38
|
-
HomebrewInstaller.run
|
39
|
-
end
|
35
|
+
config = Configuration.new(DEFAULT_CONFIG_PATH)
|
40
36
|
|
41
|
-
|
42
|
-
|
43
|
-
end
|
37
|
+
plugins(config).each { |plugin| plugin.bootstrap(config) }
|
38
|
+
end
|
44
39
|
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
def install # (config_path, _options)
|
41
|
+
config = Configuration.new(DEFAULT_CONFIG_PATH)
|
42
|
+
|
43
|
+
GitRepoInstaller.install_repo(config.dotfiles_repo, dotfiles_path)
|
44
|
+
|
45
|
+
config = Configuration.new(DEFAULT_CONFIG_PATH)
|
46
|
+
plugins(config).each { |plugin| plugin.add_requirements(config) }
|
47
|
+
config.validate!
|
48
|
+
status = SystemStatus.new
|
49
|
+
|
50
|
+
INSTALLERS.each { |installer| installer.run(config, status) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def encrypt
|
54
|
+
Secrets.encrypt(dotfiles_path)
|
55
|
+
end
|
56
|
+
|
57
|
+
def shorten_path(path)
|
58
|
+
path.sub(/#{ENV['HOME']}/, "~")
|
59
|
+
end
|
60
|
+
|
61
|
+
def log(message)
|
62
|
+
if block_given?
|
63
|
+
print "#{message}..."
|
64
|
+
yield
|
65
|
+
puts "Ok."
|
66
|
+
else
|
67
|
+
puts message
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def dotfiles_path
|
72
|
+
DEFAULT_DOTFILES_PATH
|
73
|
+
end
|
74
|
+
|
75
|
+
# private
|
48
76
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
yield
|
53
|
-
puts "Ok."
|
54
|
-
else
|
55
|
-
puts message
|
77
|
+
def plugins(config)
|
78
|
+
DEFAULT_PLUGINS + config.plugins.map { |plugin_name| Plugin.load(plugin_name) }
|
79
|
+
# @plugins ||= (DEFAULT_PLUGINS + config.plugins).map { |plugin_name| Plugin.load(plugin) }
|
56
80
|
end
|
57
81
|
end
|
58
82
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mac_setup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Wean
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,6 +108,10 @@ files:
|
|
108
108
|
- lib/mac_setup/configuration.rb
|
109
109
|
- lib/mac_setup/git_repo_installer.rb
|
110
110
|
- lib/mac_setup/homebrew_installer.rb
|
111
|
+
- lib/mac_setup/homebrew_runner.rb
|
112
|
+
- lib/mac_setup/plugin.rb
|
113
|
+
- lib/mac_setup/plugins/keybase.rb
|
114
|
+
- lib/mac_setup/plugins/mac_app_store.rb
|
111
115
|
- lib/mac_setup/script_installer.rb
|
112
116
|
- lib/mac_setup/secrets.rb
|
113
117
|
- lib/mac_setup/secrets_installer.rb
|