geordi 1.8.0 → 1.9.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/Gemfile.lock +1 -1
- data/README.md +32 -0
- data/features/cucumber.feature +2 -2
- data/lib/geordi/commands/db_clean.rb +60 -0
- data/lib/geordi/commands/delete_dumps.rb +46 -0
- data/lib/geordi/db_cleaner.rb +239 -0
- data/lib/geordi/interaction.rb +11 -0
- data/lib/geordi/util.rb +32 -0
- data/lib/geordi/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70f9242df556d6b8259f341827cc8996f6970de1e9d51c5ff13cbc44307a7ee7
|
4
|
+
data.tar.gz: 59e54eca6438f61af0c7640f88771e5f7f67008237445a0d25521b3adea4f0fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d143f1c68d472cc9918d6de6d2271b6633d0f9f01182d835b9667d872d65c495cc85b6c2752545e670b4bc685367baeb7122a32b7e4d3265ea8cc6412629be5d
|
7
|
+
data.tar.gz: ec93583e23658f4c1c69febc903f8d3d05c98b6e0e7ec7066c4c678277161fcc9d4e8f365e79e38792ee0c7a5b8bb9deec07408983c50c694a3884be254d2124
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -75,6 +75,18 @@ to use an `=` instead of a space to separate parameter name and value,
|
|
75
75
|
e.g. `--format=pretty`.
|
76
76
|
|
77
77
|
|
78
|
+
### geordi delete_dumps [DIRECTORY]
|
79
|
+
|
80
|
+
Delete database dump files (`*.dump`).
|
81
|
+
|
82
|
+
Example: `geordi delete_dumps` or `geordy delete_dumps ~/tmp/dumps`
|
83
|
+
|
84
|
+
Recursively search for files ending in `*.dump` and offer to delete those. When
|
85
|
+
no argument is given, two default directories are searched for dump files: the
|
86
|
+
current working directory and `~/dumps` (for dumps created with geordi).
|
87
|
+
|
88
|
+
Geordi will ask for confirmation before actually deleting files.
|
89
|
+
|
78
90
|
### `geordi deploy [STAGE]`
|
79
91
|
|
80
92
|
Guided deployment across branches.
|
@@ -105,6 +117,26 @@ instead of `cap deploy:migrations`. You can force using `deploy` by passing the
|
|
105
117
|
-M option: `geordi deploy -M staging`.
|
106
118
|
|
107
119
|
|
120
|
+
### `geordi drop_databases`
|
121
|
+
|
122
|
+
Delete local MySQL/MariaDB and Postgres databases that are not whitelisted.
|
123
|
+
|
124
|
+
Example: `geordi drop_databases`
|
125
|
+
|
126
|
+
Check both MySQL/MariaDB and Postgres on the machine running geordi for databases
|
127
|
+
and offer to delete them. Excluded are databases that are whitelisted. This comes
|
128
|
+
in handy when you're keeping your currently active projects in the whitelist files
|
129
|
+
and perform regular housekeeping with Geordi.
|
130
|
+
|
131
|
+
When called with `-P` or `-M` options, only handles Postgres resp. MySQL/MariaDB.
|
132
|
+
|
133
|
+
When called with `--postgres <port or local socket>` or `--mysql <port or local socket>`,
|
134
|
+
will instruct the underlying management commands to use those connection methods
|
135
|
+
instead of the defaults. This is useful when running multiple installations.
|
136
|
+
|
137
|
+
Geordi will ask for confirmation before actually dropping databases and will
|
138
|
+
offer to edit the whitelist instead.
|
139
|
+
|
108
140
|
### `geordi dump [TARGET]`
|
109
141
|
|
110
142
|
Handle dumps (see `geordi help dump` for details).
|
data/features/cucumber.feature
CHANGED
@@ -97,7 +97,7 @@ Feature: The cucumber command
|
|
97
97
|
|
98
98
|
When I run `geordi cucumber --verbose features`
|
99
99
|
Then the output should contain "# Running features"
|
100
|
-
And the output should match /^> .*cucumber .*--tags ~@solo/
|
100
|
+
And the output should match /^> .*cucumber .*--tags \"~@solo\"/
|
101
101
|
And the output should contain "# Running @solo features"
|
102
102
|
And the output should match /^> .*cucumber .*--tags @solo/
|
103
103
|
|
@@ -122,7 +122,7 @@ Feature: The cucumber command
|
|
122
122
|
|
123
123
|
When I run `geordi cucumber features/no_solo --verbose`
|
124
124
|
Then the output should contain "# Running features"
|
125
|
-
And the output should match /^> .*cucumber .*--tags ~@solo/
|
125
|
+
And the output should match /^> .*cucumber .*--tags \"~@solo\"/
|
126
126
|
But the output should not contain "# Running @solo features"
|
127
127
|
|
128
128
|
|
@@ -0,0 +1,60 @@
|
|
1
|
+
desc 'drop-databases', 'Delete local non-whitelisted databases'
|
2
|
+
long_desc <<-LONGDESC
|
3
|
+
|
4
|
+
Delete local MySQL/MariaDB and Postgres databases that are not whitelisted.
|
5
|
+
|
6
|
+
Example: `geordi drop_databases`
|
7
|
+
|
8
|
+
Check both MySQL/MariaDB and Postgres on the machine running geordi for databases
|
9
|
+
and offer to delete them. Excluded are databases that are whitelisted. This comes
|
10
|
+
in handy when you're keeping your currently active projects in the whitelist files
|
11
|
+
and perform regular housekeeping with Geordi.
|
12
|
+
|
13
|
+
When called with `-P` or `-M` options, only handles Postgres resp. MySQL/MariaDB.
|
14
|
+
|
15
|
+
When called with `--postgres <port or local socket>` or `--mysql <port or local socket>`,
|
16
|
+
will instruct the underlying management commands to use those connection methods
|
17
|
+
instead of the defaults. This is useful when running multiple installations.
|
18
|
+
LONGDESC
|
19
|
+
|
20
|
+
option :postgres_only, :aliases => '-P', :type => :boolean,
|
21
|
+
:desc => 'Only clean Postgres', :default => false
|
22
|
+
option :mysql_only, :aliases => '-M', :type => :boolean,
|
23
|
+
:desc => 'Only clean MySQL/MariaDB', :default => false
|
24
|
+
option :postgres, :banner => 'PORT_OR_SOCKET',
|
25
|
+
:desc => 'Use Postgres port or socket'
|
26
|
+
option :mysql, :banner => 'PORT_OR_SOCKET',
|
27
|
+
:desc => 'Use MySQL/MariaDB port or socket'
|
28
|
+
|
29
|
+
def drop_databases
|
30
|
+
require 'geordi/db_cleaner'
|
31
|
+
fail '-P and -M are mutually exclusive' if options.postgres_only and options.mysql_only
|
32
|
+
mysql_flags = nil
|
33
|
+
postgres_flags = nil
|
34
|
+
|
35
|
+
unless options.mysql.nil?
|
36
|
+
begin
|
37
|
+
mysql_port = Integer(options.mysql)
|
38
|
+
mysql_flags = "--port=#{mysql_port} --protocol=TCP"
|
39
|
+
rescue AttributeError
|
40
|
+
unless File.exist? options.mysql
|
41
|
+
fail "Path #{options.mysql} is not a valid MySQL socket"
|
42
|
+
end
|
43
|
+
mysql_flags = "--socket=#{options.mysql}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
unless options.postgres.nil?
|
48
|
+
postgres_flags = "--port=#{options.postgres}"
|
49
|
+
end
|
50
|
+
|
51
|
+
extra_flags = {'mysql' => mysql_flags,
|
52
|
+
'postgres' => postgres_flags
|
53
|
+
}
|
54
|
+
cleaner = DBCleaner.new(extra_flags)
|
55
|
+
cleaner.clean_mysql unless options.postgres_only
|
56
|
+
cleaner.clean_postgres unless options.mysql_only
|
57
|
+
|
58
|
+
success 'Done.'
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
desc 'delete_dumps [DIRECTORY]', 'delete database dump files (*.dump)'
|
2
|
+
long_desc <<-LONGDESC
|
3
|
+
Delete database dump files (`*.dump`).
|
4
|
+
|
5
|
+
Example: `geordi delete_dumps` or `geordy delete_dumps ~/tmp/dumps`
|
6
|
+
|
7
|
+
Recursively search for files ending in `*.dump` and offer to delete those. When
|
8
|
+
no argument is given, two default directories are searched for dump files: the
|
9
|
+
current working directory and `~/dumps` (for dumps created with geordi).
|
10
|
+
|
11
|
+
Geordi will ask for confirmation before actually deleting files.
|
12
|
+
|
13
|
+
LONGDESC
|
14
|
+
|
15
|
+
def delete_dumps(dump_directory = nil)
|
16
|
+
deletable_dumps = []
|
17
|
+
if dump_directory.nil?
|
18
|
+
dump_directories = [
|
19
|
+
File.join(Dir.home, 'dumps'),
|
20
|
+
Dir.pwd
|
21
|
+
]
|
22
|
+
else
|
23
|
+
dump_directories = [dump_directory]
|
24
|
+
end
|
25
|
+
announce 'Looking for *.dump in ' << dump_directories.join(',')
|
26
|
+
dump_directories.each do |d|
|
27
|
+
d2 = File.expand_path(d)
|
28
|
+
unless File.directory? File.realdirpath(d2)
|
29
|
+
warn "Directory #{d2} does not exist"
|
30
|
+
next
|
31
|
+
end
|
32
|
+
deletable_dumps.concat(Dir.glob("#{d2}/**/*.dump"))
|
33
|
+
end
|
34
|
+
if deletable_dumps.empty?
|
35
|
+
success 'No dumps to delete' if deletable_dumps.empty?
|
36
|
+
exit 0
|
37
|
+
end
|
38
|
+
deletable_dumps.uniq!
|
39
|
+
note 'The following dumps can be deleted:'
|
40
|
+
puts
|
41
|
+
puts deletable_dumps
|
42
|
+
prompt 'Delete those dumps', 'n', /y|yes/ or fail 'Cancelled.'
|
43
|
+
deletable_dumps.each do |dump|
|
44
|
+
File.delete dump unless File.directory? dump
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'open3'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
module Geordi
|
6
|
+
class DBCleaner
|
7
|
+
include Geordi::Interaction
|
8
|
+
|
9
|
+
def initialize(extra_flags)
|
10
|
+
puts 'Please enter your sudo password if asked, for db operations as system users'
|
11
|
+
puts "We're going to run `sudo -u postgres psql` for PostgreSQL"
|
12
|
+
puts ' and `sudo mysql` for MariaDB (which uses PAM auth)'
|
13
|
+
`sudo true`
|
14
|
+
fail 'sudo access is required for database operations as database users' if $? != 0
|
15
|
+
@derivative_dbname = /_(test\d?|development|cucumber)$/
|
16
|
+
base_directory = ENV['XDG_CONFIG_HOME']
|
17
|
+
base_directory = "#{Dir.home}" if base_directory.nil?
|
18
|
+
@whitelist_directory = File.join(base_directory, '.config', 'geordi', 'whitelists')
|
19
|
+
FileUtils.mkdir_p(@whitelist_directory) unless File.directory? @whitelist_directory
|
20
|
+
@mysql_command = decide_mysql_command(extra_flags['mysql'])
|
21
|
+
@postgres_command = decide_postgres_command(extra_flags['postgres'])
|
22
|
+
end
|
23
|
+
|
24
|
+
def edit_whitelist(dbtype)
|
25
|
+
whitelist = whitelist_fname(dbtype)
|
26
|
+
if File.exist? whitelist
|
27
|
+
whitelisted_dbs = Geordi::Util.stripped_lines(File.read(whitelist))\
|
28
|
+
.delete_if { |l| l.start_with? '#' }
|
29
|
+
else
|
30
|
+
whitelisted_dbs = Array.new
|
31
|
+
end
|
32
|
+
all_dbs = list_all_dbs(dbtype)
|
33
|
+
tmp = Tempfile.open("geordi_whitelist_#{dbtype}")
|
34
|
+
tmp.write <<-HEREDOC
|
35
|
+
# Put each whitelisted database on a new line.
|
36
|
+
# System databases will never be deleted.
|
37
|
+
# When you whitelist foo, foo_development and foo_test\\d? are whitelisted, too.
|
38
|
+
# This works even if foo does not exist. Also, you will only see foo in this list.
|
39
|
+
#
|
40
|
+
# Syntax: keep foo
|
41
|
+
# drop bar
|
42
|
+
HEREDOC
|
43
|
+
tmpfile_content = Array.new
|
44
|
+
all_dbs.each do |db|
|
45
|
+
next if is_whitelisted?(dbtype, db)
|
46
|
+
next if is_protected?(dbtype, db)
|
47
|
+
db.sub!(@derivative_dbname, '')
|
48
|
+
tmpfile_content.push(['drop', db])
|
49
|
+
end
|
50
|
+
whitelisted_dbs.each do |db|
|
51
|
+
tmpfile_content.push(['keep', db])
|
52
|
+
end
|
53
|
+
tmpfile_content.sort_by! { |k| k[1] }
|
54
|
+
tmpfile_content.uniq!
|
55
|
+
tmpfile_content.each do |line|
|
56
|
+
tmp.write("#{line[0]} #{line[1]}\n")
|
57
|
+
end
|
58
|
+
tmp.close
|
59
|
+
texteditor = Geordi::Util.decide_texteditor
|
60
|
+
system("#{texteditor} #{tmp.path}")
|
61
|
+
File.open(tmp.path, 'r') do |wl_edited|
|
62
|
+
whitelisted_dbs = Array.new
|
63
|
+
whitelist_storage = File.open(whitelist, 'w')
|
64
|
+
lines = Geordi::Util.stripped_lines(wl_edited.read)
|
65
|
+
lines.each do |line|
|
66
|
+
next if line.start_with?('#')
|
67
|
+
fail 'Invalid edit to whitelist file' unless line.split.length == 2
|
68
|
+
fail 'Invalid edit to whitelist file' unless %w[keep drop k d].include? line.split[0]
|
69
|
+
db_status, db_name = line.split
|
70
|
+
if db_status == 'keep'
|
71
|
+
whitelisted_dbs.push db_name
|
72
|
+
whitelist_storage.write(db_name << "\n")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
whitelist_storage.close
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def decide_mysql_command(extra_flags)
|
80
|
+
cmd = 'sudo mysql'
|
81
|
+
unless extra_flags.nil?
|
82
|
+
if extra_flags.include? 'port'
|
83
|
+
port = Integer(extra_flags.split('=')[1].split()[0])
|
84
|
+
fail "Port #{port} is not open" unless Geordi::Util.is_port_open? port
|
85
|
+
end
|
86
|
+
cmd << " #{extra_flags}"
|
87
|
+
end
|
88
|
+
Open3.popen3("#{cmd} -e 'QUIT'") do |stdin, stdout, stderr, thread|
|
89
|
+
break if thread.value.exitstatus == 0
|
90
|
+
# sudo mysql was not successful, switching to mysql-internal user management
|
91
|
+
mysql_error = stderr.read.lines[0].chomp.strip.split[1]
|
92
|
+
if %w[1045 1698].include? mysql_error # authentication failed
|
93
|
+
cmd = 'mysql -uroot'
|
94
|
+
cmd << " #{extra_flags}" unless extra_flags.nil?
|
95
|
+
unless File.exist? File.join(Dir.home, '.my.cnf')
|
96
|
+
puts "Please enter your MySQL/MariaDB password for account 'root'."
|
97
|
+
warn "You should create a ~/.my.cnf file instead, or you'll need to enter your MySQL root password for each db."
|
98
|
+
warn "See https://makandracards.com/makandra/50813-store-mysql-passwords-for-development for more information."
|
99
|
+
cmd << ' -p' # need to ask for password now
|
100
|
+
end
|
101
|
+
Open3.popen3("#{cmd} -e 'QUIT'") do |stdin2, stdout2, stderr2, thread2|
|
102
|
+
fail 'Could not connect to MySQL/MariaDB' unless thread2.value.exitstatus == 0
|
103
|
+
end
|
104
|
+
elsif mysql_error == '2013' # connection to port or socket failed
|
105
|
+
fail 'MySQL/MariaDB connection failed, is this the correct port?'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
return cmd
|
109
|
+
end
|
110
|
+
private :decide_mysql_command
|
111
|
+
|
112
|
+
def decide_postgres_command(extra_flags)
|
113
|
+
cmd = 'sudo -u postgres psql'
|
114
|
+
unless extra_flags.nil?
|
115
|
+
begin
|
116
|
+
port = Integer(extra_flags.split('=')[1])
|
117
|
+
fail "Port #{port} is not open" unless Geordi::Util.is_port_open? port
|
118
|
+
rescue ArgumentError
|
119
|
+
socket = extra_flags.split('=')[1]
|
120
|
+
fail "Socket #{socket} does not exist" unless File.exist? socket
|
121
|
+
end
|
122
|
+
cmd << " #{extra_flags}"
|
123
|
+
end
|
124
|
+
return cmd
|
125
|
+
end
|
126
|
+
private :decide_postgres_command
|
127
|
+
|
128
|
+
def list_all_dbs(dbtype)
|
129
|
+
if dbtype == 'postgres'
|
130
|
+
return list_all_postgres_dbs
|
131
|
+
else
|
132
|
+
return list_all_mysql_dbs
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def list_all_postgres_dbs
|
137
|
+
`#{@postgres_command} -t -A -c 'SELECT DATNAME FROM pg_database WHERE datistemplate = false'`.split
|
138
|
+
end
|
139
|
+
|
140
|
+
def list_all_mysql_dbs
|
141
|
+
if @mysql_command.include? '-p'
|
142
|
+
puts "Please enter your MySQL/MariaDB account 'root' for: list all databases"
|
143
|
+
end
|
144
|
+
`#{@mysql_command} -B -N -e 'show databases'`.split
|
145
|
+
end
|
146
|
+
|
147
|
+
def clean_mysql
|
148
|
+
announce 'Checking for MySQL databases'
|
149
|
+
database_list = list_all_dbs('mysql')
|
150
|
+
# confirm_deletion includes option for whitelist editing
|
151
|
+
deletable_dbs = confirm_deletion('mysql', database_list)
|
152
|
+
return if deletable_dbs.nil?
|
153
|
+
deletable_dbs.each do |db|
|
154
|
+
if @mysql_command.include? '-p'
|
155
|
+
puts "Please enter your MySQL/MariaDB account 'root' for: DROP DATABASE #{db}"
|
156
|
+
else
|
157
|
+
note "Dropping MySQL/MariaDB database #{db}"
|
158
|
+
end
|
159
|
+
`#{@mysql_command} -e 'DROP DATABASE \`#{db}\`;'`
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def clean_postgres
|
164
|
+
announce 'Checking for Postgres databases'
|
165
|
+
database_list = list_all_dbs('postgres')
|
166
|
+
deletable_dbs = confirm_deletion('postgres', database_list)
|
167
|
+
return if deletable_dbs.nil?
|
168
|
+
deletable_dbs.each do |db|
|
169
|
+
note "Dropping PostgreSQL database `#{db}`."
|
170
|
+
`#{@postgres_command} -c 'DROP DATABASE "#{db}";'`
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def whitelist_fname(dbtype)
|
175
|
+
File.join(@whitelist_directory, dbtype) << '.txt'
|
176
|
+
end
|
177
|
+
|
178
|
+
def confirm_deletion(dbtype, database_list)
|
179
|
+
proceed = ''
|
180
|
+
until %w[y n].include? proceed
|
181
|
+
deletable_dbs = filter_whitelisted(dbtype, database_list)
|
182
|
+
if deletable_dbs.empty?
|
183
|
+
note "No #{dbtype} databases found that were not whitelisted"
|
184
|
+
if prompt('Edit the whitelist? [y]es or [n]o') == 'y'
|
185
|
+
proceed = 'e'
|
186
|
+
else
|
187
|
+
return []
|
188
|
+
end
|
189
|
+
end
|
190
|
+
if proceed.empty?
|
191
|
+
note "The following #{dbtype} databases are not whitelisted and could be deleted:"
|
192
|
+
deletable_dbs.sort.each do |db|
|
193
|
+
puts db
|
194
|
+
end
|
195
|
+
note "Those #{dbtype} databases are not whitelisted and could be deleted."
|
196
|
+
proceed = prompt('Proceed? [y]es, [n]o or [e]dit whitelist')
|
197
|
+
end
|
198
|
+
case proceed
|
199
|
+
when 'e'
|
200
|
+
proceed = '' # reset user selection
|
201
|
+
edit_whitelist dbtype
|
202
|
+
when 'n'
|
203
|
+
success 'Not deleting anything'
|
204
|
+
return []
|
205
|
+
when 'y'
|
206
|
+
return deletable_dbs
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
private :confirm_deletion
|
211
|
+
|
212
|
+
def is_protected?(dbtype, database_name)
|
213
|
+
protected = {
|
214
|
+
'mysql' => %w[mysql information_schema performance_schema sys],
|
215
|
+
'postgres' => ['postgres'],
|
216
|
+
}
|
217
|
+
protected[dbtype].include? database_name
|
218
|
+
end
|
219
|
+
|
220
|
+
def is_whitelisted?(dbtype, database_name)
|
221
|
+
if File.exist? whitelist_fname(dbtype)
|
222
|
+
whitelist_content = Geordi::Util.stripped_lines(File.open(whitelist_fname(dbtype), 'r').read)
|
223
|
+
else
|
224
|
+
whitelist_content = Array.new
|
225
|
+
end
|
226
|
+
whitelist_content.include? database_name.sub(@derivative_dbname, '')
|
227
|
+
end
|
228
|
+
|
229
|
+
def filter_whitelisted(dbtype, database_list)
|
230
|
+
# n.b. `delete` means 'delete from list of dbs that should be deleted in this context
|
231
|
+
# i.e. `delete` means 'keep this database'
|
232
|
+
deletable_dbs = database_list.dup
|
233
|
+
deletable_dbs.delete_if { |db| is_whitelisted?(dbtype, db) if File.exist? whitelist_fname(dbtype) }
|
234
|
+
deletable_dbs.delete_if { |db| is_protected?(dbtype, db) }
|
235
|
+
deletable_dbs.delete_if { |db| db.start_with? '#' }
|
236
|
+
end
|
237
|
+
private :filter_whitelisted
|
238
|
+
end
|
239
|
+
end
|
data/lib/geordi/interaction.rb
CHANGED
@@ -1,31 +1,42 @@
|
|
1
|
+
# Use the methods in this file to communicate with the user
|
2
|
+
#
|
1
3
|
module Geordi
|
2
4
|
module Interaction
|
3
5
|
|
6
|
+
# Start your command by `announce`-ing what you're about to do
|
4
7
|
def announce(text)
|
5
8
|
message = "\n# #{text}"
|
6
9
|
puts "\e[4;34m#{message}\e[0m" # blue underline
|
7
10
|
end
|
8
11
|
|
12
|
+
# Any hints, comments, infos or explanations should be `note`d. Please do
|
13
|
+
# not print any output (data, file contents, lists) with `note`.
|
9
14
|
def note(text)
|
10
15
|
puts '> ' + text
|
11
16
|
end
|
12
17
|
|
18
|
+
# Like `note`, but yellow. Use to warn the user.
|
13
19
|
def warn(text)
|
14
20
|
message = "> #{text}"
|
15
21
|
puts "\e[33m#{message}\e[0m" # yellow
|
16
22
|
end
|
17
23
|
|
24
|
+
# Like `note`, but pink. Use to print (bash) commands.
|
25
|
+
# Also see Util.system!
|
18
26
|
def note_cmd(text)
|
19
27
|
message = "> #{text}"
|
20
28
|
puts "\e[35m#{message}\e[0m" # pink
|
21
29
|
end
|
22
30
|
|
31
|
+
# Exit execution with status code 1 and give a short note what happened,
|
32
|
+
# e.g. "Failed" or "Cancelled"
|
23
33
|
def fail(text)
|
24
34
|
message = "\nx #{text}"
|
25
35
|
puts "\e[31m#{message}\e[0m" # red
|
26
36
|
exit(1)
|
27
37
|
end
|
28
38
|
|
39
|
+
# When you're done, inform the user with a `success` and a short message
|
29
40
|
def success(text)
|
30
41
|
message = "\n> #{text}"
|
31
42
|
puts "\e[32m#{message}\e[0m" # green
|
data/lib/geordi/util.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'geordi/interaction'
|
2
|
+
require 'socket'
|
2
3
|
|
3
4
|
module Geordi
|
4
5
|
class Util
|
@@ -79,6 +80,37 @@ module Geordi
|
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
83
|
+
# try to guess user's favorite cli text editor
|
84
|
+
def decide_texteditor
|
85
|
+
%w[$VISUAL $EDITOR /usr/bin/editor vi].each do |texteditor|
|
86
|
+
if cmd_exists? texteditor and texteditor.start_with? '$'
|
87
|
+
return ENV[texteditor[1..-1]]
|
88
|
+
elsif cmd_exists? texteditor
|
89
|
+
return texteditor
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# check if given cmd is executable. Absolute path or command in $PATH allowed.
|
95
|
+
def cmd_exists? cmd
|
96
|
+
system("which #{cmd} > /dev/null")
|
97
|
+
return $?.exitstatus.zero?
|
98
|
+
end
|
99
|
+
|
100
|
+
def is_port_open?(port)
|
101
|
+
begin
|
102
|
+
socket = TCPSocket.new('127.0.0.1', port)
|
103
|
+
socket.close
|
104
|
+
return true
|
105
|
+
rescue Errno::ECONNREFUSED
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# splint lines e.g. read from a file into lines and clean those up
|
111
|
+
def stripped_lines(input_string)
|
112
|
+
input_string.lines.map(&:chomp).map(&:strip)
|
113
|
+
end
|
82
114
|
end
|
83
115
|
end
|
84
116
|
end
|
data/lib/geordi/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geordi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henning Koch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -97,6 +97,8 @@ files:
|
|
97
97
|
- lib/geordi/commands/create_database_yml.rb
|
98
98
|
- lib/geordi/commands/create_databases.rb
|
99
99
|
- lib/geordi/commands/cucumber.rb
|
100
|
+
- lib/geordi/commands/db_clean.rb
|
101
|
+
- lib/geordi/commands/delete_dumps.rb
|
100
102
|
- lib/geordi/commands/deploy.rb
|
101
103
|
- lib/geordi/commands/dump.rb
|
102
104
|
- lib/geordi/commands/eurest.rb
|
@@ -117,6 +119,7 @@ files:
|
|
117
119
|
- lib/geordi/commands/vnc.rb
|
118
120
|
- lib/geordi/commands/with_rake.rb
|
119
121
|
- lib/geordi/cucumber.rb
|
122
|
+
- lib/geordi/db_cleaner.rb
|
120
123
|
- lib/geordi/dump_loader.rb
|
121
124
|
- lib/geordi/firefox_for_selenium.rb
|
122
125
|
- lib/geordi/gitpt.rb
|