pmgmt 1.0.0 → 1.1.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.
Files changed (4) hide show
  1. checksums.yaml +5 -5
  2. data/lib/optionsparser.rb +69 -0
  3. data/lib/pmgmt.rb +68 -13
  4. metadata +8 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 3e30d7e78a8a61ae27c505f47f1821c2ee991ac91264abfed389651626823e9a
4
- data.tar.gz: 151734accba09a0511a88d78380894de6c4af6fad2ad0613c701441eb89963de
2
+ SHA1:
3
+ metadata.gz: 3e6afb20a3759c4c7975553ffb186bb641cb7b05
4
+ data.tar.gz: f0200e100d4de9902e24286d6cc4f78a05cf0270
5
5
  SHA512:
6
- metadata.gz: 764187c3dcb66e45fd17b6e111d8230f06e4fa622f75690f9cf3a43639f75777392b1d8a37cbb59d6b13e854da3e2411e5c3e3e2fe5d6c1c5ad28fe20c1cbfb2
7
- data.tar.gz: 97a9f031cd58f3ba87e97104cef2be3945a27c13815a55be444507cf9184f7285a3e6c011ee3e44d62fd0a7d5d586f31cd0ff817ed03373509f00ef9043f4fea
6
+ metadata.gz: 768f313e048275c7c79aab4e88a4e963999ca657cacfde98241f5ee13e8795e3c022cc28a9971e554e6ce014d7cbbaddb96fedae76eab89c355f8a0ce2f1f115
7
+ data.tar.gz: 257c6e1a90cb9b67e8d89f0fcb8ca23ea53d1c53609eb41cfcdf41b0fcd9d2b73ede6f315431fb5ff39a35d98fb27d43977bdaee3ef285db9d3109b7f80133e4
@@ -0,0 +1,69 @@
1
+ require "optparse"
2
+ require "ostruct"
3
+
4
+ # Creates a default command-line argument parser.
5
+ # command_name: For help text.
6
+ def create_parser(command_name)
7
+ OptionParser.new do |parser|
8
+ parser.banner = "Usage: #{$PROGRAM_NAME} #{command_name} [options]"
9
+ parser
10
+ end
11
+ end
12
+
13
+ module PmgmtLib
14
+
15
+ ##
16
+ # Allows parsing of command line options without requiring any subclassing.
17
+
18
+ class OptionsParser
19
+ attr_reader :opts, :remaining
20
+
21
+ def initialize(command_name, args)
22
+ @opts = OpenStruct.new
23
+ @parser = create_parser(command_name)
24
+ @args = args
25
+ @validators = []
26
+ end
27
+
28
+ def add_option(option, assign, help)
29
+ @parser.on(option, help) {|v| assign.call(@opts, v)}
30
+ self
31
+ end
32
+
33
+ def add_typed_option(option, type, assign, help)
34
+ @parser.on(option, type, help) {|v| assign.call(@opts, v)}
35
+ self
36
+ end
37
+
38
+ def add_validator(fn)
39
+ @validators.push(fn)
40
+ self
41
+ end
42
+
43
+ def parse()
44
+ begin
45
+ @remaining = @parser.parse @args
46
+ rescue ArgumentError => e
47
+ STDERR.puts e
48
+ STDERR.puts
49
+ STDERR.puts @parser.help
50
+ exit 1
51
+ end
52
+ self
53
+ end
54
+
55
+ def validate()
56
+ @validators.each do |fn|
57
+ begin
58
+ fn.call(@opts)
59
+ rescue ArgumentError => e
60
+ STDERR.puts e
61
+ STDERR.puts
62
+ STDERR.puts @parser.help
63
+ exit 1
64
+ end
65
+ end
66
+ self
67
+ end
68
+ end
69
+ end
data/lib/pmgmt.rb CHANGED
@@ -3,11 +3,23 @@ require "ostruct"
3
3
  require "yaml"
4
4
 
5
5
  require_relative "dockerhelper"
6
+ require_relative "optionsparser"
6
7
  require_relative "syncfiles"
7
8
 
8
9
  class Pmgmt
10
+ # State to hold registered commands. See {#Pmgmt.register_command}.
9
11
  @@commands = []
12
+ # Convenience method to provide access to the options parsing utility class.
13
+ @@options_parser = PmgmtLib::OptionsParser
10
14
 
