dotman-bin 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0e297c042d8398cb7b9602acae6f11a8caebab8687319e365326580ec1caaa50
4
+ data.tar.gz: c73c57f74294fe4e63e5ab5904f68e8e5ba79016d896ed9432a1ae77bfbca37a
5
+ SHA512:
6
+ metadata.gz: 45e98e9c493425fa1369eeaf3a67e6e322e97bb9a0c99c2de94a1435fcced7da42f4fb4eda4ad180915cf8ba96ad3cbdcaff42f05534731625012281cc24f878
7
+ data.tar.gz: a7e54d5d57993014b7065192565acd16e499c67cce3e8ebf96b3bb106ab00ee0c0b62e7a7778c6ce6aa4971421a05071a378ebcc2b2775d49b805f2bb72389c4
data/bin/dotman ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/dotman'
4
+ include Dotman
5
+
6
+ class Main
7
+ DOTFILE = 'Dotfile'
8
+
9
+ def self.run(opts)
10
+ unless File.exist?(DOTFILE)
11
+ puts 'Dotfile not found'.red
12
+ exit 1
13
+ end
14
+
15
+ class << Dotfile
16
+ load DOTFILE
17
+ end
18
+
19
+ env = {
20
+ base: File.expand_path(opts['--base']),
21
+ home: File.expand_path(opts['--home'])
22
+ }
23
+
24
+ puts Dotfile.to_script(env)
25
+ end
26
+ end
27
+
28
+ docs = <<~EOF
29
+ Usage:
30
+ dotman [options] build
31
+
32
+ Options:
33
+ --base=BASE Dir from where symlinks should be sourced [default: ~/.dotfiles/files]
34
+ --home=HOME Dir where symlinks should be placed [default: ~]
35
+ EOF
36
+
37
+ begin
38
+ opts = Docopt::docopt(docs)
39
+ rescue Docopt::Exit => e
40
+ puts e.message
41
+ exit 1
42
+ end
43
+
44
+ Main.run(opts)
@@ -0,0 +1,29 @@
1
+ module Dotman::Action
2
+ class Init
3
+ def to_statement
4
+ Shell.statement(init, die)
5
+ end
6
+
7
+ private
8
+
9
+ def check_host
10
+ Shell.comparison('$HOST', '=', '')
11
+ end
12
+
13
+ def check_base
14
+ Shell.comparison('$BASE_DIR', '=', '')
15
+ end
16
+
17
+ def init
18
+ Shell.condition([check_host, check_base], :or)
19
+ end
20
+
21
+ def die
22
+ Shell.block([
23
+ Shell.echo(:red, 'One or more core environment variables is missing; cannot continue.'),
24
+ Shell.exit(1)
25
+ ])
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ module Dotman::Action
2
+ class Link
3
+ def initialize(from, to)
4
+ @from, @to = from, to
5
+ end
6
+
7
+ def to_statement
8
+ Shell.statement(does_not_exist, create_link, check_link)
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :from, :to
14
+
15
+ def pair
16
+ [from, to]
17
+ end
18
+
19
+ def check_link
20
+ Shell.statement(link_is_set_up, link_set_up, link_not_set_up)
21
+ end
22
+
23
+ def does_not_exist
24
+ Shell.comparison('$HOME_DIR/' + to, '! -e')
25
+ end
26
+
27
+ def create_link
28
+ Shell.block([
29
+ Shell.command('ln -s "$BASE_DIR/%s" "$HOME_DIR/%s"' % pair),
30
+ Shell.echo(:yellow, 'Link $BASE_DIR/%s → $HOME_DIR/%s created' % pair),
31
+ ])
32
+ end
33
+
34
+ def link_is_set_up
35
+ Shell.comparison('$(realpath $HOME_DIR/%s)' % to, '=', '$BASE_DIR/' + from)
36
+ end
37
+
38
+ def link_set_up
39
+ Shell.echo(:green, 'Link $BASE_DIR/%s → $HOME_DIR/%s looking good' % pair)
40
+ end
41
+
42
+ def link_not_set_up
43
+ Shell.echo(:red, 'Link $BASE_DIR/%s → $HOME_DIR/%s is not set up' % pair)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,33 @@
1
+ module Dotman::Check
2
+ class Host
3
+ def initialize(aliases, hosts, include: true)
4
+ @aliases, @hosts, @include = aliases, hosts, include
5
+ end
6
+
7
+ def to_comparison
8
+ Shell.condition(hosts.map { |host| compare(host) }, condition_operator)
9
+ end
10
+
11
+ private
12
+
13
+ def condition_operator
14
+ if @include then :or else :and end
15
+ end
16
+
17
+ def comparison_operator
18
+ if @include then '=' else '!=' end
19
+ end
20
+
21
+ def compare(host)
22
+ Shell.comparison('$HOST', comparison_operator, host)
23
+ end
24
+
25
+ def hosts
26
+ @hosts.map { |host| get_alias(host) }
27
+ end
28
+
29
+ def get_alias(target)
30
+ @aliases[target] || target
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ module Dotman
2
+ class Dotfile
3
+ def self.configure
4
+ config = DotfileConfiguration.new
5
+ @@config = config
6
+ yield config
7
+ end
8
+
9
+ def self.to_script(env)
10
+ @@config.to_script(env)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,59 @@
1
+ module Dotman
2
+ class DotfileConfiguration
3
+ def initialize
4
+ @actions, @host_aliases = [], {}
5
+ end
6
+
7
+ def link(from, to: nil, **args)
8
+ add_action Action::Link.new(from, to), args
9
+ end
10
+
11
+ def to_script(env)
12
+ [header(env), actions, footer].join
13
+ end
14
+
15
+ def alias_host(from, to)
16
+ @host_aliases[from] = to
17
+ end
18
+
19
+ private
20
+
21
+ def add_action(action, args)
22
+ @actions << Shell::Statement.new(satisfies_args(args), action.to_statement)
23
+ end
24
+
25
+ def satisfies_args(args)
26
+ Shell.satisfies_args(@host_aliases, args)
27
+ end
28
+
29
+ def actions
30
+ actions_list.map(&:to_s).join("\n\n").strip
31
+ end
32
+
33
+ def actions_list
34
+ [Action::Init.new.to_statement, *@actions]
35
+ end
36
+
37
+ def header(env)
38
+ return <<~EOF
39
+ #!/bin/bash
40
+ set -e
41
+
42
+ HOST="$(hostname -s)"
43
+ BASE_DIR="#{env[:base]}"
44
+ HOME_DIR="#{env[:home]}"
45
+
46
+ echo HOST="#{'$HOST'.bold}"
47
+ echo BASE_DIR="#{'$BASE_DIR'.bold}"
48
+ echo HOME_DIR="#{'$HOME_DIR'.bold}"
49
+
50
+ echo "#{['Starting...'].shelljoin.green}"
51
+
52
+ EOF
53
+ end
54
+
55
+ def footer
56
+ "\n\n" + 'echo "%s"' % 'Finished.'.green
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,11 @@
1
+ module Dotman::Shell
2
+ class Block
3
+ def initialize(commands)
4
+ @commands = commands
5
+ end
6
+
7
+ def to_s(level = 0)
8
+ @commands.map { |command| command.to_s(level) }.join("\n")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Dotman::Shell
2
+ class Command
3
+ def initialize(str)
4
+ @str = str
5
+ end
6
+
7
+ def to_s(level = 0)
8
+ (' ' * (level * 4)) + @str
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Dotman::Shell
2
+ class Comparison
3
+ def initialize(operand1, operator, operand2 = nil)
4
+ @operand1, @operator, @operand2 = operand1, operator, operand2
5
+ end
6
+
7
+ def to_s
8
+ if @operand2.nil?
9
+ '[ %s "%s" ]' % [@operator, @operand1]
10
+ else
11
+ '[ "%s" %s "%s" ]' % [ @operand1, @operator, @operand2 ]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module Dotman::Shell
2
+ class Condition
3
+ def initialize(conditions, operator = :and)
4
+ conditions = [conditions] unless conditions.is_a?(Array)
5
+ @operator = operator
6
+ @conditions = conditions.compact
7
+ end
8
+
9
+ def to_s
10
+ '( %s )' % @conditions.join(' ' + operator + ' ')
11
+ end
12
+
13
+ private
14
+
15
+ def operator
16
+ @operator == :and ? '&&' : '||'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ module Dotman::Shell
2
+ class Statement
3
+ def initialize(condition, true_statement, false_statement = nil)
4
+ @condition = condition
5
+ @true_statement = true_statement
6
+ @false_statement = false_statement
7
+ end
8
+
9
+ def to_s(level = 0)
10
+ if @condition.nil?
11
+ return @true_statement.to_s(level)
12
+ end
13
+
14
+ indent = Shell.indent(level)
15
+
16
+ s = indent + "if %s; then\n" % @condition
17
+ s << "%s\n" % @true_statement.to_s(level + 1)
18
+
19
+ if @false_statement
20
+ s << indent + "else\n"
21
+ s << "%s\n" % @false_statement.to_s(level + 1)
22
+ end
23
+
24
+ s << indent + 'fi'
25
+ s
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,43 @@
1
+ module Dotman
2
+ module Shell
3
+ def self.satisfies_args(aliases, only: [], except: [])
4
+ if only.length > 0
5
+ Check::Host.new(aliases, only, include: true).to_comparison
6
+ elsif except.length > 0
7
+ Check::Host.new(aliases, except, include: false).to_comparison
8
+ end
9
+ end
10
+
11
+ def self.echo(colour, msg)
12
+ command('echo "%s"' % msg.send(colour))
13
+ end
14
+
15
+ def self.exit(code)
16
+ command('exit ' + code.to_s)
17
+ end
18
+
19
+ def self.indent(level)
20
+ ' ' * (level * 4)
21
+ end
22
+
23
+ def self.block(*args)
24
+ Block.new(*args)
25
+ end
26
+
27
+ def self.command(*args)
28
+ Command.new(*args)
29
+ end
30
+
31
+ def self.comparison(*args)
32
+ Comparison.new(*args)
33
+ end
34
+
35
+ def self.condition(*args)
36
+ Condition.new(*args)
37
+ end
38
+
39
+ def self.statement(*args)
40
+ Statement.new(*args)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ module Dotman
2
+ VERSION = "1.0.0"
3
+ end
data/lib/dotman.rb ADDED
@@ -0,0 +1,13 @@
1
+ Dir.chdir __dir__ do
2
+ require 'bundler/setup'
3
+ require 'require_all'
4
+ require 'colorize'
5
+ require 'docopt'
6
+
7
+ require 'shellwords'
8
+ require 'ostruct'
9
+ require 'socket'
10
+ end
11
+
12
+ module Dotman; end
13
+ require_rel 'dotman'
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dotman-bin
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - crdx
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-09-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: require_all
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.8.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: docopt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.6.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.6.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.17.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.17.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '12.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '12.3'
97
+ description:
98
+ email:
99
+ executables:
100
+ - dotman
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - bin/dotman
105
+ - lib/dotman.rb
106
+ - lib/dotman/actions/init.rb
107
+ - lib/dotman/actions/link.rb
108
+ - lib/dotman/checks/host.rb
109
+ - lib/dotman/dotfile.rb
110
+ - lib/dotman/dotfile_configuration.rb
111
+ - lib/dotman/shell.rb
112
+ - lib/dotman/shell/block.rb
113
+ - lib/dotman/shell/command.rb
114
+ - lib/dotman/shell/comparison.rb
115
+ - lib/dotman/shell/condition.rb
116
+ - lib/dotman/shell/statement.rb
117
+ - lib/dotman/version.rb
118
+ homepage: https://github.com/crdx/dotman
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubygems_version: 3.0.6
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Run many commands dotman with a colourful overview
141
+ test_files: []