toolshed 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +14 -0
  3. data/Rakefile +11 -0
  4. data/bin/toolshed.rb +95 -16
  5. data/lib/toolshed/base.rb +7 -0
  6. data/lib/toolshed/cli.rb +13 -6
  7. data/lib/toolshed/client.rb +105 -83
  8. data/lib/toolshed/commands/checkout_branch.rb +26 -0
  9. data/lib/toolshed/commands/create_branch.rb +60 -0
  10. data/lib/toolshed/commands/create_pivotal_tracker_note.rb +9 -4
  11. data/lib/toolshed/commands/create_pull_request.rb +137 -0
  12. data/lib/toolshed/commands/delete_branch.rb +27 -0
  13. data/lib/toolshed/commands/get_daily_time_update.rb +21 -0
  14. data/lib/toolshed/commands/get_pivotal_tracker_story_information.rb +6 -3
  15. data/lib/toolshed/commands/list_branches.rb +13 -0
  16. data/lib/toolshed/commands/push_branch.rb +11 -0
  17. data/lib/toolshed/commands/update_pivotal_tracker_story_status.rb +8 -5
  18. data/lib/toolshed/git/git.rb +134 -0
  19. data/lib/toolshed/git/github.rb +88 -0
  20. data/lib/toolshed/ticket_tracking/pivotal_tracker.rb +111 -0
  21. data/lib/toolshed/ticket_tracking/ticket_tracking.rb +6 -0
  22. data/lib/toolshed/time_tracking/harvest.rb +68 -0
  23. data/lib/toolshed/time_tracking/time_tracking.rb +6 -0
  24. data/lib/toolshed/version.rb +1 -1
  25. data/lib/toolshed.rb +8 -2
  26. data/test/commands/checkout_branch_test.rb +28 -0
  27. data/test/commands/commands_helper.rb +2 -0
  28. data/test/commands/create_branch_test.rb +44 -0
  29. data/test/commands/create_pull_request_test.rb +125 -0
  30. data/test/commands/delete_branch_test.rb +75 -0
  31. data/test/commands/push_branch_test.rb +49 -0
  32. data/test/config.rb +1 -0
  33. data/test/git/git_helper.rb +31 -0
  34. data/test/git/git_test.rb +115 -0
  35. data/test/git/github_test.rb +91 -0
  36. data/test/helper.rb +98 -0
  37. data/toolshed.gemspec +8 -0
  38. metadata +151 -9
  39. data/lib/toolshed/commands/checkout_git_branch.rb +0 -23
  40. data/lib/toolshed/commands/create_git_branch.rb +0 -28
  41. data/lib/toolshed/commands/create_github_pull_request.rb +0 -77
  42. data/lib/toolshed/commands/push_git_branch.rb +0 -10
  43. data/lib/toolshed/github.rb +0 -89
  44. data/lib/toolshed/pivotal_tracker.rb +0 -87
