From 0d0e7e01bab1708cd85294788f9b9cca33a33ddb Mon Sep 17 00:00:00 2001 From: Sean Edge Date: Thu, 27 Nov 2014 13:08:14 -0500 Subject: [PATCH] Now must use YAML valid syntax in CLI or CLI Shell where Gitlab methods expect Hashes (usually in the form of options). Should fix these issues: https://github.com/NARKOZ/gitlab/issues/68 https://github.com/NARKOZ/gitlab/issues/80 --- README.md | 7 +++++++ lib/gitlab/cli.rb | 6 ++++++ lib/gitlab/cli_helpers.rb | 43 ++++++++++++++++++++++++++++++++++++--- lib/gitlab/help.rb | 4 ++-- lib/gitlab/shell.rb | 27 +++++++++++++++++++++--- 5 files changed, 79 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1aa73996c..04b55c2dc 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,10 @@ gitlab user 2 gitlab user --only=id,username gitlab user --except=email,bio + +# how to pass options hash to a command (use YAML) +gitlab create_merge_request 4 "I'm creating a new merge request!" "{source_branch: 'new_branch', target_branch: 'master', assignee_id: 42}" + ``` ## CLI Shell @@ -112,6 +116,9 @@ gitlab> groups # protect a branch gitlab> protect_branch 1 master + +# how to pass options hash to a command (use YAML) +gitlab> create_merge_request 4 "I'm creating a new merge request!" "{source_branch: 'new_branch', target_branch: 'master', assignee_id: 42}" ``` For more information, refer to [website](http://narkoz.github.io/gitlab). diff --git a/lib/gitlab/cli.rb b/lib/gitlab/cli.rb index 57c2aa5b4..db6320e20 100644 --- a/lib/gitlab/cli.rb +++ b/lib/gitlab/cli.rb @@ -38,6 +38,12 @@ def self.run(cmd, args=[]) command_args = args end + begin + yaml_load_and_symbolize_hash!(command_args) + rescue + exit 1 + end + confirm_command(cmd) data = gitlab_helper(cmd, command_args) { exit(1) } diff --git a/lib/gitlab/cli_helpers.rb b/lib/gitlab/cli_helpers.rb index d1c777dc0..839900b81 100644 --- a/lib/gitlab/cli_helpers.rb +++ b/lib/gitlab/cli_helpers.rb @@ -1,3 +1,4 @@ +require 'yaml' class Gitlab::CLI # Defines methods related to CLI output and formatting. module Helpers @@ -7,7 +8,7 @@ module Helpers # # @return [Array] def required_fields(args) - if args.any? && args.last.start_with?('--only=') + if args.any? && args.last.is_a?(String) && args.last.start_with?('--only=') args.last.gsub('--only=', '').split(',') else [] @@ -18,7 +19,7 @@ def required_fields(args) # # @return [Array] def excluded_fields(args) - if args.any? && args.last.start_with?('--except=') + if args.any? && args.last.is_a?(String) && args.last.start_with?('--except=') args.last.gsub('--except=', '').split(',') else [] @@ -45,7 +46,7 @@ def confirm_command(cmd) puts 'Command aborted.' exit(1) end - end + end end # Table with available commands. @@ -171,5 +172,41 @@ def gitlab_helper(cmd, args=[]) data end + + # Convert a hash (recursively) to use symbol hash keys + # @return [Hash] + def symbolize_keys(hash) + if hash.is_a?(Hash) + hash = hash.each_with_object({}) do |(key, value), newhash| + begin + newhash[key.to_sym] = symbolize_keys(value) + rescue NoMethodError + puts "error: cannot convert hash key to symbol: #{arg}" + raise + end + end + end + + hash + end + + # Run YAML::load on each arg and symbolize hash keys if found. + # @return [Array] + def yaml_load_and_symbolize_hash!(args) + args.map! do |arg| + begin + arg = YAML::load(arg) + + if arg.is_a?(Hash) + arg = symbolize_keys(arg) + end + rescue Psych::SyntaxError + puts "error: Argument is not valid YAML syntax: #{arg}" + raise + end + + arg + end + end end end diff --git a/lib/gitlab/help.rb b/lib/gitlab/help.rb index 6ead8af94..365c40c68 100644 --- a/lib/gitlab/help.rb +++ b/lib/gitlab/help.rb @@ -20,10 +20,10 @@ def self.get_help(methods,cmd=nil) ri_output = `#{ri_cmd} -T #{namespace} 2>&1`.chomp if $? == 0 - ri_output.gsub!(/#{cmd}\((.*?)\)/, cmd+' \1') + ri_output.gsub!(/#{cmd}\((.*?)\)/m, cmd+' \1') ri_output.gsub!(/Gitlab\./, 'gitlab> ') ri_output.gsub!(/Gitlab\..+$/, '') - ri_output.gsub!(/\,\s?/, ' ') + ri_output.gsub!(/\,[\s]*/, ' ') help = ri_output else help = "Ri docs not found for #{namespace}, please install the docs to use 'help'" diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb index 9253b61e3..52e275957 100644 --- a/lib/gitlab/shell.rb +++ b/lib/gitlab/shell.rb @@ -2,10 +2,12 @@ require 'gitlab/help' require 'gitlab/cli_helpers' require 'readline' +require 'shellwords' class Gitlab::Shell extend Gitlab::CLI::Helpers + # Start gitlab shell and run infinite loop waiting for user input def self.start actions = Gitlab.actions @@ -20,7 +22,13 @@ def self.start next if buf.nil? || buf.empty? break if buf == 'exit' - buf = buf.scan(/["][^"]+["]|\S+/).map { |word| word.gsub(/^['"]|['"]$/,'') } + begin + buf = Shellwords.shellwords(buf) + rescue ArgumentError => e + puts e.message + next + end + cmd = buf.shift args = buf.count > 0 ? buf : [] @@ -34,15 +42,28 @@ def self.start } end - args[0].nil? ? Gitlab::Help.get_help(methods) : Gitlab::Help.get_help(methods, args[0]) + args[0].nil? ? Gitlab::Help.get_help(methods) : + Gitlab::Help.get_help(methods, args[0]) next end + syntax_errors = false + + begin + yaml_load_and_symbolize_hash!(args) + rescue + syntax_errors = true + end + + # errors have been displayed, return to the prompt + next if syntax_errors + data = if actions.include?(cmd.to_sym) confirm_command(cmd) gitlab_helper(cmd, args) else - "'#{cmd}' is not a valid command. See the 'help' for a list of valid commands." + "'#{cmd}' is not a valid command. " + + "See the 'help' for a list of valid commands." end output_table(cmd, args, data)