takelage 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/LICENSE +674 -0
- data/README.md +159 -0
- data/bin/tau +5 -0
- data/lib/Thorfile +1 -0
- data/lib/takelage/bit/cli.rb +18 -0
- data/lib/takelage/bit/clipboard/cli.rb +68 -0
- data/lib/takelage/bit/clipboard/module.rb +174 -0
- data/lib/takelage/bit/scope/cli.rb +58 -0
- data/lib/takelage/bit/scope/module.rb +81 -0
- data/lib/takelage/completion/cli.rb +21 -0
- data/lib/takelage/default.yml +30 -0
- data/lib/takelage/docker/cli.rb +16 -0
- data/lib/takelage/docker/container/check/cli.rb +40 -0
- data/lib/takelage/docker/container/check/module.rb +44 -0
- data/lib/takelage/docker/container/cli.rb +127 -0
- data/lib/takelage/docker/container/module.rb +168 -0
- data/lib/takelage/docker/image/cli.rb +41 -0
- data/lib/takelage/docker/image/module.rb +33 -0
- data/lib/takelage/docker/image/tag/check/cli.rb +47 -0
- data/lib/takelage/docker/image/tag/check/module.rb +56 -0
- data/lib/takelage/docker/image/tag/cli.rb +16 -0
- data/lib/takelage/docker/image/tag/latest/cli.rb +49 -0
- data/lib/takelage/docker/image/tag/latest/module.rb +31 -0
- data/lib/takelage/docker/image/tag/list/cli.rb +46 -0
- data/lib/takelage/docker/image/tag/list/module.rb +44 -0
- data/lib/takelage/docker/socket/cli.rb +61 -0
- data/lib/takelage/docker/socket/module.rb +137 -0
- data/lib/takelage/git/check/cli.rb +46 -0
- data/lib/takelage/git/check/module.rb +64 -0
- data/lib/takelage/git/cli.rb +10 -0
- data/lib/takelage/info/cli.rb +10 -0
- data/lib/takelage/info/project/cli.rb +47 -0
- data/lib/takelage/lib/config.rb +80 -0
- data/lib/takelage/lib/logging.rb +30 -0
- data/lib/takelage/lib/project.rb +57 -0
- data/lib/takelage/lib/subcmd.rb +13 -0
- data/lib/takelage/lib/system.rb +107 -0
- data/lib/takelage/self/cli.rb +40 -0
- data/lib/takelage/self/config/cli.rb +70 -0
- data/lib/takelage/self/module.rb +26 -0
- data/lib/takelage/version +1 -0
- data/lib/takelage.rb +198 -0
- metadata +185 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
# takelage docker image tag list module
|
2
|
+
module DockerImageTagListModule
|
3
|
+
|
4
|
+
# Backend method for docker image tag list local.
|
5
|
+
# @return [Array] local docker image tags
|
6
|
+
def docker_image_tag_list_local
|
7
|
+
tags = []
|
8
|
+
|
9
|
+
cmd_docker_images = 'docker images'
|
10
|
+
images = run cmd_docker_images
|
11
|
+
|
12
|
+
images.scan(/.*#{@docker_repo}\/#{@docker_image}.*/) do |line|
|
13
|
+
tags << line.split(/\s+/)[1]
|
14
|
+
end
|
15
|
+
|
16
|
+
tags.sort_by(&Gem::Version.method(:new))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Backend method for docker image tag list remote.
|
20
|
+
# @return [Array] remote docker image tags
|
21
|
+
def docker_image_tag_list_remote
|
22
|
+
log.debug "Getting docker remote tags from \"#{@docker_tagsurl}\""
|
23
|
+
|
24
|
+
begin
|
25
|
+
@res = Net::HTTP.get_response URI(@docker_tagsurl)
|
26
|
+
unless @res.code.eql? '200'
|
27
|
+
log.error "Unable to connect to \"#{@docker_tagsurl}\""
|
28
|
+
return
|
29
|
+
end
|
30
|
+
rescue SocketError => e
|
31
|
+
log.debug e
|
32
|
+
exit false
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
tags = JSON.parse @res.body
|
37
|
+
rescue JSON::ParserError
|
38
|
+
log.error 'Unable to parse JSON'
|
39
|
+
exit false
|
40
|
+
end
|
41
|
+
|
42
|
+
tags['tags'].sort_by(&Gem::Version.method(:new))
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Takelage
|
2
|
+
|
3
|
+
# takelage docker socket
|
4
|
+
class DockerSocket < SubCommandBase
|
5
|
+
|
6
|
+
include LoggingModule
|
7
|
+
include ConfigModule
|
8
|
+
include SystemModule
|
9
|
+
include DockerSocketModule
|
10
|
+
|
11
|
+
# Initialize docker socket
|
12
|
+
def initialize(args = [], local_options = {}, configuration = {})
|
13
|
+
|
14
|
+
# initialize thor parent class
|
15
|
+
super args, local_options, configuration
|
16
|
+
|
17
|
+
@sockets = {
|
18
|
+
:'agent-socket' => {
|
19
|
+
:path => nil,
|
20
|
+
:host => '127.0.0.1',
|
21
|
+
:port => config.active['docker_socket_agent_port']},
|
22
|
+
:'agent-ssh-socket' => {
|
23
|
+
:path => nil,
|
24
|
+
:host => '127.0.0.1',
|
25
|
+
:port => config.active['docker_socket_agent_ssh_port']},
|
26
|
+
:'agent-extra-socket' => {
|
27
|
+
:path => nil,
|
28
|
+
:host => '127.0.0.1',
|
29
|
+
:port => config.active['docker_socket_agent_extra_port']},
|
30
|
+
:'agent-browser-socket' => {
|
31
|
+
:path => nil,
|
32
|
+
:host => '127.0.0.1',
|
33
|
+
:port => config.active['docker_socket_agent_browser_port']}}
|
34
|
+
_get_socket_paths
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# docker socket start
|
39
|
+
#
|
40
|
+
desc 'start', 'Start sockets for docker container'
|
41
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
42
|
+
Start sockets for docker container
|
43
|
+
LONGDESC
|
44
|
+
# Start sockets for docker container.
|
45
|
+
def start
|
46
|
+
docker_socket_start
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# docker socket stop
|
51
|
+
#
|
52
|
+
desc 'stop', 'Stop sockets for docker container'
|
53
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
54
|
+
Stop sockets for docker container
|
55
|
+
LONGDESC
|
56
|
+
# Stop sockets for docker container.
|
57
|
+
def stop
|
58
|
+
docker_socket_stop
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# takelage docker socket module
|
2
|
+
module DockerSocketModule
|
3
|
+
|
4
|
+
# Backend method for docker socket start.
|
5
|
+
def docker_socket_start
|
6
|
+
log.debug 'Starting sockets for docker container'
|
7
|
+
|
8
|
+
cmds_start_socket = _get_socket_start_commands sockets_up = false
|
9
|
+
|
10
|
+
unless cmds_start_socket.empty?
|
11
|
+
log.debug 'Request sudo so that subsequent background tasks run without delay'
|
12
|
+
|
13
|
+
cmd_sudo_true = 'sudo true'
|
14
|
+
|
15
|
+
run cmd_sudo_true
|
16
|
+
end
|
17
|
+
|
18
|
+
cmds_start_socket.each do |cmd_start_socket|
|
19
|
+
run_and_fork cmd_start_socket
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Backend method for docker socket stop.
|
24
|
+
def docker_socket_stop
|
25
|
+
log.debug 'Stopping sockets for docker container'
|
26
|
+
|
27
|
+
cmd_ps = config.active['docker_socket_ps']
|
28
|
+
|
29
|
+
# get process list
|
30
|
+
# assuming format: "pid command"
|
31
|
+
stdout_str, stderr_str, status = run_and_check cmd_ps
|
32
|
+
|
33
|
+
cmds_start_socket = _get_socket_start_commands sockets_up = true
|
34
|
+
|
35
|
+
# loop over process list
|
36
|
+
stdout_str.split(/\n+/).each do |process|
|
37
|
+
|
38
|
+
# split processes in process id and process command
|
39
|
+
pid_command = process.strip.split(/ /, 2)
|
40
|
+
pid = pid_command[0]
|
41
|
+
command = pid_command[1]
|
42
|
+
|
43
|
+
# loop over socket start commands
|
44
|
+
cmds_start_socket.each do |cmd_start_socket|
|
45
|
+
|
46
|
+
if command == cmd_start_socket
|
47
|
+
log.debug "Killing PID #{pid}"
|
48
|
+
|
49
|
+
cmd_kill = config.active['docker_socket_kill'] % {pid: pid}
|
50
|
+
|
51
|
+
run cmd_kill
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# get socket start commands
|
58
|
+
# sockets_up is a boolean which defines if the sockets need to be up
|
59
|
+
# to be included in the resulting array of socket start commands
|
60
|
+
def _get_socket_start_commands sockets_up
|
61
|
+
cmds_start_socket = []
|
62
|
+
|
63
|
+
# loop over sockets
|
64
|
+
@sockets.each do |socket, socket_config|
|
65
|
+
cmd_start_socket = config.active['docker_socket_start'] % {
|
66
|
+
host: socket_config[:host],
|
67
|
+
port: socket_config[:port],
|
68
|
+
path: socket_config[:path],
|
69
|
+
}
|
70
|
+
|
71
|
+
if sockets_up
|
72
|
+
if _socket_up? socket, socket_config
|
73
|
+
cmds_start_socket << cmd_start_socket
|
74
|
+
end
|
75
|
+
else
|
76
|
+
unless _socket_up? socket, socket_config
|
77
|
+
cmds_start_socket << cmd_start_socket
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
cmds_start_socket
|
83
|
+
end
|
84
|
+
|
85
|
+
# get socket paths
|
86
|
+
def _get_socket_paths
|
87
|
+
cmd_gpgconf_listdirs = config.active['docker_socket_gpgconf']
|
88
|
+
stdout_str, stderr_str, status = run_and_check cmd_gpgconf_listdirs
|
89
|
+
|
90
|
+
stdout_str.split(/\n+/).each do |gpg_path|
|
91
|
+
@sockets.each do |socket, socket_config|
|
92
|
+
gpg_socket = gpg_path.split(':')
|
93
|
+
if gpg_socket[0] == socket.to_s
|
94
|
+
@sockets[socket][:path] = gpg_socket[1]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# check if a socket is available
|
101
|
+
# but trying to connect to it via TCP
|
102
|
+
def _socket_up? socket, socket_config
|
103
|
+
host = socket_config[:host]
|
104
|
+
port = socket_config[:port]
|
105
|
+
path = socket_config[:path]
|
106
|
+
|
107
|
+
error_message = "failed to connect to " +
|
108
|
+
"socket \"#{socket}\" " +
|
109
|
+
"using host \"#{host}\", " +
|
110
|
+
"port \"#{port}\", " +
|
111
|
+
"path \"#{path}\""
|
112
|
+
|
113
|
+
# check if socket is available
|
114
|
+
begin
|
115
|
+
Timeout::timeout(1) do
|
116
|
+
begin
|
117
|
+
s = TCPSocket.new host, port
|
118
|
+
s.close
|
119
|
+
log.debug "Socket \"#{socket}\" available"
|
120
|
+
return true
|
121
|
+
rescue Errno::ECONNREFUSED
|
122
|
+
log.debug "Connection refused: #{error_message}"
|
123
|
+
return false
|
124
|
+
rescue Errno::EHOSTUNREACH
|
125
|
+
log.debug "Host unreachable: #{error_message}"
|
126
|
+
return false
|
127
|
+
rescue SocketError
|
128
|
+
log.debug "Socket error: #{error_message}"
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
rescue Timeout::Error
|
133
|
+
log.debug "Timeout: #{error_message}"
|
134
|
+
return false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Takelage
|
2
|
+
|
3
|
+
# takelage docker container check
|
4
|
+
class GitCheck < SubCommandBase
|
5
|
+
|
6
|
+
include LoggingModule
|
7
|
+
include SystemModule
|
8
|
+
include GitCheckModule
|
9
|
+
|
10
|
+
#
|
11
|
+
# git check clean
|
12
|
+
#
|
13
|
+
desc 'clean', 'Check if the git workspace is clean'
|
14
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
15
|
+
Check if the git workspace is clean
|
16
|
+
LONGDESC
|
17
|
+
# Check if the git workspace is clean.
|
18
|
+
def clean
|
19
|
+
exit git_check_clean
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# git check master
|
24
|
+
#
|
25
|
+
desc 'master', 'Check if we are on the git master branch'
|
26
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
27
|
+
Check if we are on the git master branch
|
28
|
+
LONGDESC
|
29
|
+
# Check if we are on the git master branch.
|
30
|
+
def master
|
31
|
+
exit git_check_master
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# git check workspace
|
36
|
+
#
|
37
|
+
desc 'workspace', 'Check if a git workspace exists'
|
38
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
39
|
+
Check if a git workspace exists
|
40
|
+
LONGDESC
|
41
|
+
# Check if a git workspace exists.
|
42
|
+
def workspace
|
43
|
+
exit git_check_workspace
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# takelage git check module
|
2
|
+
module GitCheckModule
|
3
|
+
|
4
|
+
# Backend method for git check clean.
|
5
|
+
# @return [Boolean] is git workspace clean?
|
6
|
+
def git_check_clean
|
7
|
+
log.debug "Checking if git workspace is clean"
|
8
|
+
|
9
|
+
return false unless git_check_workspace
|
10
|
+
|
11
|
+
cmd_git_unstaged = 'git diff --exit-code'
|
12
|
+
cmd_git_uncommitted = 'git diff --cached --exit-code'
|
13
|
+
cmd_git_status = 'git status --porcelain'
|
14
|
+
|
15
|
+
stdout_str, stderr_str, status_unstaged = run_and_check cmd_git_unstaged
|
16
|
+
stdout_str, stderr_str, status_uncommitted = run_and_check cmd_git_uncommitted
|
17
|
+
stdout_str_status, stderr_str, status = run_and_check cmd_git_status
|
18
|
+
|
19
|
+
# only return true if neither unstaged nor uncommitted nor empty files
|
20
|
+
sum = status_unstaged.exitstatus +
|
21
|
+
status_uncommitted.exitstatus +
|
22
|
+
stdout_str_status.length
|
23
|
+
|
24
|
+
sum.zero?
|
25
|
+
end
|
26
|
+
|
27
|
+
# Backend method for git check master.
|
28
|
+
# @return [Boolean] are we on the git master branch?
|
29
|
+
def git_check_master
|
30
|
+
log.debug 'Check if we are on the git master branch'
|
31
|
+
|
32
|
+
return false unless git_check_workspace
|
33
|
+
|
34
|
+
cmd_get_branch = 'git symbolic-ref HEAD'
|
35
|
+
stdout_str, stderr_str, status = run_and_check cmd_get_branch
|
36
|
+
|
37
|
+
branch = stdout_str.strip.split('/')[-1]
|
38
|
+
|
39
|
+
log.debug "We are on git branch \"#{branch}\""
|
40
|
+
|
41
|
+
branch == 'master'
|
42
|
+
end
|
43
|
+
|
44
|
+
# Backend method for git check workspace.
|
45
|
+
# @return [Boolean] is this a git workspace?
|
46
|
+
def git_check_workspace
|
47
|
+
log.debug 'Check if this is a git workspace'
|
48
|
+
|
49
|
+
cmd_check_git_repo = 'git -C . rev-parse'
|
50
|
+
stdout_str_repo, stderr_str_repo, status_repo = run_and_check cmd_check_git_repo
|
51
|
+
|
52
|
+
cmd_pwd = 'pwd'
|
53
|
+
stdout_str_dir, stderr_str_dir, status_dir = run_and_check cmd_pwd
|
54
|
+
|
55
|
+
dir = stdout_str_dir.strip
|
56
|
+
|
57
|
+
unless status_repo.exitstatus.zero?
|
58
|
+
log.debug "No git workspace found in \"#{dir}\""
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
|
62
|
+
true
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Takelage
|
2
|
+
|
3
|
+
# takelage info project
|
4
|
+
class InfoProject < SubCommandBase
|
5
|
+
|
6
|
+
include LoggingModule
|
7
|
+
include SystemModule
|
8
|
+
include ConfigModule
|
9
|
+
include ProjectModule
|
10
|
+
|
11
|
+
#
|
12
|
+
# info project active
|
13
|
+
#
|
14
|
+
desc 'active', 'Print active project info'
|
15
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
16
|
+
Print active project info
|
17
|
+
LONGDESC
|
18
|
+
# Print active project info.
|
19
|
+
def active
|
20
|
+
say hash_to_yaml(project.active)
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# info project private
|
25
|
+
#
|
26
|
+
desc 'private', 'Print private project info'
|
27
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
28
|
+
Print private project info
|
29
|
+
LONGDESC
|
30
|
+
# Print private project info.
|
31
|
+
def private
|
32
|
+
say hash_to_yaml(project.private)
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# info project main
|
37
|
+
#
|
38
|
+
desc 'main', 'Print main project info'
|
39
|
+
long_desc <<-LONGDESC.gsub("\n", "\x5")
|
40
|
+
Print main project info
|
41
|
+
LONGDESC
|
42
|
+
# Print main project info.
|
43
|
+
def main
|
44
|
+
say hash_to_yaml(project.main)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# takelage config module
|
2
|
+
module ConfigModule
|
3
|
+
|
4
|
+
# takelage config class.
|
5
|
+
class TakelageConfig
|
6
|
+
|
7
|
+
include LoggingModule
|
8
|
+
include SystemModule
|
9
|
+
|
10
|
+
attr_accessor :active, :default, :home, :project
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@active = Hash.new
|
14
|
+
@default = Hash.new
|
15
|
+
@home = Hash.new
|
16
|
+
@project = Hash.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Global singleton config
|
21
|
+
@@config = TakelageConfig.new
|
22
|
+
|
23
|
+
# Initialze config
|
24
|
+
def initialize_config
|
25
|
+
log.debug "takelage version: #{Takelage::VERSION}"
|
26
|
+
log.debug "Current working directory: #{Dir.pwd}"
|
27
|
+
|
28
|
+
# read default config file in lib
|
29
|
+
default_file = "#{File.dirname(__FILE__)}/../default.yml"
|
30
|
+
default_file = File.expand_path default_file
|
31
|
+
if File.exist? default_file
|
32
|
+
@@config.default = read_yaml_file(default_file) || Hash.new
|
33
|
+
@@config.default = @@config.default.sort.to_h
|
34
|
+
end
|
35
|
+
|
36
|
+
# read custom config file in $HOME
|
37
|
+
home_file = "#{Dir.home}/.takelage.yml"
|
38
|
+
if File.exist? home_file
|
39
|
+
@@config.home = read_yaml_file(home_file) || Hash.new
|
40
|
+
@@config.home = @@config.home.sort.to_h
|
41
|
+
end
|
42
|
+
|
43
|
+
# read custom config file next to Rakefile
|
44
|
+
file, path = Rake.application.find_rakefile_location
|
45
|
+
if path
|
46
|
+
project_file = "#{path}/takelage.yml"
|
47
|
+
@@config.project = read_yaml_file(project_file) || Hash.new
|
48
|
+
@@config.project = @@config.project.sort.to_h
|
49
|
+
end
|
50
|
+
|
51
|
+
# make a clone or else we'll change the original hash
|
52
|
+
default = @@config.default.clone
|
53
|
+
home = @@config.home.clone
|
54
|
+
project = @@config.project.clone
|
55
|
+
|
56
|
+
# merge default and home and project to active
|
57
|
+
# project wins against home wins against default
|
58
|
+
project_over_home = home.merge!(project)
|
59
|
+
|
60
|
+
@@config.active = default.merge!(project_over_home)
|
61
|
+
@@config.active = @@config.active.sort.to_h
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Object] global singleton config
|
65
|
+
def config
|
66
|
+
@@config
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Boolean] check if config keys are configured
|
70
|
+
def configured?(config_keys)
|
71
|
+
@configured = true
|
72
|
+
config_keys.each do |config_key|
|
73
|
+
unless @@config.active.key? config_key
|
74
|
+
log.error "Please configure \"#{config_key}\""
|
75
|
+
@configured = false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
@configured
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# takelage logging module
|
2
|
+
module LoggingModule
|
3
|
+
|
4
|
+
# Global singleton logger
|
5
|
+
@@log = Logger.new(STDOUT)
|
6
|
+
|
7
|
+
# Initialize logger with loglevel.
|
8
|
+
def initialize_logging(loglevel)
|
9
|
+
|
10
|
+
# logger: format
|
11
|
+
log.formatter = proc do |severity, datetime, progname, msg|
|
12
|
+
"[#{severity}] #{msg}\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
# logger: level
|
16
|
+
if %w(FATAL ERROR WARN INFO DEBUG).include? loglevel
|
17
|
+
log.level = loglevel
|
18
|
+
log.debug "Using loglevel #{loglevel}"
|
19
|
+
else
|
20
|
+
log.level = Logger::INFO
|
21
|
+
log.error 'The parameter "loglevel" must be one of FATAL, ERROR, WARN, INFO, DEBUG'
|
22
|
+
log.info 'Using loglevel INFO'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Object] global singleton logger
|
27
|
+
def log
|
28
|
+
@@log
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# takelage project module
|
2
|
+
module ProjectModule
|
3
|
+
|
4
|
+
# takelage config class.
|
5
|
+
class TakelageProject
|
6
|
+
|
7
|
+
include LoggingModule
|
8
|
+
include SystemModule
|
9
|
+
include ConfigModule
|
10
|
+
|
11
|
+
attr_accessor :active, :private, :main
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@active = Hash.new
|
15
|
+
@private = Hash.new
|
16
|
+
@main = Hash.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Global singleton config
|
21
|
+
@@project = TakelageProject.new
|
22
|
+
|
23
|
+
# Initialze project
|
24
|
+
def initialize_project
|
25
|
+
|
26
|
+
rakefile, path = Rake.application.find_rakefile_location
|
27
|
+
|
28
|
+
main_file = "#{path}/#{@@project.config.active['info_project_main']}"
|
29
|
+
private_file = "#{path}/#{@@project.config.active['info_project_private']}"
|
30
|
+
|
31
|
+
# read main project info
|
32
|
+
if File.exist? main_file
|
33
|
+
@@project.main = read_yaml_file(main_file) || Hash.new
|
34
|
+
@@project.main = @@project.main.sort.to_h
|
35
|
+
end
|
36
|
+
|
37
|
+
# read private project info
|
38
|
+
if File.exist? private_file
|
39
|
+
@@project.private = read_yaml_file(private_file) || Hash.new
|
40
|
+
@@project.private = @@project.private.sort.to_h
|
41
|
+
end
|
42
|
+
|
43
|
+
# make a clone or else we'll change the original hash
|
44
|
+
main = @@project.main.clone
|
45
|
+
private = @@project.private.clone
|
46
|
+
|
47
|
+
# merge main and private to active
|
48
|
+
# private wins against main
|
49
|
+
@@project.active = main.merge!(private)
|
50
|
+
@@project.active = @@project.active.sort.to_h
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Object] global singleton project
|
54
|
+
def project
|
55
|
+
@@project
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Thor with subcommands that work correctly with help
|
2
|
+
class SubCommandBase < Thor
|
3
|
+
|
4
|
+
# Set the subcommand banner
|
5
|
+
def self.banner(command, namespace = nil, subcommand = false)
|
6
|
+
"#{basename} #{subcommand_prefix} #{command.usage}"
|
7
|
+
end
|
8
|
+
|
9
|
+
# Set the subcommand prefix
|
10
|
+
def self.subcommand_prefix
|
11
|
+
self.name.gsub(%r{.*::}, '').gsub(%r{^[A-Z]}) { |match| match[0].downcase }.gsub(%r{[A-Z]}) { |match| " #{match[0].downcase}" }
|
12
|
+
end
|
13
|
+
end
|