commit d40c27d55aa488cbe733834c18bf5d803d361f69
parent 6d1c13c52e17c5995bd71f08ade578420b4d6fea
Author: Daniel Barlow <dan@telent.net>
Date: Wed, 11 Aug 2021 18:00:39 +0100
convert big case statement to CLI class
means we can have help text
Diffstat:
3 files changed, 98 insertions(+), 43 deletions(-)
diff --git a/features/moss.feature b/features/moss.feature
@@ -110,3 +110,8 @@ Feature: command-line password management
When I store a secret for "silly/two\nlines" with content "horsebattery"
Then "silly/two\nlines.age" plaintext is "horsebattery"
+ Scenario: I can see usage information
+ When I run "moss help"
+ Then I see the string "Store and retrieve encrypted secrets"
+ And I see the string "Usage: moss \[command\] \[parameters\]"
+ And I see the string "add a secret to the store"
diff --git a/features/step_definitions/steps.rb b/features/step_definitions/steps.rb
@@ -189,3 +189,8 @@ Then("my identity file is readable only by me") do
mode = File.stat(pathname).mode
expect(mode & 077).to be_zero
end
+
+When("I run \"moss help\"") do
+ @i_see = shell "#{MOSS} help"
+end
+
diff --git a/moss.rb b/moss.rb
@@ -163,50 +163,95 @@ def random_alnum(length)
bytes.pack("C*")
end
+
+class CLI
+ @@commands = {}
-action, *parameters = ARGV
-case action
-when 'generate'
- file , len = parameters
- secret = random_alnum(len.to_i)
- print secret
- MOSS.write_secret(file, secret)
-when 'insert','add'
- file, = parameters
- secret = STDIN.read
- MOSS.write_secret(file, secret)
-when 'cat','show'
- file, = parameters
- STDOUT.write(MOSS.read_secret(file))
-when 'edit'
- file, = parameters
- content = MOSS.read_secret(file)
- Tempfile.create(file.gsub(/[\W]/,"")) do |f|
- f.write(content)
- f.flush
- if Kernel.system(ENV['EDITOR'], f.path)
- f.rewind
- secret = f.read
- MOSS.write_secret(file, secret)
- else
- raise "#{$!}"
+ class << self
+ def command(name, docstring, &blk)
+ @@commands[name] = { name: name, doc: docstring, block: blk }
+ end
+
+ def dispatch(name, *parameters)
+ @@commands.fetch(name.to_sym)[:block].call(*parameters)
+ true
+ end
+
+ def aka(command, command_alias)
+ @@commands[command_alias] = @@commands[command]
end
+
+ def usage
+ puts "Store and retrieve encrypted secrets\n\n"
+ puts "Usage: moss [command] [parameters]...\n\n"
+ @@commands.each do |name, command|
+ next unless name == command[:name] # skip aliases
+ meth = command[:block]
+ params = meth.parameters
+ printf " %-40s - %s \n",
+ ([command[:name]] + params.map {|p| p[1].to_s }).join(" "),
+ command[:doc]
+ end
+ end
+ end
+
+ command :generate, "generate a random secret" do |filename, length|
+ secret = random_alnum(length.to_i)
+ print secret
+ MOSS.write_secret(filename, secret)
+ end
+
+ command :add, "add a secret to the store" do |filename|
+ secret = STDIN.read
+ MOSS.write_secret(filename, secret)
+ end
+ aka :add, :insert
+
+ command :show, "display a secret" do |file|
+ STDOUT.write(MOSS.read_secret(file))
+ end
+ aka :show, :cat
+
+ command :search, "search secrets with names matching term" do |*term|
+ files = MOSS.secrets.filter {|f|
+ f.match(Regexp.new(term.join(" ")))
+ }
+ files.each do |n|
+ puts n
+ end
+ end
+ aka :search, :list
+
+ command :edit, "edit a secret" do |file|
+ content = MOSS.read_secret(file)
+ Tempfile.create(file.gsub(/[\W]/,"")) do |f|
+ f.write(content)
+ f.flush
+ if Kernel.system(ENV['EDITOR'], f.path)
+ f.rewind
+ secret = f.read
+ MOSS.write_secret(file, secret)
+ else
+ raise "#{$!}"
+ end
+ end
+ end
+
+ command :config, "show configuration" do
+ puts JSON.generate(MOSS.config)
+ end
+
+ command :init, "create new moss repository" do |keyfile|
+ MOSS.create(Pathname.new(keyfile))
+ end
+
+ command :git, "perform git operation in store" do |* parameters|
+ MOSS.git_operation(parameters)
+ end
+
+ command :help, "display this help text" do
+ self.usage
end
-when 'search','list'
- term = parameters.join(" ")
- files = MOSS.secrets.filter {|f|
- f.match(Regexp.new(term))
- }
- files.each do |n|
- puts n
- end
-when 'config'
- puts JSON.generate(MOSS.config)
-when 'init'
- keyfile = Pathname.new(parameters.first)
- MOSS.create(keyfile)
-when 'git'
- MOSS.git_operation(parameters)
-else
- raise "command #{action} unrecognized"
end
+
+CLI.dispatch(* ARGV)