@@ -0,0 +1,137 @@
1
+ module Toolshed
2
+ module Commands
3
+ class CreatePullRequest
4
+ def execute(args, options = {})
5
+ # see what branch is checked out and where we are branched from
6
+ puts "Current Branch: #{Toolshed::Git::Base.branch_name}"
7
+ puts "Branched From: #{Toolshed::Git::Base.branched_from}"
8
+ puts "Using Defaults: #{(Toolshed::Client.use_defaults.nil?) ? 'No' : 'Yes'}"
9
+
10
+ unless (Toolshed::Client.ticket_tracking_tool.empty?)
11
+ ticket_tracking_url = ''
12
+ ticket_tracking_title = ''
13
+ ticket_id = ''
14
+
15
+ begin
16
+ ticket_tracker_class = Object.const_get("Toolshed::TicketTracking::#{Toolshed::Client.ticket_tracking_tool.camel_case}")
17
+
18
+ if Object.const_get("#{ticket_tracker_class}::USE_PROJECT_ID")
19
+ ticket_tracker_project_id = read_user_input_ticket_tracker_project_id("Project ID (Default: #{Toolshed::Client.default_pivotal_tracker_project_id}):", { default: Toolshed::Client.default_pivotal_tracker_project_id })
20
+ options.merge!({ project_id: ticket_tracker_project_id })
21
+ end
22
+
23
+ ticket_tracker = ticket_tracker_class.create_instance(options)
24
+
25
+ # @TODO - refactor this code into the git module seems more appropriate since it's performing git functions
26
+ ticket_id = read_user_input_ticket_tracker_ticket_id("Ticket ID (Default: #{Toolshed::TicketTracking::PivotalTracker::story_id_from_branch_name(Toolshed::Git::Base.branch_name)}):", { default: Toolshed::TicketTracking::PivotalTracker::story_id_from_branch_name(Toolshed::Git::Base.branch_name) })
27
+ ticket_information = ticket_tracker.story_information(ticket_id)
28
+
29
+ ticket_tracking_url = ticket_information.url
30
+ ticket_tracking_title = ticket_tracker_class.clean(ticket_information.name)
31
+ ticket_id = ticket_information.id
32
+
33
+ puts "Ticket Tracking URL: #{ticket_tracking_url}"
34
+ puts "Ticket Tracking title: #{ticket_tracking_title}"
35
+ puts "Ticket ID: #{ticket_id}"
36
+ rescue
37
+ puts "Ticket tracking tool is not supported at this time"
38
+ return
39
+ end
40
+ end
41
+
42
+ pull_request_url = ''
43
+ begin
44
+ git_tool_class = Object.const_get("Toolshed::Git::#{Toolshed::Client.git_tool.camel_case}")
45
+ git_tool = git_tool_class.create_instance
46
+
47
+ # create the pull request prompt when needed
48
+ title = read_user_input_pull_request_title("Pull request title (Default: #{ticket_tracking_title}):", options.merge!({ :default => ticket_tracking_title }))
49
+ body = read_user_input_pull_request_body("Pull request body (Default: #{ticket_tracking_url}):", options.merge!({ :default => ticket_tracking_url }))
50
+
51
+ puts "Pull request being created"
52
+ git_pull_request_result = git_tool.create_pull_request(title, body)
53
+ pull_request_url = git_pull_request_result["html_url"]
54
+
55
+ add_note_to_ticket = read_user_input_add_note_to_ticket("Would you like to add a note with the pull request url?")
56
+ if (add_note_to_ticket)
57
+ result = ticket_tracker.add_note(ticket_id, pull_request_url)
58
+ result = ticket_tracker.update_ticket_status(ticket_id, Object.const_get("#{ticket_tracker_class}::DEFAULT_COMPLETED_STATUS"))
59
+ end
60
+
61
+ puts "Created Pull Request: #{pull_request_url}"
62
+ rescue => e
63
+ puts e.message
64
+ exit
65
+ end
66
+ end
67
+
68
+ def read_user_input_add_note_to_ticket(message)
69
+ return true if (Toolshed::Client.use_defaults)
70
+
71
+ puts message
72
+ value = $stdin.gets.chomp
73
+
74
+ until (%w(y n).include?(value.downcase))
75
+ puts "Value must be Y or N"
76
+ puts message
77
+ value = $stdin.gets.chomp
78
+ end
79
+
80
+ (value == 'y') ? true : false
81
+ end
82
+
83
+ def read_user_input_pull_request_title(message, options)
84
+ return options[:title] if (options.has_key?(:title))
85
+ return options[:default] if (Toolshed::Client.use_defaults)
86
+
87
+ puts message
88
+ value = $stdin.gets.chomp
89
+ if (value.empty?)
90
+ value = default
91
+ end
92
+
93
+ value
94
+ end
95
+
96
+ def read_user_input_pull_request_body(message, options)
97
+ return options[:body] if (options.has_key?(:body))
98
+ return options[:default] if (Toolshed::Client.use_defaults)
99
+
100
+ puts message
101
+ value = $stdin.gets.chomp
102
+
103
+ if (value.empty?)
104
+ value = default
105
+ end
106
+
107
+ value
108
+ end
109
+
110
+ def read_user_input_ticket_tracker_project_id(message, options)
111
+ return options[:default] if (Toolshed::Client.use_defaults)
112
+
113
+ puts message
114
+ value = $stdin.gets.chomp
115
+
116
+ if (value.empty?)
117
+ value = default
118
+ end
119
+
120
+ value
121
+ end
122
+
123
+ def read_user_input_ticket_tracker_ticket_id(message, options)
124
+ return options[:default] if (Toolshed::Client.use_defaults)
125
+
126
+ puts message
127
+ value = $stdin.gets.chomp
128
+
129
+ if (value.empty?)
130
+ value = default
131
+ end
132
+
133
+ value
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,27 @@
1
+ module Toolshed
2
+ module Commands
3
+ class DeleteBranch
4
+ def execute(args, options = {})
5
+ branch_name = read_user_input("Ticket ID or branch name:", options)
6
+ branch_name = Toolshed::Git::Base.delete(branch_name)
7
+ puts "#{branch_name} has been deleted"
8
+ return
9
+ end
10
+
11
+ def read_user_input(message, options)
12
+ return options[:branch_name] if (options.has_key?(:branch_name))
13
+
14
+ puts message
15
+ value = $stdin.gets.chomp
16
+
17
+ until (!value.empty?)
18
+ puts "Branch name cannot be empty"
19
+ puts message
20
+ value = $stdin.gets.chomp
21
+ end
22
+
23
+ value
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ module Toolshed
2
+ module Commands
3
+ class GetDailyTimeUpdate
4
+ def execute(args, options = {})
5
+ if (Toolshed::Client.time_tracking_tool == 'harvest')
6
+ harvest = Toolshed::TimeTracking::Harvest.new
7
+
8
+ puts "Getting time entries:"
9
+
10
+ notes = harvest.previous
11
+ notes = "#{notes}\n\n#{harvest.today}"
12
+
13
+ puts notes
14
+ else
15
+ puts "Time tracking tool is undefined implementation needed"
16
+ exit
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -9,10 +9,13 @@ module Toolshed
9
9
  project_id = Toolshed::Client.default_pivotal_tracker_project_id