15
+ def self.OptionsParser
16
+ @@options_parser
17
+ end
18
+
19
+ # Loads all `.rb` scripts from the given directory. Scripts are expected to register commands as
20
+ # a side-effect of loading.
21
+ # @param scripts_dir [String]
22
+ # @return [void]
11
23
  def self.load_scripts(scripts_dir)
12
24
  if !File.directory?(scripts_dir)
13
25
  self.new.error "Cannot load scripts. Not a directory: #{scripts_dir}"
@@ -20,9 +32,22 @@ class Pmgmt
20
32
  end
21
33
  end
22
34
 
35
+ # Registers a command. Registered commands can be invoked by name, appear in command lists and
36
+ # allow --help docs.
37
+ # @param command [Map] The :invocation key is what would be typed to invoke the command and the :fn key is what function to execute when invoked. Specify only a :fn key for shorthand.
38
+ # @return [void]
23
39
  def self.register_command(command)
24
- invocation = command[:invocation]
25
- fn = command[:fn]
40
+ if command.nil?
41
+ self.new.error "register_command called with nil argument"
42
+ exit 1
43
+ end
44
+ if command.is_a?(Symbol)
45
+ invocation = command.to_s
46
+ fn = command
47
+ else
48
+ invocation = command[:invocation]
49
+ fn = command[:fn]
50
+ end
26
51
  if fn.nil?
27
52
  self.new.error "No :fn key defined for command #{invocation}"
28
53
  exit 1
@@ -40,13 +65,16 @@ class Pmgmt
40
65
  end
41
66
  end
42
67
 
43
- @@commands.push(command)
68
+ @@commands.push({:invocation => invocation, :fn => fn})
44
69
  end
45
70
 
71
+ # @return [Array] the commands array for inspection.
46
72
  def self.commands()
47
73
  @@commands
48
74
  end
49
75
 
76
+ # Handles command execution.
77
+ # @param args [Array] Pass ARGV.
50
78
  def self.handle_or_die(args)
51
79
  if args.length == 0 or args[0] == "--help"
52
80
  self.new.print_usage
@@ -65,19 +93,27 @@ class Pmgmt
65
93
  command = args.first
66
94
  handler = @@commands.select{ |x| x[:invocation] == command }.first
67
95
  if handler.nil?
68
- error "#{command} command not found."
96
+ self.new.error "#{command} command not found."
69
97
  exit 1
70
98
  end
71
99
 
72
100
  fn = handler[:fn]
101
+ args = args
73
102
  if fn.is_a?(Symbol)
74
- method(fn).call(*args)
103
+ fn = method(fn)
104
+ else
105
+ args = args.drop(1)
106
+ end
107
+ if fn.arity == 0
108
+ fn.call()
75
109
  else
76
- handler[:fn].call(*args.drop(1))
110
+ fn.call(*args)
77
111
  end
78
112
  end
79
113
 
114
+ # Convenience method to easily retrieve Docker utilities. See {#PmgmtLib::DockerHelper}.
80
115
  attr :docker
116
+ # Convenience method to easily retrieve file-syncing utilities. See {#PmgmtLib::SyncFiles}.
81
117
  attr :sf
82
118
 
83
119
  def initialize()
@@ -123,19 +159,25 @@ class Pmgmt
123
159
  "\033[1m#{text}\033[0m"
124
160
  end
125
161
 
162
+ # Prints "status" text (blue) on STDERR.
163
+ # @return [void]
126
164
  def status(text)
127
165
  STDERR.puts blue_term_text(text)
128
166
  end
129
167
 
168
+ # Prints "warning" text (yellow) on STDERR.
169
+ # @return [void]
130
170
  def warning(text)
131
171
  STDERR.puts yellow_term_text(text)
132
172
  end
133
173
 
174
+ # Prints "error" text (red) on STDERR.
175
+ # @return [void]
134
176
  def error(text)
135
177
  STDERR.puts red_term_text(text)
136
178
  end
137
179
 
138
- def put_command(cmd, redact=nil)
180
+ def put_command(cmd, redact: nil)
139
181
  if cmd.is_a?(String)
140
182
  command_string = "+ #{cmd}"
141
183
  else
