todone 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rvmrc +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +39 -0
- data/LICENSE.txt +20 -0
- data/README.md +37 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/bin/todone +77 -0
- data/git_config_read_test +12 -0
- data/lib/todone/config.rb +73 -0
- data/lib/todone/consts.rb +16 -0
- data/lib/todone/pivotal_puller.rb +24 -0
- data/lib/todone/views.rb +61 -0
- data/lib/todone.rb +131 -0
- data/spec/helper.rb +113 -0
- data/spec/libs/config_spec.rb +74 -0
- data/spec/libs/message_processor_spec.rb +169 -0
- data/spec/libs/pivotal_puller_spec.rb +47 -0
- metadata +168 -0
data/.document
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm ruby-1.9.2-head@rails3
|
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
|
4
|
+
gem "commander","4.0.3"
|
5
|
+
gem "crack", "0.1.8"
|
6
|
+
gem "httparty", "0.7.4"
|
7
|
+
|
8
|
+
# Add dependencies to develop your gem here.
|
9
|
+
group :development do
|
10
|
+
gem "rspec"
|
11
|
+
gem "mocha","0.9.12"
|
12
|
+
gem "bundler", "~> 1.0.0"
|
13
|
+
gem "jeweler", "~> 1.5.2"
|
14
|
+
gem "rcov", ">= 0"
|
15
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
commander (4.0.3)
|
5
|
+
highline (>= 1.5.0)
|
6
|
+
crack (0.1.8)
|
7
|
+
diff-lcs (1.1.2)
|
8
|
+
git (1.2.5)
|
9
|
+
highline (1.6.1)
|
10
|
+
httparty (0.7.4)
|
11
|
+
crack (= 0.1.8)
|
12
|
+
jeweler (1.5.2)
|
13
|
+
bundler (~> 1.0.0)
|
14
|
+
git (>= 1.2.5)
|
15
|
+
rake
|
16
|
+
mocha (0.9.12)
|
17
|
+
rake (0.8.7)
|
18
|
+
rcov (0.9.9)
|
19
|
+
rspec (2.5.0)
|
20
|
+
rspec-core (~> 2.5.0)
|
21
|
+
rspec-expectations (~> 2.5.0)
|
22
|
+
rspec-mocks (~> 2.5.0)
|
23
|
+
rspec-core (2.5.1)
|
24
|
+
rspec-expectations (2.5.0)
|
25
|
+
diff-lcs (~> 1.1.2)
|
26
|
+
rspec-mocks (2.5.0)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
bundler (~> 1.0.0)
|
33
|
+
commander (= 4.0.3)
|
34
|
+
crack (= 0.1.8)
|
35
|
+
httparty (= 0.7.4)
|
36
|
+
jeweler (~> 1.5.2)
|
37
|
+
mocha (= 0.9.12)
|
38
|
+
rcov
|
39
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 A Flores
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
todone
|
2
|
+
====
|
3
|
+
|
4
|
+
ToDone is a command-line tool that gives you the ability to better integrate git with your project manager(which is currently only allowed to be pivotal tracker). Also, Todone is, somewhat ironically, a work in progress.
|
5
|
+
|
6
|
+
Requirements
|
7
|
+
------------
|
8
|
+
|
9
|
+
* Ruby = 1.9.2
|
10
|
+
* Rubygems = 1.3.7
|
11
|
+
|
12
|
+
Installation & Setup
|
13
|
+
--------------------
|
14
|
+
|
15
|
+
$ gem install todone
|
16
|
+
$ cd git_pj_directory
|
17
|
+
$ todone add_project
|
18
|
+
|
19
|
+
todone add_project
|
20
|
+
----------------
|
21
|
+
|
22
|
+
adds a hook for pre-commit that pulls in open stories from pivotal tracker in order to standardize the user's commit messages
|
23
|
+
|
24
|
+
todone users
|
25
|
+
--------
|
26
|
+
|
27
|
+
displays who todone will filter by when grabbing information via pivotal
|
28
|
+
|
29
|
+
todone tickets
|
30
|
+
--------------------------
|
31
|
+
|
32
|
+
grabs all of the tickets/chores/bugs from pivotal tracker that are open or have been modified for the current day.
|
33
|
+
|
34
|
+
todone daily_update
|
35
|
+
-----------------
|
36
|
+
|
37
|
+
prints out a template for the daily update a user will have
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "todone"
|
16
|
+
gem.homepage = "http://github.com/unflores/todone"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Todone is a command-line tool that gives you the ability to better integrate git with your pivotal project.}
|
19
|
+
gem.description = %Q{Toone is a command-line tool that gives you the ability to better integrate git with your project manager(which is currently only allowed to be pivotal tracker). Todone will keep track of the tickets your working on so you don't have to.}
|
20
|
+
gem.email = "ctrl4ltdeleteme@gmail.com"
|
21
|
+
gem.authors = ["A Flores"]
|
22
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core/rake_task'
|
29
|
+
RSpec::Core::RakeTask.new do |t|
|
30
|
+
t.rspec_opts = ["--color", "--format documentation", "--fail-fast"]
|
31
|
+
t.pattern = ['spec/libs/*.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'rcov/rcovtask'
|
35
|
+
Rcov::RcovTask.new do |test|
|
36
|
+
test.libs << 'spec'
|
37
|
+
test.pattern = 'spec/libs/*_spec.rb'
|
38
|
+
test.verbose = true
|
39
|
+
end
|
40
|
+
|
41
|
+
task :default => :test
|
42
|
+
|
43
|
+
require 'rake/rdoctask'
|
44
|
+
Rake::RDocTask.new do |rdoc|
|
45
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
46
|
+
|
47
|
+
rdoc.rdoc_dir = 'rdoc'
|
48
|
+
rdoc.title = "todone #{version}"
|
49
|
+
rdoc.rdoc_files.include('README*')
|
50
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
51
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.2
|
data/bin/todone
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
|
4
|
+
%w(rubygems commander/import todone).each{|requirement| require requirement}
|
5
|
+
|
6
|
+
version_file = File.join(File.dirname(__FILE__), '..', 'VERSION')
|
7
|
+
|
8
|
+
program :name, 'Todone'
|
9
|
+
program :description, 'a tool for better communication'
|
10
|
+
program :version, File.read(version_file)
|
11
|
+
program :help_formatter, Commander::HelpFormatter::TerminalCompact
|
12
|
+
default_command :help
|
13
|
+
|
14
|
+
def ensure_config_exists!
|
15
|
+
if Todone::MessageProcessor.needs_init?
|
16
|
+
setup = {}
|
17
|
+
setup[:api_key] = ask("API Key: ") {|q| q.echo = true}
|
18
|
+
setup[:owner] = ask("Username: "){|q| q.echo = true}
|
19
|
+
Todone::MessageProcessor.init setup
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
command :add_project do |cmd|
|
24
|
+
cmd.syntax = "todone #{cmd.name}"
|
25
|
+
cmd.summary = "Adds the current project to the config file"
|
26
|
+
cmd.description = "#{cmd.summary}"
|
27
|
+
cmd.when_called do |args, options|
|
28
|
+
|
29
|
+
ensure_config_exists!
|
30
|
+
|
31
|
+
options = {}
|
32
|
+
options[:id] = ask("Project id: ") {|q| q.echo = true}
|
33
|
+
options[:users] = ask("Other users: "){|q| q.echo = true}
|
34
|
+
mp = Todone::MessageProcessor.new()
|
35
|
+
puts mp.add_project(options)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
command :users do |cmd|
|
40
|
+
cmd.syntax = "todone #{cmd.name}"
|
41
|
+
cmd.summary = "display the users who the tickets will be filtered by"
|
42
|
+
cmd.description = "#{cmd.summary}"
|
43
|
+
cmd.when_called do |args, options|
|
44
|
+
#
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
command :daily_update do |cmd|
|
49
|
+
cmd.syntax = "todone #{cmd.name}"
|
50
|
+
cmd.summary = "print out an email template with"
|
51
|
+
cmd.description = "#{cmd.summary}"
|
52
|
+
cmd.when_called do |args, options|
|
53
|
+
ensure_config_exists!
|
54
|
+
#
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
command :tickets do |cmd|
|
59
|
+
cmd.syntax = "todone #{cmd.name} [options]"
|
60
|
+
cmd.summary = "print out a list of open tickets"
|
61
|
+
cmd.description = "#{cmd.summary}"
|
62
|
+
cmd.option "-s","--started", "All tickets currently started"
|
63
|
+
cmd.option "-d","--delivered", "All tickets delivered today"
|
64
|
+
cmd.option "-a","--accepted", "All tickets accepted today"
|
65
|
+
cmd.option "-w", "--write-file", "Write to file"
|
66
|
+
cmd.option "--file [FILE]", String ,"File to write to. Default is .git/COMMIT_EDITMSG"
|
67
|
+
cmd.when_called do |args, options|
|
68
|
+
ensure_config_exists!
|
69
|
+
project_id = args.shift
|
70
|
+
mp = Todone::MessageProcessor.new(:project_id => project_id)
|
71
|
+
if options.write_file.nil?
|
72
|
+
puts mp.view_tickets
|
73
|
+
else
|
74
|
+
mp.write_tickets :file => options.file
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
project_string = ''
|
2
|
+
found = nil
|
3
|
+
File.open('.git/config') do |file|
|
4
|
+
file.each_line do |line|
|
5
|
+
found ||= line.slice('[pivotal]')
|
6
|
+
project_string = line.tr(" \t\n",'') unless found.nil? or (line.slice('[pivotal]') and found)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
return nil if project_string.blank?
|
11
|
+
|
12
|
+
project_string.split('=').last
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# @see http://mjijackson.com/2010/02/flexible-ruby-config-objects
|
2
|
+
# @author Michael Jackson
|
3
|
+
#
|
4
|
+
# config = Config.new
|
5
|
+
# config.database = 'database_name'
|
6
|
+
# config.username = 'user'
|
7
|
+
# config.db_hosts = {
|
8
|
+
# 'sj' => 'sanjose.example.com',
|
9
|
+
# 'ny' => 'newyork.example.com'
|
10
|
+
# }
|
11
|
+
#
|
12
|
+
# config.username # "user"
|
13
|
+
# config.db_hosts.ny # "newyork.example.com"
|
14
|
+
module Todone
|
15
|
+
class Config
|
16
|
+
|
17
|
+
class << self
|
18
|
+
# @see Todone::Consts:CONFIG_FILE
|
19
|
+
# @param [String] dir The directory to look in for the file specified by {Todone::Consts::CONFIG_FILE}
|
20
|
+
# @return [Todone::Config] The populated {Config} instance
|
21
|
+
def load_config dir
|
22
|
+
require 'yaml'
|
23
|
+
data = YAML.load(File.open(File.join(dir, Todone::Consts::CONFIG_FILE)).read)
|
24
|
+
Todone::Config.new data
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def save dir
|
29
|
+
File.open(File.join(dir, Todone::Consts::CONFIG_FILE), 'w') do |f|
|
30
|
+
f.write( @data.to_hash.to_yaml )
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(data={})
|
35
|
+
@data = {}
|
36
|
+
update!(data)
|
37
|
+
end
|
38
|
+
|
39
|
+
def update!(data)
|
40
|
+
data.each do |key, value|
|
41
|
+
self[key] = value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def [](key)
|
46
|
+
@data[key.to_sym]
|
47
|
+
end
|
48
|
+
|
49
|
+
def []=(key, value)
|
50
|
+
if value.class == Hash
|
51
|
+
@data[key.to_sym] = Config.new(value)
|
52
|
+
else
|
53
|
+
@data[key.to_sym] = value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_hash
|
58
|
+
hash = {}
|
59
|
+
@data.each do |key,value|
|
60
|
+
hash[key] = value.class == Config ? value.to_hash : value
|
61
|
+
end
|
62
|
+
hash
|
63
|
+
end
|
64
|
+
|
65
|
+
def method_missing(sym, *args)
|
66
|
+
if sym.to_s =~ /(.+)=$/
|
67
|
+
self[$1] = args.first
|
68
|
+
else
|
69
|
+
self[sym]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Todone
|
2
|
+
##
|
3
|
+
# Simple container module for constants.
|
4
|
+
#
|
5
|
+
# @author A Flores
|
6
|
+
module Consts
|
7
|
+
## Name of the general (defaults) config file
|
8
|
+
CONFIG_FILE = 'config.yml'
|
9
|
+
## Default configuaration storage directory
|
10
|
+
CONFIG_DIR = File.join(ENV['HOME'], '.todone')
|
11
|
+
## Default general (defaults) config file location
|
12
|
+
CONFIG = File.join(CONFIG_DIR, CONFIG_FILE)
|
13
|
+
## where the hook file is
|
14
|
+
HOOK_FILE = File.join('.git','hooks','pre-commit')
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'cgi'
|
3
|
+
module Todone
|
4
|
+
class PivotalPuller
|
5
|
+
include HTTParty
|
6
|
+
base_uri 'www.pivotaltracker.com'
|
7
|
+
|
8
|
+
|
9
|
+
def initialize opts
|
10
|
+
@project_id = opts[:project_id]
|
11
|
+
Todone::PivotalPuller.headers 'X-TrackerToken' => opts[:tracker_token]
|
12
|
+
end
|
13
|
+
|
14
|
+
def pull_stories state
|
15
|
+
return { "error" => "invalid_state" } unless %w(started unstarted accepted delivered unscheduled).include? state
|
16
|
+
filter = CGI.escape("state:#{state}")
|
17
|
+
PivotalPuller.get("/services/v3/projects/#{@project_id}/stories?filter=#{filter}")['stories'] || []
|
18
|
+
rescue
|
19
|
+
return { "error" => "api_problem" }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
data/lib/todone/views.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module Todone
|
2
|
+
module Views
|
3
|
+
|
4
|
+
def missing_project
|
5
|
+
"Error: Missing project id or users."
|
6
|
+
end
|
7
|
+
|
8
|
+
def missing_hooks_dir data
|
9
|
+
"Couldn't find the .git dir.\n" +
|
10
|
+
"Go to your project directory and type the following:\n" +
|
11
|
+
"echo 'todone tickets #{data[:project][:id]} -m' > .git/hooks/pre-commit\n" +
|
12
|
+
"chmod 751 #{Todone::Consts::HOOK_FILE}\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
def missing_project_id
|
16
|
+
"Error: No project id"
|
17
|
+
end
|
18
|
+
|
19
|
+
def exists_pre_commit_hook data
|
20
|
+
"It looks like you're already using your pre-commit hook.\n" +
|
21
|
+
"I was planning on putting something like the following in there:\n" +
|
22
|
+
"todone tickets #{data[:project_id]} -m"
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def updated_pre_commit_hook
|
27
|
+
"Your pre-commit hook has been updated."
|
28
|
+
end
|
29
|
+
|
30
|
+
def show_pivotal_stories data
|
31
|
+
#TODO: merge post-commit into precommit
|
32
|
+
#TODO: resque from getaddrinfo: nodename nor servname provided, or not known (SocketError)
|
33
|
+
=begin def last_msg
|
34
|
+
last_commit = `git log -n1`.split("\n")
|
35
|
+
3.times{ last_commit.shift }
|
36
|
+
last_commit_msg = "#\n#==================Last Commit===============\n"
|
37
|
+
last_commit_msg << last_commit.collect{|line| "##{line}"}.join("\n")+"\n"
|
38
|
+
end
|
39
|
+
=end
|
40
|
+
pre_commit_msg = "#==================Open Tickets================\n"
|
41
|
+
unless data[:stories].nil?
|
42
|
+
data[:stories].each do |story|
|
43
|
+
pre_commit_msg << "#[#{story['id']}] #{story['name']}\n"
|
44
|
+
end
|
45
|
+
pre_commit_msg
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def missing_write_file data
|
50
|
+
"The file you are trying to write to '#{data[:file]}' does not exist"
|
51
|
+
end
|
52
|
+
|
53
|
+
def missing_view data
|
54
|
+
"The method: #{data[:method]} does not currently have a view associated with it."
|
55
|
+
end
|
56
|
+
|
57
|
+
def api_problem data
|
58
|
+
"There was a problem connecting to the PivotalTracker API."
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/todone.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'todone')
|
2
|
+
|
3
|
+
%w(cgi pivotal_puller config consts views yaml fileutils).each{|requirement| require requirement}
|
4
|
+
|
5
|
+
module Todone
|
6
|
+
class MessageProcessor
|
7
|
+
attr :config
|
8
|
+
attr_writer :config_dir
|
9
|
+
include Todone::Consts
|
10
|
+
include Todone::Views
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def needs_init? dir = Todone::Consts::CONFIG_DIR
|
14
|
+
not File.exists? File.join(dir, Todone::Consts::CONFIG_FILE)
|
15
|
+
end
|
16
|
+
|
17
|
+
def init options
|
18
|
+
return if options[:owner].nil? or options[:api_key].nil?
|
19
|
+
dir = options.delete(:dir) || Todone::Consts::CONFIG_DIR
|
20
|
+
conf_file = File.join(dir, Todone::Consts::CONFIG_FILE)
|
21
|
+
|
22
|
+
FileUtils.mkdir_p dir unless File.exists? dir
|
23
|
+
unless File.exists? conf_file
|
24
|
+
File.open(conf_file, 'w') do |f|
|
25
|
+
YAML.dump({
|
26
|
+
:owner => options[:owner],
|
27
|
+
:api_key => options[:api_key]
|
28
|
+
}, f)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def load_project_id
|
35
|
+
File.open(Todone::MessageProcessor.git_config) do |file|
|
36
|
+
file.each_line do |line|
|
37
|
+
return file.gets.tr("\s\t\n",'').split('=').last if line.slice('[pivotal]')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
return nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def commit_msg_file
|
44
|
+
File.join(git_dir,'COMMIT_EDITMSG')
|
45
|
+
end
|
46
|
+
|
47
|
+
def git_dir
|
48
|
+
if Dir.getwd.split('/').last == 'hooks' then '..'
|
49
|
+
elsif Dir.exists? '.git' then '.git'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def git_config; File.join(git_dir,'config') end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def initialize opts = {}
|
58
|
+
self.config_dir = opts[:config_dir]
|
59
|
+
project_id = opts[:project_id] || Todone::MessageProcessor.load_project_id
|
60
|
+
@pp = Todone::PivotalPuller.new(:project_id => project_id, :tracker_token => config.api_key) if project_id
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_project project
|
64
|
+
return 'missing_project' if project.nil? or project[:id].nil? or project[:users].nil?
|
65
|
+
save_project_id project[:id]
|
66
|
+
config[project[:id]] = project[:users].split(',')
|
67
|
+
config.save config_dir
|
68
|
+
return ['missing_hooks_dir', {:project => project}] unless File.exists? File.join('.git','hooks')
|
69
|
+
|
70
|
+
return self.add_hook project[:id]
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_hook project_id
|
74
|
+
if File.exists? Todone::Consts::HOOK_FILE
|
75
|
+
return ['exists_pre_commit_hook',{:project_id => project_id}]
|
76
|
+
else
|
77
|
+
File.open(Todone::Consts::HOOK_FILE,'w') do |f|
|
78
|
+
f.write("todone tickets #{project_id} -m")
|
79
|
+
end
|
80
|
+
FileUtils.chmod 0751, Todone::Consts::HOOK_FILE
|
81
|
+
return "pre_commit_hook_updated"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def save_project_id project_id
|
86
|
+
`git config -f .git/config pivotal.project-id #{project_id}`
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def config
|
91
|
+
@config ||= Todone::Config.load_config self.config_dir
|
92
|
+
end
|
93
|
+
|
94
|
+
def config_dir
|
95
|
+
(@config_dir.nil? && Todone::Consts::CONFIG_DIR) || @config_dir
|
96
|
+
end
|
97
|
+
|
98
|
+
def tickets
|
99
|
+
return ["missing_project_id"] if @pp.nil?
|
100
|
+
api_data = @pp.pull_stories("started")
|
101
|
+
if api_data.class == Hash
|
102
|
+
api_data.delete("error")
|
103
|
+
else
|
104
|
+
["show_pivotal_stories", :stories => api_data]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def write_tickets opts = {}
|
109
|
+
file = opts[:file] || Todone::MessageProcessor.commit_msg_file
|
110
|
+
if File.exists? file
|
111
|
+
File.open(file, 'r+') do |f|
|
112
|
+
original_message = f.read
|
113
|
+
f.pos = 0
|
114
|
+
f.write( view_tickets + original_message )
|
115
|
+
end
|
116
|
+
else
|
117
|
+
puts missing_write_file( :file => file )
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
def method_missing(method_id, *args)
|
123
|
+
super unless match = /view_(.*)/.match(method_id.to_s) and Todone::MessageProcessor.method_defined?(match[1])
|
124
|
+
method = match[1]
|
125
|
+
view, data = self.send(method, *args)
|
126
|
+
return self.send('missing_view',:method=> method) unless Todone::Views.method_defined? view
|
127
|
+
|
128
|
+
self.send(view, data)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'yaml'
|
4
|
+
require 'mocha'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.mock_with :mocha
|
15
|
+
end
|
16
|
+
|
17
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '../..', 'lib'))
|
18
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
19
|
+
|
20
|
+
require 'todone'
|
21
|
+
module FSHelp
|
22
|
+
TMP_DIR = '/tmp'
|
23
|
+
CONFIG_DIR = File.join(TMP_DIR, '.todone_config')
|
24
|
+
ABS_CONFIG_FILE = File.join(CONFIG_DIR, Todone::Consts::CONFIG_FILE)
|
25
|
+
|
26
|
+
def clean_test_config!
|
27
|
+
%x(rm -rf #{CONFIG_DIR}) if File.exists? CONFIG_DIR
|
28
|
+
end
|
29
|
+
|
30
|
+
def dummy_config
|
31
|
+
{:owner => 'name',:api_key => 'alkjlkjlkjfd512452354'}
|
32
|
+
end
|
33
|
+
|
34
|
+
def ensure_fresh_config!
|
35
|
+
clean_test_config!
|
36
|
+
%x(mkdir -p #{CONFIG_DIR}) unless File.exists? CONFIG_DIR
|
37
|
+
|
38
|
+
File.open(ABS_CONFIG_FILE, 'w') {|f| f.write(dummy_config.to_yaml) }
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
include FSHelp
|
43
|
+
|
44
|
+
module PivotStories
|
45
|
+
|
46
|
+
accepted = {
|
47
|
+
"id"=>10622339,
|
48
|
+
"project_id"=>232039,
|
49
|
+
"story_type"=>"feature",
|
50
|
+
"url"=>"http://www.pivotaltracker.com/story/show/10622339",
|
51
|
+
"estimate"=>1,
|
52
|
+
"current_state"=>"accepted",
|
53
|
+
"description"=>"specifically the .git hooks. I'm leaving off the config settings for now",
|
54
|
+
"name"=>"remove the file manipulation in the tests",
|
55
|
+
"requested_by"=>"Austin Flores",
|
56
|
+
"owned_by"=>"Austin Flores",
|
57
|
+
"created_at"=>"2011-03-02 06:38:25 UTC",
|
58
|
+
"updated_at"=>"2011-03-14 01:43:01 UTC",
|
59
|
+
"accepted_at"=>"2011-03-14 01:43:01 UTC"
|
60
|
+
}
|
61
|
+
|
62
|
+
unscheduled = {
|
63
|
+
"id"=>9958691,
|
64
|
+
"project_id"=>232039,
|
65
|
+
"story_type"=>"feature",
|
66
|
+
"url"=>"http://www.pivotaltracker.com/story/show/9958691",
|
67
|
+
"estimate"=>1,
|
68
|
+
"current_state"=>"unscheduled",
|
69
|
+
"description"=>"returns the tickets/chores/bugs from pivotal tracker that have been completed/started for the current day.\n",
|
70
|
+
"name"=>"PivotalPuller grabs the day_stats from pivotal",
|
71
|
+
"requested_by"=>"Austin Flores",
|
72
|
+
"created_at"=>"2011-02-14 06:49:52 UTC",
|
73
|
+
"updated_at"=>"2011-02-14 06:50:17 UTC"
|
74
|
+
}
|
75
|
+
|
76
|
+
unstarted = {
|
77
|
+
"id"=>11211881,
|
78
|
+
"project_id"=>232039,
|
79
|
+
"story_type"=>"feature",
|
80
|
+
"url"=>"http://www.pivotaltracker.com/story/show/11211881",
|
81
|
+
"estimate"=>2, "current_state"=>"unstarted",
|
82
|
+
"description"=>"* Add a method that finds the other users on the project\n* gets all of the tickets that have been started/finished by them today\n*display that to the screen",
|
83
|
+
"name"=>"Add a daily_update method",
|
84
|
+
"requested_by"=>"Austin Flores",
|
85
|
+
"created_at"=>"2011-03-17 05:02:46 UTC",
|
86
|
+
"updated_at"=>"2011-03-17 05:02:51 UTC"
|
87
|
+
}
|
88
|
+
delivered = {
|
89
|
+
"id"=>11255061,
|
90
|
+
"project_id"=>232039,
|
91
|
+
"story_type"=>"feature",
|
92
|
+
"url"=>"http://www.pivotaltracker.com/story/show/11255061",
|
93
|
+
"estimate"=>1, "current_state"=>"delivered",
|
94
|
+
"description"=>"if no project-id is given check git config",
|
95
|
+
"name"=>"Read project id from git config",
|
96
|
+
"requested_by"=>"Austin Flores",
|
97
|
+
"owned_by"=>"Austin Flores",
|
98
|
+
"created_at"=>"2011-03-18 01:08:32 UTC",
|
99
|
+
"updated_at"=>"2011-03-30 04:46:41 UTC"
|
100
|
+
}
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
include PivotStories
|
105
|
+
|
106
|
+
class Class
|
107
|
+
def publicize_methods
|
108
|
+
saved_private_instance_methods = self.private_instance_methods
|
109
|
+
self.class_eval { public *saved_private_instance_methods }
|
110
|
+
yield
|
111
|
+
self.class_eval { private *saved_private_instance_methods }
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
describe Config do
|
5
|
+
context "class" do
|
6
|
+
describe "self#load_config" do
|
7
|
+
before(:each) { FSHelp::ensure_fresh_config! }
|
8
|
+
after(:each) { clean_test_config! }
|
9
|
+
|
10
|
+
it "should properly load the config file" do
|
11
|
+
Todone::Config.load_config(FSHelp::CONFIG_DIR).to_hash.should == YAML.load(File.open(FSHelp::ABS_CONFIG_FILE).read)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
context "instance" do
|
16
|
+
before(:each) do
|
17
|
+
@config = Todone::Config.new
|
18
|
+
@hash = { :foo => "bar", :baz => "widget" }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#update!" do
|
22
|
+
it "should properly update and return its data variable" do
|
23
|
+
@config.update! @hash
|
24
|
+
@config.to_hash.should == @hash
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "self#new" do
|
29
|
+
it "should properly instantiate with data" do
|
30
|
+
config = Todone::Config.new @hash
|
31
|
+
@hash.should == config.to_hash
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "hash setter" do
|
36
|
+
it "should work with object getter" do
|
37
|
+
@config[:foo] = "bar"
|
38
|
+
"bar".should == @config[:foo]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "object setter" do
|
43
|
+
it "should work with object getter" do
|
44
|
+
@config.foo = "bar"
|
45
|
+
"bar".should == @config.foo
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#save" do
|
50
|
+
it "should write out a yaml version of the @data attribute" do
|
51
|
+
FSHelp::ensure_fresh_config!
|
52
|
+
hash = { :user => :dr_rumack, :nickname => 'Shirley' }
|
53
|
+
config = Todone::Config.new hash
|
54
|
+
config.save FSHelp::CONFIG_DIR
|
55
|
+
YAML.load(File.open(FSHelp::ABS_CONFIG_FILE).read).to_hash.should == config.to_hash
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#to_hash" do
|
60
|
+
it "should return a recursively hashified version of the @data attribute" do
|
61
|
+
#this hash should cover my bases as far as being deep
|
62
|
+
hash = {
|
63
|
+
:frank_drebbin => {
|
64
|
+
:guns => ['gun1','gun2','crome_dome'],
|
65
|
+
:friends=> {
|
66
|
+
:nordberg => { :football_skills => 'teh_best' }
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
Todone::Config.new(hash).to_hash.should == hash
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Todone::MessageProcessor do
|
4
|
+
before(:each) { FSHelp::clean_test_config! }
|
5
|
+
describe "self#needs_init?" do
|
6
|
+
it "should return true there is no config.yml" do
|
7
|
+
Todone::MessageProcessor.needs_init?(FSHelp::CONFIG_DIR).should == true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should return false when there is a config.yml" do
|
11
|
+
ensure_fresh_config!
|
12
|
+
Todone::MessageProcessor.needs_init?(FSHelp::CONFIG_DIR).should == false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "self#init" do
|
17
|
+
it "should set owner and api_key when given those options" do
|
18
|
+
options = { :dir => FSHelp::CONFIG_DIR }.merge(FSHelp::dummy_config)
|
19
|
+
Todone::MessageProcessor.init options
|
20
|
+
config = File.open( FSHelp::ABS_CONFIG_FILE ) { |yf| YAML::load( yf ) }
|
21
|
+
config.should == FSHelp::dummy_config
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return nil if :api_key or :owner arent passed in" do
|
25
|
+
options = { :dir => FSHelp::CONFIG_DIR }
|
26
|
+
Todone::MessageProcessor.init(options).should == nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#TODO remove file work and replace with some stubs
|
31
|
+
describe "#add_project" do
|
32
|
+
before(:each) do
|
33
|
+
FSHelp::ensure_fresh_config!
|
34
|
+
@mp = Todone::MessageProcessor.new(:config_dir => FSHelp::CONFIG_DIR)
|
35
|
+
@mp.stubs(:save_project_id).returns(nil);
|
36
|
+
@project = { :users => 'frank_drebbin', :id => '555555' }
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should edit a project in config if project is present" do
|
40
|
+
@mp.stubs(:add_hook).returns("called")
|
41
|
+
@mp.add_project @project
|
42
|
+
config = File.open( FSHelp::ABS_CONFIG_FILE ) { |yf| YAML::load( yf ) }
|
43
|
+
config.should == FSHelp::dummy_config.merge({:'555555'=> ["frank_drebbin"]})
|
44
|
+
@mp.add_project @project
|
45
|
+
config = File.open( FSHelp::ABS_CONFIG_FILE ) { |yf| YAML::load( yf ) }
|
46
|
+
config.should == FSHelp::dummy_config.merge({:'555555'=> ["frank_drebbin"]})
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should add a hook to .git/hooks/pre-commit if not present" do
|
50
|
+
File.stubs(:exists?).with(File.join('.git','hooks')).returns(true)
|
51
|
+
@mp.stubs(:add_hook).returns("called")
|
52
|
+
@mp.add_project(@project).should == "called"
|
53
|
+
end
|
54
|
+
|
55
|
+
#TODO remove text from return statement
|
56
|
+
it "should not add a hook if .git/hooks/pre-commit is present" do
|
57
|
+
File.stubs(:exists?).returns(true)
|
58
|
+
data = @mp.add_project(@project)
|
59
|
+
data.shift.should == "exists_pre_commit_hook"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should not add a hook if .git/hooks/ cannot be found" do
|
63
|
+
File.stubs(:exists?).returns(false)
|
64
|
+
data = @mp.add_project(@project)
|
65
|
+
data.shift.should == 'missing_hooks_dir'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#load_project_id" do
|
70
|
+
it "should return the project_id if one exists in .git/config file" do
|
71
|
+
end
|
72
|
+
it "should return nil when a project_id does not exist in the .git/config file" do
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#tickets" do
|
78
|
+
|
79
|
+
it "should return show_pivotal_stories when project_id not passed to construct but exists in git config" do
|
80
|
+
Todone::MessageProcessor.stubs(:load_project_id).returns(nil)
|
81
|
+
@mp = Todone::MessageProcessor.new
|
82
|
+
data = @mp.tickets
|
83
|
+
data.shift.should == 'missing_project_id'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return show_pivotal_stories when stories are returned" do
|
87
|
+
@mp = Todone::MessageProcessor.new({:project_id => 5})
|
88
|
+
Todone::PivotalPuller.stubs(:get).returns({'stories'=> []})
|
89
|
+
data = @mp.tickets
|
90
|
+
data.shift.should == "show_pivotal_stories"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return api_problem when an api error" do
|
94
|
+
@mp = Todone::MessageProcessor.new({:project_id => 5})
|
95
|
+
Todone::PivotalPuller.stubs(:get).raises(SocketError)
|
96
|
+
@mp.tickets.should == "api_problem"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should return bad_state when passed a non-existant ticket state"
|
100
|
+
|
101
|
+
end
|
102
|
+
describe "#write_tickets" do
|
103
|
+
before(:each) do
|
104
|
+
@mp = Todone::MessageProcessor.new({:project_id => 5})
|
105
|
+
end
|
106
|
+
|
107
|
+
#TODO: figure out a better way to test this
|
108
|
+
it "should write to a file if there are stories and no file is specified" do
|
109
|
+
Todone::PivotalPuller.stubs(:get).returns({'stories'=> ['thing']})
|
110
|
+
File.expects(:open)
|
111
|
+
@mp.write_tickets
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should not write to a file if there are no stories" do
|
115
|
+
Todone::PivotalPuller.stubs(:get).returns({'stories'=> []})
|
116
|
+
File.expects(:write).never
|
117
|
+
@mp.write_tickets
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should call a missing_write_file view if a bad write file is specified" do
|
121
|
+
@mp.expects(:missing_write_file).returns("")
|
122
|
+
@mp.write_tickets :file => 'nonexistant_file_is_nonexistant'
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#commit_msg_file" do
|
128
|
+
|
129
|
+
before(:each) do
|
130
|
+
@mp = Todone::MessageProcessor.new({:project_id => 5})
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should return ../COMMIT_EDITMSG if current dir is hooks" do
|
134
|
+
Dir.stubs(:getwd).returns('hooks')
|
135
|
+
Todone::MessageProcessor.commit_msg_file.should == '../COMMIT_EDITMSG'
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should return .git/COMMIT_EDITMSG if current dir is base pj dir" do
|
139
|
+
Dir.stubs(:exists?).returns(true)
|
140
|
+
Todone::MessageProcessor.commit_msg_file.should == '.git/COMMIT_EDITMSG'
|
141
|
+
end
|
142
|
+
|
143
|
+
it "Not sure what to do if in a different directory than preious 2"
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "dynamic view methods" do
|
147
|
+
|
148
|
+
it "should exist if a method exists" do
|
149
|
+
Todone::MessageProcessor.method_defined?('tickets').should == true
|
150
|
+
@mp = Todone::MessageProcessor.new({:project_id => 5})
|
151
|
+
@mp.view_tickets.class.should == String
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should raise a method_missing error if the method does not exist" do
|
155
|
+
Todone::MessageProcessor.method_defined?('get_me_a_coke').should_not == true
|
156
|
+
@mp = Todone::MessageProcessor.new({:project_id => 5})
|
157
|
+
lambda {@mp.write_get_me_a_coke}.should raise_error NoMethodError
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should call the missing template view method when view does not exist" do
|
161
|
+
@mp = Todone::MessageProcessor.new({:project_id => 5})
|
162
|
+
Todone::MessageProcessor.method_defined?('tickets').should == true
|
163
|
+
@mp.expects(:missing_view)
|
164
|
+
Todone::Views.stubs(:method_defined?).returns(false)
|
165
|
+
@mp.view_tickets
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
|
5
|
+
describe Todone::PivotalPuller do
|
6
|
+
describe "self#pull_stories" do
|
7
|
+
it "should return stories when they are available" do
|
8
|
+
Todone::PivotalPuller.stubs(:get).returns({'stories'=> [{"id"=> 'valid_id'}]})
|
9
|
+
pp = Todone::PivotalPuller.new( :project_id => 100000, :api_key => 'blabbityboo' )
|
10
|
+
pp.pull_stories('started').class.to_s.should == 'Array'
|
11
|
+
end
|
12
|
+
|
13
|
+
# TODO: figure out how to test this, api_key stored in config, don't want to stub the call, is this important?
|
14
|
+
it "should return an empty array when a bad project_id is given" do
|
15
|
+
#pp = Todone::PivotalPuller.new( :project_id => 1, :api_key => 'blabbityboo' )
|
16
|
+
#pp.pull_stories('started').class.to_s.should == 'Array'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return an empty array when no stories are available" do
|
20
|
+
Todone::PivotalPuller.stubs(:get).returns({'stories'=> []})
|
21
|
+
pp = Todone::PivotalPuller.new( :project_id => 100000, :api_key => 'blabbityboo' )
|
22
|
+
pp.pull_stories('started').class.to_s.should == 'Array'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return an error if a bad state is requested" do
|
26
|
+
pp = Todone::PivotalPuller.new( :project_id => 100000, :api_key => 'blabbityboo' )
|
27
|
+
pp.pull_stories('unnavailable_state')['error'].should == 'invalid_state'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return error when site unreachable" do
|
31
|
+
Todone::PivotalPuller.stubs(:get).raises(SocketError)
|
32
|
+
pp = Todone::PivotalPuller.new( :project_id => 100000, :api_key => 'blabbityboo' )
|
33
|
+
pp.pull_stories('started')['error'].should == 'api_problem'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return an array of stories if given the state: unscheduled, started, unstarted, accepted or delivered" do
|
37
|
+
Todone::PivotalPuller.stubs(:get).returns({'stories'=> [{"id"=> 'valid_id'}]})
|
38
|
+
pp = Todone::PivotalPuller.new( :project_id => 100000, :api_key => 'blabbityboo' )
|
39
|
+
%w(unscheduled started unstarted accepted delivered).each do |state|
|
40
|
+
return_statement = pp.pull_stories(state)
|
41
|
+
return_statement.class.should == Array
|
42
|
+
return_statement[0]['id'].should_not == nil
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: todone
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.2.2
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- A Flores
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-23 00:00:00 +02:00
|
14
|
+
default_executable: todone
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: commander
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 4.0.3
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: crack
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - "="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.1.8
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: httparty
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - "="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.7.4
|
46
|
+
type: :runtime
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: mocha
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - "="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.9.12
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: bundler
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 1.0.0
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *id006
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: jeweler
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.5.2
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: *id007
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: rcov
|
95
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: "0"
|
101
|
+
type: :development
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: *id008
|
104
|
+
description: Toone is a command-line tool that gives you the ability to better integrate git with your project manager(which is currently only allowed to be pivotal tracker). Todone will keep track of the tickets your working on so you don't have to.
|
105
|
+
email: ctrl4ltdeleteme@gmail.com
|
106
|
+
executables:
|
107
|
+
- todone
|
108
|
+
extensions: []
|
109
|
+
|
110
|
+
extra_rdoc_files:
|
111
|
+
- LICENSE.txt
|
112
|
+
- README.md
|
113
|
+
files:
|
114
|
+
- .document
|
115
|
+
- .rvmrc
|
116
|
+
- Gemfile
|
117
|
+
- Gemfile.lock
|
118
|
+
- LICENSE.txt
|
119
|
+
- README.md
|
120
|
+
- Rakefile
|
121
|
+
- VERSION
|
122
|
+
- bin/todone
|
123
|
+
- git_config_read_test
|
124
|
+
- lib/todone.rb
|
125
|
+
- lib/todone/config.rb
|
126
|
+
- lib/todone/consts.rb
|
127
|
+
- lib/todone/pivotal_puller.rb
|
128
|
+
- lib/todone/views.rb
|
129
|
+
- spec/helper.rb
|
130
|
+
- spec/libs/config_spec.rb
|
131
|
+
- spec/libs/message_processor_spec.rb
|
132
|
+
- spec/libs/pivotal_puller_spec.rb
|
133
|
+
has_rdoc: true
|
134
|
+
homepage: http://github.com/unflores/todone
|
135
|
+
licenses:
|
136
|
+
- MIT
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
hash: 1320610435493697253
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
version: "0"
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: "0"
|
157
|
+
requirements: []
|
158
|
+
|
159
|
+
rubyforge_project:
|
160
|
+
rubygems_version: 1.6.2
|
161
|
+
signing_key:
|
162
|
+
specification_version: 3
|
163
|
+
summary: Todone is a command-line tool that gives you the ability to better integrate git with your pivotal project.
|
164
|
+
test_files:
|
165
|
+
- spec/helper.rb
|
166
|
+
- spec/libs/config_spec.rb
|
167
|
+
- spec/libs/message_processor_spec.rb
|
168
|
+
- spec/libs/pivotal_puller_spec.rb
|