flo 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b84be555cacd1fd27392d83cd39e89c19e9dafd4
4
- data.tar.gz: 9cd073f4e4c9ab0da1ea2b816b2cb1e90a579441
3
+ metadata.gz: 0c4b34788a7d80192abd6ec7d302ebc9b0e44615
4
+ data.tar.gz: 26f726d4839283d43adc1a4fafd9a47464338b7e
5
5
  SHA512:
6
- metadata.gz: 43b7d50133307857e6a656d5ef99b0c9b8c0e99030541b7c890086d3903e4ca6b4387ea624d060e17d02384b6d6b1e9c0dbad5c22d44809b4f324b920881fd43
7
- data.tar.gz: e8ad9ceec8b76344fa641774919a41d38298f2c50d122668e64935175a0c4e61b657a95233746ee8c36cb8f491cd07919a5ec1fc7536f434981396a43664f31b
6
+ metadata.gz: c8b474dfc8872e4a04cd236c51837dda2668ef9f7d75bb405935f5cfd5998adcfe6068b09a38010a4f7b06d1cd5a37c99e3b67c246401a628836964a59d77a26
7
+ data.tar.gz: 38c4d9b143a55b62fbb9c71f86d53d7b62e19fc485c343e2b61cc67f640c54bb3fba302e2a42d5fca4161480d74c5a2170e852dd946417a69f5da389eb51d939
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Flo
2
- [![Code Climate](https://codeclimate.com/github/codeclimate/codeclimate/badges/gpa.svg)](https://codeclimate.com/github/codeclimate/codeclimate) [![Build Status](https://semaphoreci.com/api/v1/justinpowers/flo/branches/master/shields_badge.svg)](https://semaphoreci.com/justinpowers/flo)
2
+ [![Gem Version](https://badge.fury.io/rb/flo.svg)](https://badge.fury.io/rb/flo) [![Code Climate](https://codeclimate.com/github/salesforce/flo/badges/gpa.svg)](https://codeclimate.com/github/salesforce/flo) [![Test Coverage](https://codeclimate.com/github/salesforce/flo/badges/coverage.svg)](https://codeclimate.com/github/salesforce/flo/coverage) [![Build Status](https://semaphoreci.com/api/v1/justinpowers/flo/branches/master/shields_badge.svg)](https://semaphoreci.com/justinpowers/flo) [![Inline docs](http://inch-ci.org/github/salesforce/flo.svg?branch=master)](http://inch-ci.org/github/salesforce/flo)
3
3
 
4
4
 
5
5
  Flo is a local workflow automation tool that helps you get things done. This gem contains the core functionality for Flo, plugins for interacting with various systems can be found in separate provider gems.
@@ -23,14 +23,23 @@ $ gem install flo
23
23
  ```
24
24
 
25
25
  ## Documentation
26
- https://www.rubydoc.info/github/salesforce/flo/
26
+ http://www.rubydoc.info/github/salesforce/flo/
27
27
 
28
28
  ## Usage
29
29
 
30
30
  ### Command line usage
31
31
 
32
- COMING SOON!
33
- A command line parser has not yet been added. If you require a script that can be invoked from the command line, you can create a ruby script that creates and runs a `Flo::Runner` instance. See [Ruby script usage](#Ruby_script_usage) for more details.
32
+ If you have a `.flo` configuration file (See [.flo configuration file](#flo-configuration-file)), in your current working directory and/or your home directory, flo will parse your configuration file(s) and generate CLI commands for you. To list out the possible commands, use
33
+
34
+ ```bash
35
+ flo help
36
+ ```
37
+
38
+ You can also see the usage and options for specific commands:
39
+
40
+ ```bash
41
+ flo help <command>
42
+ ```
34
43
 
35
44
  ### Ruby script usage
36
45
 
@@ -45,7 +54,7 @@ runner = Flo::Runner.new
45
54
  runner.load_config_file(File.join(__dir__,'.flo'))
46
55
 
47
56
  # Run the something:useful command defined in the .flo file
48
- response = runner.execute([:something, :useful], id: '123')
57
+ response = runner.execute('something:useful', id: '123')
49
58
  ```
50
59
 
51
60
 
@@ -73,7 +82,7 @@ You can register any number of commands. Commands are namespaced to make it eas
73
82
  # Registers a command for starting a feature - feature:start. This command has
74
83
  # one required argument: 'feature_name'. Note that in order for this to work,
75
84
  # you will need to declare the git_flo provider in the config section.
76
- register_command([:feature, :start]) do |feature_name: nil|
85
+ register_command('feature:start') do |feature_name: nil|
77
86
 
78
87
  # During command execution, perform the :check_out_or_create_branch method on
79
88
  # the git_flo provider, passing in the :from and :name arguments
@@ -88,6 +97,7 @@ end
88
97
  3. Commit your changes (`git commit -am 'Add some feature'`)
89
98
  4. Push to the branch (`git push origin my-new-feature`)
90
99
  5. Create new Pull Request
100
+ 6. If this is your first contribution, you will need Accept the Contributor License Agreement. You can follow the link in the pull request 'checks' section to do so.
91
101
 
92
102
  ## License
93
103
 
data/bin/flo ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright © 2017, Salesforce.com, Inc.
4
+ # All Rights Reserved.
5
+ # Licensed under the BSD 3-Clause license.
6
+ # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
+
8
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
9
+ require 'flo'
10
+ require 'flo/cli'
11
+
12
+ Flo::Cli.new.call(ARGV)
data/flo.gemspec CHANGED
@@ -9,24 +9,29 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
9
9
  require 'flo/version'
10
10
 
11
11
  Gem::Specification.new do |spec|
12
- spec.name = "flo"
12
+ spec.name = 'flo'
13
13
  spec.version = Flo::VERSION
14
- spec.authors = ["Justin Powers"]
15
- spec.email = ["justinspowers@gmail.com"]
14
+ spec.authors = ['Justin Powers']
15
+ spec.email = ['justinspowers@gmail.com']
16
16
  spec.summary = %q{Simple developer workflow automation}
17
17
  spec.description = %q{Flo is a local workflow automation tool that helps you get things done. This gem contains the core functionality for Flo, plugins for interacting with various systems can be found in separate provider gems.}
18
- spec.homepage = "https://github.com/salesforce/flo"
19
- spec.license = "BSD-3-Clause"
18
+ spec.homepage = 'https://github.com/salesforce/flo'
19
+ spec.license = 'BSD-3-Clause'
20
20
 
21
+ spec.executables << 'flo'
21
22
  spec.files = `git ls-files -z`.split("\x0")
22
23
  spec.test_files = spec.files.grep(%r{^test/})
23
- spec.require_paths = ["lib"]
24
+ spec.require_paths = ['lib']
24
25
 
25
- spec.add_dependency "cleanroom"
26
+ spec.add_dependency 'cleanroom'
27
+ spec.add_dependency 'gpgme'
28
+ spec.add_dependency 'cri'
26
29
 
27
- spec.add_development_dependency "bundler", "~> 1.5"
28
- spec.add_development_dependency "rake"
29
- spec.add_development_dependency "minitest"
30
- spec.add_development_dependency "pry"
31
- spec.add_development_dependency "simplecov"
30
+ spec.add_development_dependency 'bundler', '~> 1.5'
31
+ spec.add_development_dependency 'rake'
32
+ spec.add_development_dependency 'minitest'
33
+ spec.add_development_dependency 'minitest-proveit'
34
+ spec.add_development_dependency 'pry'
35
+ spec.add_development_dependency 'simplecov'
36
+ spec.add_development_dependency 'codeclimate-test-reporter'
32
37
  end
data/lib/flo/cli.rb ADDED
@@ -0,0 +1,76 @@
1
+ # Copyright © 2017, Salesforce.com, Inc.
2
+ # All Rights Reserved.
3
+ # Licensed under the BSD 3-Clause license.
4
+ # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
+
6
+ require 'cri'
7
+
8
+ module Flo
9
+
10
+ # Builds the command line parser and executes Flo::Runner using the commands supplied.
11
+ # In general you should be able to create a new instance and then pass in ARGV directly
12
+ # into {#call}.
13
+ class Cli
14
+
15
+ # Creates a new CLI runner instance.
16
+ # @option opts [Class] runner_class (Runner) Class of the runner object dependency
17
+ def initialize(opts={})
18
+ @runner_class = opts[:runner_class] || Runner
19
+ end
20
+
21
+ # Runs a command using args directly from ARGV.
22
+ # @param argv [Array<String>] An array of strings. Typically you would pass in ARGV directly.
23
+ # The first value should be the name of the command
24
+ #
25
+ def call(argv)
26
+ generate_commands.run(argv)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :runner_class
32
+
33
+ def generate_commands
34
+ flo_runner = runner_class.new
35
+ flo_runner.load_default_config_files
36
+
37
+ flo_runner.commands.each do |cmd_name, cmd|
38
+
39
+ main_command.define_command do
40
+ options = cmd[:command].required_parameters
41
+
42
+ unless cmd[:command].optional_parameters.empty?
43
+ options << '[options]'
44
+
45
+ cmd[:command].optional_parameters.each do |param|
46
+ optional(nil, param, param.to_s.tr('_', ' '))
47
+ end
48
+ end
49
+
50
+ name(cmd_name)
51
+ usage("#{cmd_name} #{options.join(' ')}")
52
+ summary(cmd[:summary])
53
+ description(cmd[:description])
54
+
55
+ run do |opts, arguments, command|
56
+ flo_runner.execute(command.name, arguments.dup.push(opts))
57
+ end
58
+ end
59
+ end
60
+
61
+ main_command
62
+ end
63
+
64
+ def main_command
65
+ @main_command ||= Cri::Command.new_basic_root.modify do
66
+ name 'flo'
67
+ usage 'flo [command]'
68
+ summary 'Local workflow automation'
69
+ description 'Use `flo help [command]` for usage on individual commands'
70
+
71
+ default_subcommand 'help'
72
+ end
73
+ end
74
+
75
+ end
76
+ end
data/lib/flo/command.rb CHANGED
@@ -87,11 +87,32 @@ module Flo
87
87
  end.last
88
88
  end
89
89
 
90
+ # Returns a list of any required parameters
91
+ #
92
+ # Required parameters are generated automatically by inspecting the required
93
+ # parameters for the definition lambda
94
+ # @return [Array<Symbol>] An array of symbols representing required parameters
95
+ #
96
+ def required_parameters
97
+ definition_lambda.parameters.select { |key,_value| key == :req }.map { |_key,value| value }
98
+ end
99
+
100
+
101
+ # Returns a list of any optional parameters
102
+ #
103
+ # Optional parameters are generated automatically by inspecting the optional
104
+ # parameters for the definition lambda
105
+ # @return [Array<Symbol>] An array of symbols representing optional parameters
106
+ #
107
+ def optional_parameters
108
+ definition_lambda.parameters.select { |key,_value| key == :key }.map { |_key,value| value }
109
+ end
110
+
90
111
  private
91
112
 
92
113
  attr_reader :tasks, :definition_lambda, :providers, :state_class
93
114
 
94
- def evaluate_command_definition(*args)
115
+ def evaluate_command_definition(args)
95
116
  cleanroom.instance_exec(*args, &definition_lambda)
96
117
  end
97
118
 
@@ -3,22 +3,32 @@
3
3
  # Licensed under the BSD 3-Clause license.
4
4
  # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
5
 
6
+ require 'forwardable'
7
+ require 'flo/error'
8
+
6
9
  module Flo
7
- CommandNotDefinedError = Class.new(StandardError)
10
+
11
+ CommandNotDefinedError = Class.new(Flo::Error)
12
+
13
+ # A collection of commands. Behaves like a Hash, except that fetching a key that does
14
+ # not exist raises an error
8
15
  class CommandCollection
16
+ extend Forwardable
17
+ def_delegators :@commands, :each, :[]=
9
18
 
10
19
  def initialize
11
20
  @commands = {}
12
21
  end
13
22
 
14
- def [](*key)
23
+ # Returns the value corresponding to the key. Identical to accessing Hash values, except
24
+ # that fetching a value that does not exist raises an error
25
+ # @param key [String] Name of the command
26
+ # @raises Flo::CommandNotDefinedError if the command does not exist
27
+ #
28
+ def [](key)
15
29
  raise CommandNotDefinedError.new("#{key} command is not defined") unless @commands.has_key?(key)
16
30
  @commands[key]
17
31
  end
18
32
 
19
- def []=(*key, command)
20
- @commands[key] = command
21
- end
22
-
23
33
  end
24
34
  end
data/lib/flo/config.rb CHANGED
@@ -3,14 +3,30 @@
3
3
  # Licensed under the BSD 3-Clause license.
4
4
  # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
5
 
6
+ require 'flo/cred_store/yaml_store'
7
+
6
8
  module Flo
7
- MissingRequireError = Class.new(StandardError)
9
+ MissingRequireError = Class.new(Flo::Error)
8
10
 
9
11
  # Instantiates and stores providers for use in command definitions
10
12
  #
11
13
  # @attr_reader providers [Hash] Hash of provider instances
12
14
  #
13
15
  class Config
16
+
17
+ # A placeholder for credentials that can be evaluated at a later time
18
+ class LazyCreds
19
+
20
+ # Returns a lambda that takes a credential store for a specific provider as an argument.
21
+ # This prevents providers from accessing the credentials for another provider
22
+ # @param key [Symbol,String]
23
+ # @return [lambda]
24
+ def [](key)
25
+ lambda { |cred_store| cred_store[key] }
26
+ end
27
+ end
28
+
29
+ attr_writer :cred_store
14
30
  attr_reader :providers
15
31
 
16
32
  def initialize
@@ -24,7 +40,20 @@ module Flo
24
40
  # accepts a block
25
41
  #
26
42
  def provider(provider_sym, options={}, &blk)
27
- @providers[provider_sym] = provider_class(provider_sym).new(options, &blk)
43
+ provider = provider_class(provider_sym).new(options, &blk)
44
+ provider.cred_store = cred_store.credentials_for(provider_sym)
45
+ @providers[provider_sym] = provider
46
+ end
47
+
48
+ def cred_store
49
+ @cred_store ||= Flo::CredStore::YamlStore.new
50
+ end
51
+
52
+ # Returns an object that responds to [], but instead of returning a value, returns
53
+ # a lambda that can be evaluated later in the context of the credentials for the provider
54
+ # @return [LazyCred]
55
+ def creds
56
+ LazyCreds.new
28
57
  end
29
58
 
30
59
  private
@@ -33,7 +62,7 @@ module Flo
33
62
  klass = camel_case(provider_sym.to_s)
34
63
  klass_name = "Flo::Provider::#{klass}"
35
64
  Object.const_get(klass_name)
36
- rescue NameError => e
65
+ rescue NameError
37
66
  raise MissingRequireError.new("#{klass_name} is not loaded. Please require the library before use")
38
67
  end
39
68
 
@@ -0,0 +1,27 @@
1
+ # Copyright © 2017, Salesforce.com, Inc.
2
+ # All Rights Reserved.
3
+ # Licensed under the BSD 3-Clause license.
4
+ # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
+
6
+ module Flo
7
+ MissingCredentialError = Class.new(Flo::Error)
8
+
9
+ module CredStore
10
+ class Creds
11
+
12
+ def initialize(credentials)
13
+ @credentials = credentials
14
+ end
15
+
16
+ # Returns the credential referenced by the key provided
17
+ # @param key [Symbol, String]
18
+ # @raises Flo::MissingCredentialError if key does not exist
19
+ #
20
+ def [](key)
21
+ raise Flo::MissingCredentialError unless @credentials.key?(key)
22
+
23
+ @credentials[key]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,59 @@
1
+ # Copyright © 2017, Salesforce.com, Inc.
2
+ # All Rights Reserved.
3
+ # Licensed under the BSD 3-Clause license.
4
+ # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
+
6
+ module Flo
7
+ module CredStore
8
+ class PwProtectedStore
9
+
10
+ attr_writer :cred_file
11
+
12
+ def initialize(opts={})
13
+ @password = opts[:password] # If nil, should prompt interactively
14
+ @cred_file_location = opts[:cred_file_location]
15
+ end
16
+
17
+ # Decrypts the credentials file and returns the credentials for the requested provider
18
+ # @param provider_sym [Symbol]
19
+ # @return [Flo::CredStore::Creds]
20
+ #
21
+ def credentials_for(provider_sym)
22
+ Flo::CredStore::Creds.new(full_credentials_hash[provider_sym])
23
+ end
24
+
25
+ # Convenience method for producing an encrypted version of a file. This only returns
26
+ # the encrypted version as a string, you will have to save it yourself if desired
27
+ # @param file_location [String]
28
+ # @return [String]
29
+ def encrypt_file(file_location)
30
+ crypto.encrypt(File.open(file_location)).to_s
31
+ end
32
+
33
+ def cred_file
34
+ @cred_file ||= File.new(@cred_file_location || File.join(Dir.home, '.flo_creds.yml.gpg'))
35
+ end
36
+
37
+ # Remove password from inspect output
38
+ def inspect
39
+ "#<Flo::CredStore::PwProtectedStore:#{object_id} @cred_file=#{cred_file.inspect}>"
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :password
45
+
46
+ def decrypted_file
47
+ crypto.decrypt(cred_file)
48
+ end
49
+
50
+ def full_credentials_hash
51
+ @full_credentials_hash ||= YAML.load(decrypted_file.read) || {}
52
+ end
53
+
54
+ def crypto
55
+ GPGME::Crypto.new(password: @password, symmetric: true)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright © 2017, Salesforce.com, Inc.
2
+ # All Rights Reserved.
3
+ # Licensed under the BSD 3-Clause license.
4
+ # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
+
6
+ require 'yaml'
7
+ require 'flo/error'
8
+ require 'flo/cred_store/creds'
9
+
10
+ module Flo
11
+
12
+ MissingProviderError = Class.new(Flo::Error)
13
+
14
+ module CredStore
15
+ class YamlStore
16
+
17
+ def initialize(location=nil)
18
+ @location = location || File.join(Dir.home, '.flo_creds.yml')
19
+ end
20
+
21
+ # Returns the credentials for the requested provider
22
+ # @param provider_sym [Symbol]
23
+ # @return [Flo::CredStore::Creds]
24
+ #
25
+ def credentials_for(provider_sym)
26
+ Flo::CredStore::Creds.new(full_credentials_hash[provider_sym])
27
+ end
28
+
29
+ private
30
+
31
+ def full_credentials_hash
32
+ @full_credentials_hash ||= YAML.load(File.read(@location)) || {}
33
+ end
34
+ end
35
+ end
36
+ end
data/lib/flo/error.rb ADDED
@@ -0,0 +1,9 @@
1
+ # Copyright © 2017, Salesforce.com, Inc.
2
+ # All Rights Reserved.
3
+ # Licensed under the BSD 3-Clause license.
4
+ # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
+
6
+ module Flo
7
+
8
+ Error = Class.new(StandardError)
9
+ end
@@ -0,0 +1,62 @@
1
+ # Copyright © 2017, Salesforce.com, Inc.
2
+ # All Rights Reserved.
3
+ # Licensed under the BSD 3-Clause license.
4
+ # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
+
6
+ module Flo
7
+ module Provider
8
+ MissingOptionError = Class.new(StandardError)
9
+ OptionDefinition = Struct.new(:default, :required)
10
+
11
+ # @abstract Subclass and use {.option} to declare initialize options
12
+ # A base provider class that all custom providers should inherit from.
13
+ #
14
+ class Base
15
+
16
+ attr_writer :cred_store
17
+
18
+ # Creates an instance of a provider
19
+ # @param opts [Hash] Arbitrary array of options defined by the provider
20
+ # using the {.option} method
21
+ # @raise [MissingOptionError] if a required option is not provided. Error
22
+ # message will state which options are missing.
23
+ #
24
+ def initialize(opts={})
25
+ # @options = allow_whitelisted(opts, @@option_keys)
26
+ @options = {}
27
+ self.class.option_keys.each do |key, definition|
28
+ @options[key] = opts.fetch(key, definition.default)
29
+ end
30
+
31
+ missing_required = self.class.option_keys.select {|_k,v| v.required }.keys - @options.select { |_k,v| !v.nil? }.keys
32
+ unless missing_required.empty?
33
+ raise MissingOptionError.new("#{self.class.name} invoked without required options: #{missing_required.join(' ')}")
34
+ end
35
+ end
36
+
37
+ # Declare an option to be passed in when declaring the provider in the
38
+ # .flo file
39
+ # @param name [Symbol] The name of the option
40
+ # @param default Default value for the option if none is provided
41
+ # @option args [Boolean] :required (false) Whether the option is required.
42
+ # A MissingOptionError will be raised if a provider is instantiated
43
+ # without a required argument
44
+ #
45
+ def self.option(name, default=nil, args={})
46
+ option_keys[name] = OptionDefinition.new(default, args[:required] == true)
47
+ end
48
+
49
+ # Hash of option definitions. Add to this hash using the {.option}
50
+ # method.
51
+ #
52
+ # @return [Hash{Symbol => OptionDefiniton}]
53
+ def self.option_keys
54
+ @option_keys ||= {}
55
+ end
56
+
57
+ private
58
+
59
+ attr_reader :options
60
+ end
61
+ end
62
+ end
@@ -3,16 +3,15 @@
3
3
  # Licensed under the BSD 3-Clause license.
4
4
  # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
5
 
6
+ require 'flo/provider/base'
6
7
  require 'ostruct'
7
8
 
8
9
  module Flo
9
10
  module Provider
10
11
  Response = Struct.new(:success?)
11
- class Developer
12
+ class Developer < Flo::Provider::Base
12
13
 
13
- def initialize(options={})
14
-
15
- end
14
+ option :password, nil, required: false
16
15
 
17
16
  def is_successful(opts={})
18
17
  success = opts[:success].nil? ? true : opts[:success]
@@ -23,9 +22,8 @@ module Flo
23
22
  true
24
23
  end
25
24
 
26
- def echo(opts={})
27
- puts opts.inspect
28
- Flo::Provider::Response.new(true)
25
+ def has_option(opts={})
26
+ Flo::Provider::Response.new(options.include?(opts[:option]))
29
27
  end
30
28
  end
31
29
  end
data/lib/flo/runner.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  # Licensed under the BSD 3-Clause license.
4
4
  # For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
5
5
 
6
- require 'flo'
7
6
  require 'flo/command'
8
7
  require 'flo/command_collection'
9
8
  require 'flo/state'
@@ -48,14 +47,28 @@ module Flo
48
47
  evaluate_file(config_file)
49
48
  end
50
49
 
50
+ # Open and parse any available config files, in the following order:
51
+ # * ENV['FLO_CONFIG_FILE'] # Allows the addition of custom files
52
+ # * ./.flo
53
+ # * ~/.flo
54
+ # See {#load_config_file}
55
+ #
56
+ def load_default_config_files
57
+ [ENV['FLO_CONFIG_FILE'], File.join(Dir.pwd, '.flo'), File.join(Dir.home, '.flo')].compact.each do |file|
58
+ if File.exist?(file)
59
+ self.load_config_file(file)
60
+ end
61
+ end
62
+ end
63
+
51
64
  # Executes the command specified, with the arguments specified
52
65
  # @param command_namespace [Array<Symbol>] An array containing the name of
53
66
  # the command as a symbol, including the namespace. For example, the
54
67
  # command "issue submit" would become [:issue, :submit]
55
- # @param args={} [Hash] Options that will get passed to the command
68
+ # @param args=[] [Array] Options that will get passed to the command
56
69
  #
57
- def execute(command_namespace, args={})
58
- commands[command_namespace].call(args)
70
+ def execute(command_namespace, args=[])
71
+ commands[command_namespace][:command].call(args)
59
72
  end
60
73
 
61
74
  # @api dsl
@@ -76,13 +89,15 @@ module Flo
76
89
  # DSL method: Creates and defines a {Command}, adding it to the command collection.
77
90
  # Definition for the command should happen inside of the required block.
78
91
  # See {Command} for methods available within the block.
79
- # @param command_namespace [Array<Symbol>] Array of symbols representing the
80
- # command including the namespace
81
- # @yield [args*]The block containing the definition for the command.
92
+ # @param command_namespace [String] name of the command
93
+ # @option opts [String] :summary Summary of the command
94
+ # @option opts [String] :description Detailed description of the command
95
+ # @yield [args*] The block containing the definition for the command.
82
96
  # Arguments passed into {#execute} are available within the block
83
97
  #
84
- def register_command(command_namespace, &blk)
85
- commands[command_namespace] = command_class.new(providers: config.providers, &blk)
98
+ def register_command(command_namespace, opts={}, &blk)
99
+ opts[:command] = command_class.new(providers: config.providers, &blk)
100
+ commands[command_namespace] = opts
86
101
  end
87
102
  expose :register_command
88
103