@@ -148,8 +190,11 @@ class Pmgmt
148
190
  STDERR.puts command_to_echo
149
191
  end
150
192
 
151
- # Pass err=nil to suppress stderr.
152
- def capture_stdout(cmd, err = STDERR)
193
+ # Runs the given command and captures its stdout.
194
+ # @param cmd [Array] Command to run.
195
+ # @param err: Pass nil to suppress stderr output.
196
+ # @return [String] Captured stdout.
197
+ def capture_stdout(cmd, err: STDERR)
153
198
  if err.nil?
154
199
  err = "/dev/null"
155
200
  end
@@ -157,8 +202,12 @@ class Pmgmt
157
202
  output
158
203
  end
159
204
 
160
- def run_inline(cmd, redact=nil)
161
- put_command(cmd, redact)
205
+ # Runs the given command "inline," meaning that it will take over the terminal while running.
206
+ # @param cmd [Array] Command to run.
207
+ # @param redact: [String] Occurrances of this string will be hidden from normal output.
208
+ # @return [void]
209
+ def run_inline(cmd, redact: nil)
210
+ put_command(cmd, redact: redact)
162
211
 
163
212
  # `system`, by design (?!), hides stderr when the command fails.
164
213
  if ENV["PROJECTRB_USE_SYSTEM"] == "true"
@@ -179,6 +228,7 @@ class Pmgmt
179
228
  end
180
229
  end
181
230
 
231
+ # Similar to {#run_inline} but will prevent exiting when an interrupt is encountered.
182
232
  def run_inline_swallowing_interrupt(cmd)
183
233
  begin
184
234
  run_inline cmd
@@ -186,8 +236,9 @@ class Pmgmt
186
236
  end
187
237
  end
188
238
 
189
- def run_or_fail(cmd, redact=nil)
190
- put_command(cmd, redact)
239
+ # Runs a command and fails on non-success exit code.
240
+ def run_or_fail(cmd, redact: nil)
241
+ put_command(cmd, redact: redact)
191
242
  Open3.popen3(*cmd) do |i, o, e, t|
192
243
  i.close
193
244
  if not t.value.success?
@@ -197,6 +248,8 @@ class Pmgmt
197
248
  end
198
249
  end
199
250
 
251
+ # Runs a command without echoing.
252
+ # @return [Status] command's exit status.
200
253
  def run(cmd)
201
254
  Open3.popen3(*cmd) do |i, o, e, t|
202
255
  i.close
@@ -204,6 +257,8 @@ class Pmgmt
204
257
  end
205
258
  end
206
259
 
260
+ # Accepts multiple arrays of commands and pipes each one to the next, failing if any command
261
+ # exits with an error.
207
262
  def pipe(*cmds)
208
263
  s = cmds.map { |x| x.join(" ") }
209
264
  s = s.join(" | ")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pmgmt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Mohs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-10 00:00:00.000000000 Z
11
+ date: 2018-12-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A library to make Ruby your preferred scripting language for dev scripts.
14
14
  email: davidmohs@gmail.com
@@ -17,12 +17,14 @@ extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
19
  - lib/dockerhelper.rb
20
+ - lib/optionsparser.rb
20
21
  - lib/pmgmt.rb
21
22
  - lib/syncfiles.rb
22
- homepage: http://rubygems.org/gems/pmgmt
23
+ homepage: https://github.com/dmohs/project-management
23
24
  licenses:
24
25
  - MIT
25
- metadata: {}
26
+ metadata:
27
+ source_code_uri: https://github.com/dmohs/project-management
26
28
  post_install_message:
27
29
  rdoc_options: []
28
30
  require_paths:
@@ -31,7 +33,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
31
33
  requirements:
32
34
  - - ">="
33
35
  - !ruby/object:Gem::Version
34
- version: '0'
36
+ version: '2'
35
37
  required_rubygems_version: !ruby/object:Gem::Requirement
36
38
  requirements:
37
39
  - - ">="
@@ -39,7 +41,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
39
41
  version: '0'
40
42
  requirements: []
41
43
  rubyforge_project:
42
- rubygems_version: 2.7.6
44
+ rubygems_version: 2.5.2.3
43
45
  signing_key:
44
46
  specification_version: 4
45
47
  summary: Project management scripting library.