duty 0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b04eb166b84df79f038e4cd1f03181ff7294049
4
+ data.tar.gz: 8cec611a0d0fcbf8ae02de1ea3ed798633fed7e7
5
+ SHA512:
6
+ metadata.gz: 1fd3ce618dcc3c2e631715efcb138558345e7b7b6481e9655443f14c668b4de115f66983239e3cb769cd2ff73c9cec63f543c68e0c2c326a10505af9bf6ecff4
7
+ data.tar.gz: 4b7e91969a5d696d976c3d7ea0739fdbec15e16fef9c89a74f62f7e215a4a468e466419c7f58943406ccd9ba06a280f9fe7139420afc1cb1d392851af52be0d5
data/.duty.yml.sample ADDED
@@ -0,0 +1 @@
1
+ tasks: /path/to/my/project/specific/tasks
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ .duty.yml
3
+ pkg
data/.gitmodules ADDED
File without changes
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ duty
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.3
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.3
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Jan Owiesniak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ [![Build Status](https://travis-ci.org/JanOwiesniak/duty.svg?branch=master)](https://travis-ci.org/JanOwiesniak/duty) [![Inline docs](http://inch-ci.org/github/JanOwiesniak/duty.svg?branch=master)](http://inch-ci.org/github/JanOwiesniak/duty)
2
+
3
+ # Duty
4
+
5
+ Craft.
6
+ Don't battle.
7
+ Do your duty, let me handle the rest.
8
+
9
+ ## Installation
10
+
11
+ ```
12
+ $ gem install duty
13
+ ```
14
+
15
+ ## Add executable to your $PATH
16
+
17
+ ```
18
+ $ export PATH="$PATH:$HOME/path/to/duty/bin"
19
+ ```
20
+ ```
21
+
22
+ ## Add shell completion
23
+
24
+ This gem supports a simple shell completion for
25
+ [Bash](https://www.gnu.org/software/bash/) and [ZSH](http://www.zsh.org).
26
+ To enable this feature load the completion functions:
27
+
28
+ ```
29
+ source duty.completion
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```
35
+ $ duty <task> [<args>]
36
+ ```
37
+
38
+ ## Naming conventions
39
+
40
+ Task names should be a combination of one verb joined with one or more nouns.
41
+
42
+ Examples:
43
+
44
+ * `start-feature`
45
+ * `continue-feature`
46
+
47
+ ## List of official duty plugins
48
+
49
+ * [duty-git](https://github.com/JanOwiesniak/duty-git)
50
+
51
+ ## Extend duty with your own tasks
52
+
53
+ * Create a new `tasks` dir
54
+ * Create one or more duty task files in there
55
+ * Create a .duty file e.g. in your home dir
56
+
57
+ ### How does a basic duty task looks like?
58
+
59
+ path/to/your/new/tasks/my_new_task.rb
60
+
61
+ ```ruby
62
+ require 'duty/tasks/base'
63
+
64
+ module Duty
65
+ module Tasks
66
+ class MyNewTask < Duty::Tasks::Base
67
+ end
68
+ end
69
+ end
70
+ ```
71
+
72
+ ### How does a .duty file looks like?
73
+
74
+ .duty
75
+
76
+ ```
77
+ tasks:
78
+ git: /path/to/my/git/specific/tasks
79
+ projectA: /path/to/my/projectA/specific/tasks
80
+ projectB: /path/to/my/projectB/specific/tasks
81
+ ```
82
+
83
+ ### How to use my own task?
84
+
85
+ Your new task will be immediately available from the CLI.
86
+
87
+ ```
88
+ duty
89
+ ```
90
+
91
+ Fire up the CLI and execute your new task.
92
+ Duty will tell you what you have to do next.
93
+
94
+ ```
95
+ duty <your-task>
96
+ ```
97
+
98
+ ## Contributing
99
+
100
+ 1. [Fork](http://github.com/JanOwiesniak/duty/fork)
101
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
102
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
103
+ 4. Push to the branch (`git push origin my-new-feature`)
104
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'spec'
5
+ t.test_files = FileList['spec/*_spec.rb']
6
+ t.verbose = true
7
+ end
8
+
9
+ task :default => :test
data/bin/duty ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Finds the path to the 'lib' directory of Duty. Follows symlinks, which
4
+ # comes in handy.
5
+ def find_lib_path
6
+ path = __FILE__
7
+ while File.symlink?(path)
8
+ path = File.expand_path(File.readlink(path), File.dirname(path))
9
+ end
10
+ File.join(File.dirname(File.expand_path(path)), '..', 'lib')
11
+ end
12
+
13
+ $LOAD_PATH.unshift(find_lib_path)
14
+
15
+ require 'duty'
16
+
17
+ Duty::CLI.new(ARGV).exec
@@ -0,0 +1,18 @@
1
+ if [ -n "$BASH_VERSION" ]; then
2
+ _duty_complete() {
3
+ COMPREPLY=()
4
+ local word=${COMP_WORDS[COMP_CWORD]}
5
+ local completions=$(duty --cmplt "${word}")
6
+ COMPREPLY=( $completions )
7
+ }
8
+ complete -F _duty_complete duty
9
+ elif [ -n "$ZSH_VERSION" ]; then
10
+ _duty_complete() {
11
+ local word completions
12
+ word="$1"
13
+ completions="$(duty --cmplt "${word}")"
14
+ reply=( "${(ps:\n:)completions}" )
15
+ }
16
+
17
+ compctl -K _duty_complete duty
18
+ fi
data/duty.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "duty/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "duty"
7
+ spec.version = Duty::VERSION
8
+ spec.authors = ["Jan Owiesniak"]
9
+ spec.email = ["owiesniak@mailbox.org"]
10
+
11
+ spec.summary = "Extendable Task Manager"
12
+ spec.description = "Duty provides a CLI for high-level tasks"
13
+ spec.homepage = "https://github.com/JanOwiesniak/duty"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+
20
+ spec.executables = spec.files.grep(%r{^bin\/}) { |f| File.basename(f) }
21
+
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "minitest", "~> 5.8"
26
+ end
data/lib/duty/cli.rb ADDED
@@ -0,0 +1,215 @@
1
+ require 'duty/registry'
2
+ require 'duty/plugins'
3
+ require 'duty/meta'
4
+
5
+ module Duty
6
+ class CLI
7
+ DUTY_CONFIG_FILENAME = '.duty.yml'
8
+ attr_reader :registry
9
+
10
+ def initialize(args)
11
+ @input = Input.new(args)
12
+ @output = Output.new
13
+ @registry = Duty::Registry.load(plugins)
14
+ end
15
+
16
+ def exec
17
+ stdout usage if help?
18
+ stdout completion if completion?
19
+ run_task
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :input, :output
25
+
26
+ def plugins
27
+ Duty::Plugins.load(DUTY_CONFIG_FILENAME)
28
+ end
29
+
30
+ def stdout(string)
31
+ $stdout.puts string
32
+ exit 0
33
+ end
34
+
35
+ def help?
36
+ input.help?
37
+ end
38
+
39
+ def usage
40
+ Duty::Meta::Help.new(self).to_s
41
+ end
42
+
43
+ def completion?
44
+ input.completion?
45
+ end
46
+
47
+ def completion
48
+ Duty::Meta::Completion.new(self, input.drop(1)).to_s
49
+ end
50
+
51
+ def run_task
52
+ begin
53
+ task.run
54
+ rescue NameError => e
55
+ stdout invalid_task(e.message)
56
+ end
57
+ end
58
+
59
+ def task
60
+ input.task_class.new(input.task_input, view)
61
+ end
62
+
63
+ def invalid_task(error_message)
64
+ "duty: `#{input.join(' ')}` is not a duty task. Failed with: #{error_message}"
65
+ end
66
+
67
+ def view
68
+ if verbose?
69
+ VerboseView.new(output)
70
+ else
71
+ View.new(output)
72
+ end
73
+ end
74
+
75
+ def verbose?
76
+ input.verbose?
77
+ end
78
+
79
+ class Input
80
+ def initialize(args)
81
+ @args = [args].flatten
82
+ end
83
+
84
+ def[](index)
85
+ @args[index]
86
+ end
87
+
88
+ def drop(index)
89
+ @args.drop(1)
90
+ end
91
+
92
+ def task_name
93
+ task, *rest = @args
94
+ task
95
+ end
96
+
97
+ def task_class
98
+ name = task_name.split('-').collect(&:capitalize).join
99
+ Object.const_get("Duty::Tasks::#{name}")
100
+ end
101
+
102
+ def task_input
103
+ task, *rest = @args
104
+ rest
105
+ end
106
+
107
+ def join(seperator='')
108
+ @args.join(seperator)
109
+ end
110
+
111
+ def verbose?
112
+ @args.include?('-v') || @args.include?('--verbose')
113
+ end
114
+
115
+ def completion?
116
+ @args.first == '--cmplt'
117
+ end
118
+
119
+ def help?
120
+ @args.empty? || @args == %w(-h) || @args == %w(--help)
121
+ end
122
+ end
123
+
124
+ class Output
125
+ def print(*args)
126
+ $stdout.puts(*args)
127
+ end
128
+
129
+ def error(*args)
130
+ $stderr.puts(*args)
131
+ end
132
+ end
133
+
134
+ class View
135
+ def initialize(output)
136
+ @output = output
137
+ end
138
+
139
+ def task_explain(task)
140
+ task_class = task.class
141
+ description = task_class.description
142
+ usage = task_class.usage
143
+
144
+ @output.print(description)
145
+ @output.print(usage)
146
+ end
147
+
148
+ def task_success(task)
149
+ task_name = task.class.name
150
+ success("#{task_name} task executed")
151
+ end
152
+
153
+ def task_failure(task)
154
+ task_name = task.class.name
155
+ failure("#{task_name} task aborted")
156
+ end
157
+
158
+ def command_success(command)
159
+ description = command.description
160
+ success(description)
161
+ end
162
+
163
+ def command_failure(command)
164
+ description = command.description
165
+ failure(description)
166
+ end
167
+
168
+ private
169
+
170
+ def success(msg)
171
+ @output.print([check_mark, msg].join(' '))
172
+ end
173
+
174
+ def failure(msg)
175
+ @output.error([cross_mark, msg].join(' '))
176
+ end
177
+
178
+ def cross_mark
179
+ unicode("2715")
180
+ end
181
+
182
+ def check_mark
183
+ unicode("2713")
184
+ end
185
+
186
+ def unicode(code)
187
+ ["0x#{code}".hex].pack('U')
188
+ end
189
+ end
190
+
191
+ class VerboseView < View
192
+ def command_success(command)
193
+ success(command_msg(command))
194
+ end
195
+
196
+ def command_failure(command)
197
+ failure(command_msg(command))
198
+ end
199
+
200
+ private
201
+
202
+ def command_msg(command)
203
+ [command.description, command_logs(command)].join(' ')
204
+ end
205
+
206
+ def command_logs(command)
207
+ elements = command.logger.flatten
208
+
209
+ if elements.any?
210
+ ["|>", elements.join(' | ')].join(' ')
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,41 @@
1
+ module Duty
2
+ module Meta
3
+ class Completion
4
+ def initialize(cli, args)
5
+ @registry = cli.registry
6
+ @humanizer = Humanizer.new
7
+ @input = args.join(" ").downcase
8
+ end
9
+
10
+ def to_s
11
+ possible_completions
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :registry, :humanizer
17
+
18
+ def possible_completions
19
+ matching_tasks.join("\n")
20
+ end
21
+
22
+ def matching_tasks
23
+ humanized_tasks.select do |cmd|
24
+ cmd.start_with?(@input)
25
+ end
26
+ end
27
+
28
+ def humanized_tasks
29
+ registry.plugins.map do |plugin|
30
+ tasks_for(plugin)
31
+ end.flatten
32
+ end
33
+
34
+ def tasks_for(plugin)
35
+ plugin.tasks.map do |task_class|
36
+ humanizer.task(task_class)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ module Duty
2
+ module Meta
3
+ class Help
4
+ def initialize(cli)
5
+ @registry = cli.registry
6
+ @humanizer = Humanizer.new
7
+ end
8
+
9
+ def to_s
10
+ usage
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :registry, :humanizer
16
+
17
+ def usage
18
+ msg = <<-EOF
19
+ Usage: duty <task> [<args>]
20
+
21
+ Tasks:
22
+
23
+ #{plugins}
24
+ EOF
25
+ end
26
+
27
+ def plugins
28
+ registry.plugins.map do |plugin|
29
+ [namespace_for(plugin), tasks_for(plugin)].join("\n")
30
+ end.join("\n")
31
+ end
32
+
33
+ def namespace_for(plugin)
34
+ "[" + plugin.namespace + "]"
35
+ end
36
+
37
+ def tasks_for(plugin)
38
+ plugin.tasks.map do |task_class|
39
+ [" • ", humanizer.task(task_class).ljust(20), task_class.description].join
40
+ end.join("\n")
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ require 'duty/registry'
2
+
3
+ module Duty
4
+ module Meta
5
+ class Humanizer
6
+ def task(klass)
7
+ klass.to_s.
8
+ gsub(/([A-Z])/, '-\1').
9
+ split('-').
10
+ reject(&:empty?).
11
+ map(&:downcase).
12
+ join('-').
13
+ split('::').
14
+ last.
15
+ gsub(/^-/,'')
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/duty/meta.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'duty/meta/completion'
2
+ require 'duty/meta/help'
3
+ require 'duty/meta/humanizer'
@@ -0,0 +1,50 @@
1
+ require 'duty/tasks'
2
+ require 'yaml'
3
+
4
+ module Duty
5
+ module Plugins
6
+ def self.load(filename)
7
+ if File.exists?(filename)
8
+ duty_config = YAML.load(File.read(filename))
9
+ tasks = duty_config["tasks"]
10
+ tasks.map do |namespace, task_dir|
11
+ Plugin.new(namespace, task_dir) if Dir.exists?(task_dir)
12
+ end
13
+ end
14
+ end
15
+
16
+ class Plugin
17
+ TASK_NAMESPACE = Duty::Tasks
18
+ def initialize(namespace, task_dir)
19
+ @namespace = namespace
20
+ @task_dir = task_dir
21
+ end
22
+
23
+ def namespace
24
+ @namespace
25
+ end
26
+
27
+ def require_tasks
28
+ task_files = File.expand_path(File.join(@task_dir, "*.rb"))
29
+ Dir[task_files].each do |path|
30
+ require path.gsub(/(\.rb)$/, '')
31
+ end
32
+ end
33
+
34
+ def tasks
35
+ task_names = TASK_NAMESPACE.constants - [:Base]
36
+ task_names.reduce([]) do |task_classes, task_name|
37
+ task_class = TASK_NAMESPACE.const_get(task_name)
38
+ task_classes << task_class if valid?(task_class)
39
+ task_classes
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def valid?(task_class)
46
+ task_class.superclass == TASK_NAMESPACE::Base
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,16 @@
1
+ module Duty
2
+ class Registry
3
+ def self.load(plugins = [])
4
+ new(plugins).tap {|registry| registry.require_tasks }
5
+ end
6
+
7
+ attr_reader :plugins
8
+ def initialize(plugins)
9
+ @plugins = plugins
10
+ end
11
+
12
+ def require_tasks
13
+ plugins.each {|plugin| plugin.require_tasks }
14
+ end
15
+ end
16
+ end
data/lib/duty/tasks.rb ADDED
@@ -0,0 +1,205 @@
1
+ module Duty
2
+ module Tasks
3
+ class Base
4
+ ExecutionError = Class.new(RuntimeError)
5
+
6
+ def initialize(arguments, view)
7
+ @arguments = arguments
8
+ @view = view
9
+ @parallel = []
10
+ end
11
+
12
+ def run
13
+ if !valid?
14
+ task_explain
15
+ else
16
+ begin
17
+ execute_in_thread
18
+ task_success
19
+ rescue ExecutionError
20
+ task_failure
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.name
26
+ self.to_s.split('::').last
27
+ end
28
+
29
+ def self.description
30
+ "TODO: Describe your task by overwriting `self.description`"
31
+ end
32
+
33
+ def self.usage
34
+ "TODO: Explain your task by overwriting `self.usage`"
35
+ end
36
+
37
+ def execute
38
+ ruby(Proc.new{},'Describe your task')
39
+ ruby(Proc.new{},'Explain your task')
40
+ ruby(Proc.new{ raise ExecutionError.new },'TODO: Implement your task by overwriting `execute`')
41
+ end
42
+
43
+ private
44
+
45
+ def execute_in_thread
46
+ Thread.new do
47
+ execute
48
+ @parallel.each {|thread| thread.join }
49
+ end.join
50
+ end
51
+
52
+ def valid?
53
+ !todo?(self.class.description) && !todo?(self.class.usage)
54
+ end
55
+
56
+ def todo?(string)
57
+ string.match(/TODO/)
58
+ end
59
+
60
+ def task_explain
61
+ @view.task_explain(self)
62
+ end
63
+
64
+ def task_success
65
+ @view.task_success(self)
66
+ end
67
+
68
+ def task_failure
69
+ @view.task_failure(self)
70
+ end
71
+
72
+ def command_success(command)
73
+ @view.command_success(command)
74
+ end
75
+
76
+ def command_failure(command)
77
+ @view.command_failure(command)
78
+ end
79
+
80
+ def parallel(&blk)
81
+ @parallel << Thread.new(&blk)
82
+ end
83
+
84
+ def ruby(desc = 'Unknown ruby command', &blk)
85
+ handle_errors(Ruby.run(desc, blk))
86
+ end
87
+
88
+ def sh(desc = 'Unknown shell command', &blk)
89
+ handle_errors(Shell.run(desc, blk))
90
+ end
91
+
92
+ def handle_errors(command)
93
+ if command.success?
94
+ command_success(command)
95
+ else
96
+ command_failure(command)
97
+ raise ExecutionError.new
98
+ end
99
+ end
100
+
101
+ class Command
102
+ def initialize(description, callable)
103
+ @description = description
104
+ @callable = callable
105
+ @success = false
106
+ @error = nil
107
+ @logger = []
108
+ end
109
+
110
+ def self.run(description, callable)
111
+ new(description, callable).tap {|command| command.execute}
112
+ end
113
+
114
+ def success?
115
+ @success
116
+ end
117
+
118
+ def description
119
+ @description
120
+ end
121
+
122
+ def logger
123
+ @logger
124
+ end
125
+
126
+ def error
127
+ @error
128
+ end
129
+ end
130
+
131
+ class Ruby < Command
132
+ def execute
133
+ begin
134
+ @callable.call
135
+ @success = true
136
+ rescue Exception => e
137
+ @error = "ERROR: #{e.inspect}"
138
+ ensure
139
+ @logger << summary
140
+ @logger << error
141
+ end
142
+ end
143
+
144
+ private
145
+
146
+ def summary
147
+ "[RUBY] #{@callable.inspect}"
148
+ end
149
+ end
150
+
151
+ class Shell < Command
152
+ require 'open3'
153
+ def execute
154
+ if !cmd
155
+ @success = true
156
+ return
157
+ end
158
+
159
+ begin
160
+ @stdout, @stderr, @status = Open3.capture3(cmd)
161
+ @success = true if status.success?
162
+ rescue Exception => e
163
+ @error = "ERROR: #{e.inspect}"
164
+ ensure
165
+ @logger << summary
166
+ @logger << error
167
+ end
168
+ end
169
+
170
+ private
171
+
172
+ def summary
173
+ [
174
+ "[SHELL]",
175
+ "COMMAND: #{cmd}",
176
+ "DIR: #{dir}",
177
+ "STDOUT: #{stdout}",
178
+ "STDERR: #{stderr}",
179
+ "STATUS: #{status}"
180
+ ]
181
+ end
182
+
183
+ def stdout
184
+ @stdout
185
+ end
186
+
187
+ def stderr
188
+ @stderr
189
+ end
190
+
191
+ def status
192
+ @status
193
+ end
194
+
195
+ def cmd
196
+ @cmd ||= @callable.call
197
+ end
198
+
199
+ def dir
200
+ Dir.pwd
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,3 @@
1
+ module Duty
2
+ VERSION = "0.1.0"
3
+ end
data/lib/duty.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'duty/cli'
2
+ require 'duty/tasks'
3
+ require 'duty/version'
4
+
5
+ module Duty
6
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: duty
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jan Owiesniak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '10.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.8'
41
+ description: Duty provides a CLI for high-level tasks
42
+ email:
43
+ - owiesniak@mailbox.org
44
+ executables:
45
+ - duty
46
+ - duty.completion
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - ".duty.yml.sample"
51
+ - ".gitignore"
52
+ - ".gitmodules"
53
+ - ".ruby-gemset"
54
+ - ".ruby-version"
55
+ - ".travis.yml"
56
+ - Gemfile
57
+ - LICENSE
58
+ - README.md
59
+ - Rakefile
60
+ - bin/duty
61
+ - bin/duty.completion
62
+ - duty.gemspec
63
+ - lib/duty.rb
64
+ - lib/duty/cli.rb
65
+ - lib/duty/meta.rb
66
+ - lib/duty/meta/completion.rb
67
+ - lib/duty/meta/help.rb
68
+ - lib/duty/meta/humanizer.rb
69
+ - lib/duty/plugins.rb
70
+ - lib/duty/registry.rb
71
+ - lib/duty/tasks.rb
72
+ - lib/duty/version.rb
73
+ homepage: https://github.com/JanOwiesniak/duty
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.4.8
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Extendable Task Manager
97
+ test_files: []