10
10
  end
11
11
 
12
- pivotal_tracker = Toolshed::PivotalTracker.new({ project_id: project_id, username: Toolshed::PivotalTracker.username, password: Toolshed::PivotalTracker.password })
13
- github = Toolshed::Github.new
12
+ pivotal_tracker = Toolshed::TicketTracking::PivotalTracker.new({
13
+ project_id: project_id,
14
+ username: Toolshed::TicketTracking::PivotalTracker.username,
15
+ password: Toolshed::TicketTracking::PivotalTracker.password,
16
+ })
14
17
 
15
- default_story_id = Toolshed::PivotalTracker::story_id_from_branch_name(github.branch_name)
18
+ default_story_id = Toolshed::TicketTracking::PivotalTracker::story_id_from_branch_name(Toolshed::Git::Base.branch_name)
16
19
  print "Story ID (Default: #{default_story_id})? "
17
20
  story_id = $stdin.gets.chomp.strip
18
21
  if (story_id == '')
@@ -0,0 +1,13 @@
1
+ module Toolshed
2
+ module Commands
3
+ class ListBranches
4
+ def execute(args, options = {})
5
+ git = Toolshed::Git::Github.new
6
+ branches = git.list_branches
7
+ branches.each do |branch|
8
+ puts branch['name']
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Toolshed
2
+ module Commands
3
+ class PushBranch
4
+ def execute(args, options = {})
5
+ branch_name = Toolshed::Git::Base.push(options)
6
+ puts "#{branch_name} has been pushed"
7
+ return
8
+ end
9
+ end
10
+ end
11
+ end
@@ -10,20 +10,23 @@ module Toolshed
10
10
  project_id = Toolshed::Client.default_pivotal_tracker_project_id
11
11
  end
12
12
 
13
- pivotal_tracker = Toolshed::PivotalTracker.new({ project_id: project_id, username: Toolshed::PivotalTracker.username, password: Toolshed::PivotalTracker.password })
14
- github = Toolshed::Github.new
13
+ pivotal_tracker = Toolshed::TicketTracking::PivotalTracker.new({
14
+ project_id: project_id,
15
+ username: Toolshed::TicketTracking::PivotalTracker.username,
16
+ password: Toolshed::TicketTracking::PivotalTracker.password,
17
+ })
15
18
 
16
- default_story_id = Toolshed::PivotalTracker::story_id_from_branch_name(github.branch_name)
19
+ default_story_id = Toolshed::TicketTracking::PivotalTracker::story_id_from_branch_name(Toolshed::Git::Base.branch_name)
17
20
  print "Story ID (Default: #{default_story_id})? "
18
21
  story_id = $stdin.gets.chomp.strip
19
22
  if (story_id == '')
20
23
  story_id = default_story_id
21
24
  end
22
25
 
23
- print "Status (Default: #{Toolshed::PivotalTracker::STORY_STATUS_DEFAULT})? "
26
+ print "Status (Default: #{Toolshed::TicketTracking::PivotalTracker::STORY_STATUS_DEFAULT})? "
24
27
  story_status = $stdin.gets.chomp.strip
25
28
  if (story_status == '')
26
- story_status = Toolshed::PivotalTracker::STORY_STATUS_DEFAULT
29
+ story_status = Toolshed::TicketTracking::PivotalTracker::STORY_STATUS_DEFAULT
27
30
  end
28
31
 
29
32
  begin
@@ -0,0 +1,134 @@
1
+ module Toolshed
2
+ module Git
3
+ DEFAULT_GIT_TOOL = 'github'
4
+
5
+ def branch_name
6
+ # branch information
7
+ branch_name = `git rev-parse --abbrev-ref HEAD`.strip
8
+ end
9
+
10
+ def branched_from
11
+ branched_from = `git rev-parse --abbrev-ref --symbolic-full-name @{u}`.split('/')[-1].strip
12
+ end
13
+
14
+ def branch_name_from_id(id)
15
+ branch_name = `git branch | grep \"#{id}\"`.gsub("*", "").strip
16
+ end
17
+
18
+ def checkout(branch_name)
19
+ branch_name = Toolshed::Git::Base.branch_name_from_id(branch_name)
20
+ until system("git checkout #{branch_name} #{Toolshed::Client.git_quiet}")
21
+ sleep 1
22
+ end
23
+
24
+ unless (Toolshed::Git::Base.git_submodule_command.empty?)
25
+ until system(Toolshed::Git::Base.git_submodule_command)
26
+ sleep 1
27
+ end
28
+ end
29
+
30
+ branch_name
31
+ end
32
+
33
+ def delete(branch_name)
34
+ branch_name = Toolshed::Git::Base.branch_name_from_id(branch_name)
35
+
36
+ # if delete your current branch checkout master so it can be deleted
37
+ if (branch_name == Toolshed::Git::Base.branch_name)
38
+ Toolshed::Git::Base.checkout('master')
39
+ end
40
+
41
+ until system("git push #{Toolshed::Client.push_to_remote_name} :#{branch_name}; git branch -D #{branch_name}")
42
+ sleep 1
43
+ end
44
+
45
+ branch_name
46
+ end
47
+
48
+ def git_submodule_command
49
+ git_submodule_command = ''
50
+ if (Toolshed::Client.use_git_submodules)
51
+ git_submodule_command = "git submodule update #{Toolshed::Client.git_quiet}"
52
+ end
53
+
54
+ git_submodule_command
55
+ end
56
+
57
+ def clean_branch_name(branch_name)
58
+ branch_name.strip.downcase.tr(" ", "_").gsub("-", "").gsub("&", "").gsub("/", "_").gsub(".", "_").gsub("'", "").gsub("__", "_").gsub(":", "")
59
+ end
60
+
61
+ def push(options = {})
62
+ branch_name = (options.has_key?(:branch_name)) ? Toolshed::Git::Base.branch_name_from_id(options[:branch_name]) : Toolshed::Git::Base.branch_name
63
+ force_command = (options.has_key?(:force_command)) ? '--force' : ''
64
+
65
+ until system("git push #{Toolshed::Client.push_to_remote_name} #{branch_name} #{force_command}")
66
+ sleep 1
67
+ end
68
+
69
+ branch_name
70
+ end
71
+
72
+ class GitValidator
73
+ include Veto.validator
74
+
75
+ validates :from_remote_name, :presence => true
76
+ validates :from_remote_branch_name, :presence => true
77
+ validates :to_remote_name, :presence => true
78
+ validates :to_remote_branch_name, :presence => true
79
+ end
80
+
81
+ class Base
82
+ extend Toolshed::Git
83
+
84
+ attr_accessor :from_remote_name, :from_remote_branch_name, :to_remote_name, :to_remote_branch_name, :validator
85
+
86
+ def initialize(options={})
87
+ # options with defaults
88
+ self.from_remote_name = Toolshed::Client.pull_from_remote_name
89
+ unless (options[:from_remote_name].nil?)
90
+ self.from_remote_name = options[:from_remote_name]
91
+ end
92
+
93
+ self.to_remote_name = Toolshed::Client.push_to_remote_name
94
+ unless (options[:to_remote_name].nil?)
95
+ self.to_remote_name = options[:to_remote_name]
96
+ end
97
+
98
+ # options that do not have a default
99
+ unless (options[:from_remote_branch_name].nil?)
100
+ self.from_remote_branch_name = options[:from_remote_branch_name]
101
+ end
102
+
103
+ unless (options[:to_remote_branch_name].nil?)
104
+ self.to_remote_branch_name = options[:to_remote_branch_name]
105
+ end
106
+
107
+ self.validator = ::Toolshed::Git::GitValidator.new
108
+ end
109
+
110
+ def create_branch
111
+ self.validator.validate!(self)
112
+
113
+ new_branch_name = Toolshed::Git::Base.clean_branch_name(self.to_remote_branch_name)
114
+ until system("git remote update #{Toolshed::Client.git_quiet}")
115
+ sleep 1
116
+ end
117
+
118
+ until system("git checkout -b #{new_branch_name} #{self.from_remote_name}/#{self.from_remote_branch_name} #{Toolshed::Client.git_quiet}")
119
+ sleep 1
120
+ end
121
+
122
+ unless (Toolshed::Git::Base.git_submodule_command.empty?)
123
+ until system(Toolshed::Git::Base.git_submodule_command)
124
+ sleep 1
125
+ end
126
+ end
127
+
128
+ until system("git push #{self.to_remote_name} #{new_branch_name} #{Toolshed::Client.git_quiet}")
129
+ sleep 1
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,88 @@
1
+ module Toolshed
2
+ module Git
3
+ class Github < Base
4
+ extend Toolshed::Git
5
+ include HTTParty
6
+
7
+ attr_accessor :default_options
8
+
9
+ def initialize(options={})
10
+ super(options)
11
+
12
+ username = Toolshed::Client::github_username
13
+ password = Toolshed::Client::github_password
14
+
15
+ unless (options[:username].nil?)
16
+ username = options[:username]
17
+ end
18
+
19
+ unless (options[:password].nil?)
20
+ password = options[:password]
21
+ end
22
+
23
+ @auth = { username: username, password: password }
24
+ self.default_options = {
25
+ :headers => {
26
+ "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1309.0 Safari/537.17"
27
+ },
28
+ basic_auth: @auth,
29
+ }
30
+ end
31
+
32
+ def create_pull_request(title, body, options={})
33
+ options.merge!(self.default_options)
34
+ options.merge!({
35
+ body: {
36
+ title: title,
37
+ body: body,
38
+ head: "#{Toolshed::Client.github_username}:#{Toolshed::Git::Base.branch_name}",
39
+ base: Toolshed::Git::Base.branched_from
40
+ }.to_json
41
+ })
42
+
43
+ response = HTTParty.post("#{Toolshed::Client::GITHUB_BASE_API_URL}repos/#{Toolshed::Client.pull_from_repository_user}/#{Toolshed::Client.pull_from_repository_name}/pulls", options).response
44
+ response = JSON.parse(response.body)
45
+ if (response["errors"].nil?)
46
+ response
47
+ else
48
+ raise "validation errors #{response.inspect}"
49
+ end
50
+ end
51
+
52
+ def list_branches(options={})
53
+ options.merge!(self.default_options)
54
+
55
+ response = HTTParty.get("#{Toolshed::Client::GITHUB_BASE_API_URL}repos/#{Toolshed::Client.github_username}/#{Toolshed::Client.pull_from_repository_name}/branches", options).response
56
+ response = JSON.parse(response.body)
57
+ end
58
+
59
+ def self.username
60
+ username = Toolshed::Client::github_username
61
+ if (username.nil?)
62
+ # prompt to ask for username
63
+ puts "Github username? "
64
+ username = $stdin.gets.chomp.strip
65
+ end
66
+
67
+ return username
68
+ end
69
+
70
+ def self.password
71
+ password = Toolshed::Client::github_password
72
+ if (password.nil?)
73
+ # prompt to ask for password
74
+ system "stty -echo"
75
+ puts "Github password? "
76
+ password = $stdin.gets.chomp.strip
77
+ system "stty echo"
78
+ end
79
+
80
+ return password
81
+ end
82
+
83
+ def self.create_instance
84
+ Toolshed::Git::Github.new({ username: Toolshed::Git::Github.username, password: Toolshed::Git::Github.password })
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,111 @@
1
+ module Toolshed
2
+ module TicketTracking
3
+ class PivotalTracker
4
+ extend TicketTracking
5
+ include HTTParty
6
+
7
+ DEFAULT_COMPLETED_STATUS = 'finished'
8
+ USE_PROJECT_ID = true
9
+
10
+ attr_accessor :project_id, :token
11
+
12
+ def initialize(options={})
13
+ username = Toolshed::Client::pivotal_tracker_username
14
+ password = Toolshed::Client::pivotal_tracker_password
15
+
16
+ unless (options[:username].nil?)
17
+ username = options[:username]
18
+ end
19
+
20
+ unless (options[:password].nil?)
21
+ password = options[:password]
22
+ end
23
+
24
+ self.token = ::PivotalTracker::Client.token(username, password)
25
+
26
+ self.project_id = (options[:project_id].nil?) ? Toolshed::Client.default_pivotal_tracker_project_id : options[:project_id]
27
+ @pt_project = ::PivotalTracker::Project.find(self.project_id)
28
+ end
29
+
30
+ #
31
+ # Instance methods
32
+ #
33
+ def story_information(story_id)
34
+ return @pt_project.stories.find(story_id)
35
+ end
36
+
37
+ def add_note(story_id, note_text)
38
+ story = @pt_project.stories.find(story_id)
39
+ results = story.notes.create(text: note_text)
40
+ end
41
+
42
+ def update_ticket_status(story_id, current_state, options={})
43
+ options.merge!({
44
+ :headers => {
45
+ "X-TrackerToken" => self.token,
46
+ "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1309.0 Safari/537.17",
47
+ "Content-Type" => "application/json",
48
+ },
49
+ body: {
50
+ current_state: current_state
51
+ }.to_json
52
+ })
53
+
54
+ response = HTTParty.put("#{Toolshed::Client::PIVOTAL_TRACKER_BASE_API_URL}projects/#{self.project_id}/stories/#{story_id}", options).response
55
+ response = JSON.parse(response.body)
56
+
57
+ if (response["error"].nil?)
58
+ response
59
+ else
60
+ raise "validation errors #{response.inspect}"
61
+ end
62
+ end
63
+
64
+ #
65
+ # Class methods
66
+ #
67
+ def self.story_id_from_branch_name(branch_name)
68
+ story_id = branch_name.split("_")[0]
69
+ end
70
+
71
+ def self.username
72
+ username = Toolshed::Client::pivotal_tracker_username
73
+ if (username.nil?)
74
+ # prompt to ask for username
75
+ puts "PivotalTracker username? "
76
+ username = $stdin.gets.chomp.strip
77
+ end
78
+
79
+ return username
80
+ end
81
+
82
+ def self.password
83
+ password = Toolshed::Client::pivotal_tracker_password
84
+ if (password.nil?)
85
+ # prompt to ask for password
86
+ system "stty -echo"
87
+ puts "PivotalTracker password? "
88
+ password = $stdin.gets.chomp.strip
89
+ system "stty echo"
90
+ end
91
+
92
+ return password
93
+ end
94
+
95
+ #
96
+ # Get the pivotal tracker object based off of the project_id
97
+ #
98
+ def self.create_instance(options={})
99
+ unless (options.has_key?(:project_id))
100
+ raise 'Unable to use PivotalTracker as project id was not supplied'
101
+ end
102
+
103
+ pivotal_tracker = Toolshed::TicketTracking::PivotalTracker.new({ project_id: options[:project_id], username: Toolshed::TicketTracking::PivotalTracker.username, password: Toolshed::TicketTracking::PivotalTracker.password })
104
+ end
105
+
106
+ def self.clean(title)
107
+ title.gsub("'", "").gsub("\"", "")
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,6 @@
1
+ module Toolshed
2
+ module TicketTracking
3
+ def initialize(options={})
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,68 @@
1
+ module Toolshed
2
+ module TimeTracking
3
+ class Harvest
4
+ extend TimeTracking
5
+
6
+ MAX_ATTEMPTS = 10
7
+
8
+ attr_accessor :harvest_client, :project_id
9
+
10
+ def initialize(options={})
11
+ username = Toolshed::Client::time_tracking_username
12
+ password = Toolshed::Client::time_tracking_password
13
+ owner = Toolshed::Client.time_tracking_owner
14
+
15
+ unless (options[:username].nil?)
16
+ username = options[:username]
17
+ end
18
+
19
+ unless (options[:password].nil?)
20
+ password = options[:password]
21
+ end
22
+
23
+ unless (options[:sub_domain].nil?)
24
+ owner = options[:sub_domain]
25
+ end
26
+
27
+ self.harvest_client = ::Harvest.client('ackmanndickenson', 'jwaller@ackmanndickenson.com', 'V0AU2gRMLhs1')
28
+ self.project_id = self.get_project_id
29
+ end
30
+
31
+ def previous(days_ago=1)
32
+ notes = "Previous:\n\n"
33
+
34
+ time_entries = self.harvest_client.time.all((DateTime.now - days_ago), self.project_id)
35
+ if (time_entries.size > 0 || days_ago == Toolshed::TimeTracking::Harvest::MAX_ATTEMPTS)
36
+ time_entries.each do |time_entry|
37
+ notes = "#{notes}#{time_entry.notes}\n"
38
+ end
39
+ else
40
+ notes = self.previous(days_ago + 1)
41
+ end
42
+
43
+ notes
44
+ end
45
+
46
+ def today
47
+ notes = "Today:\n\n"
48
+
49
+ time_entries = self.harvest_client.time.all(Time.now, self.project_id)
50
+ time_entries.each do |time_entry|
51
+ notes = "#{notes}#{time_entry.notes}\n"
52
+ end
53
+
54
+ notes
55
+ end
56
+
57
+ def get_project_id
58
+ print "Project ID (Default: #{Toolshed::Client.time_tracking_default_project_id})? "
59
+ project_id = $stdin.gets.chomp.strip
60
+ if (project_id == '')
61
+ project_id = Toolshed::Client.time_tracking_default_project_id
62
+ end
63
+
64
+ project_id
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,6 @@
1
+ module Toolshed
2
+ module TimeTracking
3
+ def initialize(options={})
4
+ end
5
+ end
6
+ end
@@ -1,3 +1,3 @@
1
1
  module Toolshed
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end