v2gpti 1.1.9 → 1.2.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/bin/git-deliver +1 -1
  3. data/bin/git-finish +1 -1
  4. data/bin/git-newbug +1 -1
  5. data/bin/git-newfeature +1 -1
  6. data/bin/git-qa +1 -1
  7. data/bin/git-release +1 -1
  8. data/bin/git-report +1 -1
  9. data/bin/git-start +1 -1
  10. data/bin/git-uat +1 -1
  11. data/config_template +16 -0
  12. data/lib/git-pivotal-tracker-integration/command/base.rb +235 -322
  13. data/lib/git-pivotal-tracker-integration/command/configuration.rb +183 -109
  14. data/lib/git-pivotal-tracker-integration/command/deliver.rb +145 -200
  15. data/lib/git-pivotal-tracker-integration/command/finish.rb +70 -63
  16. data/lib/git-pivotal-tracker-integration/command/newbug.rb +36 -39
  17. data/lib/git-pivotal-tracker-integration/command/newfeature.rb +43 -42
  18. data/lib/git-pivotal-tracker-integration/command/release.rb +171 -203
  19. data/lib/git-pivotal-tracker-integration/command/report.rb +33 -36
  20. data/lib/git-pivotal-tracker-integration/command/start.rb +74 -78
  21. data/lib/git-pivotal-tracker-integration/util/git.rb +202 -204
  22. data/lib/git-pivotal-tracker-integration/util/shell.rb +19 -16
  23. data/lib/git-pivotal-tracker-integration/util/story.rb +155 -177
  24. data/lib/git-pivotal-tracker-integration/version-update/gradle.rb +44 -40
  25. data/lib/git-pivotal-tracker-integration.rb +44 -0
  26. data/spec/git-pivotal-tracker-integration/command/configuration_spec.rb +1 -2
  27. data/spec/git-pivotal-tracker-integration/command/finish_spec.rb +1 -1
  28. data/spec/git-pivotal-tracker-integration/command/release_spec.rb +1 -1
  29. data/spec/git-pivotal-tracker-integration/command/start_spec.rb +1 -1
  30. data/spec/git-pivotal-tracker-integration/util/story_spec.rb +21 -32
  31. data/tracker_api/lib/tracker_api/client.rb +241 -0
  32. data/tracker_api/lib/tracker_api/endpoints/activity.rb +38 -0
  33. data/tracker_api/lib/tracker_api/endpoints/comments.rb +27 -0
  34. data/tracker_api/lib/tracker_api/endpoints/epic.rb +17 -0
  35. data/tracker_api/lib/tracker_api/endpoints/epics.rb +20 -0
  36. data/tracker_api/lib/tracker_api/endpoints/file_attachment.rb +18 -0
  37. data/tracker_api/lib/tracker_api/endpoints/iterations.rb +20 -0
  38. data/tracker_api/lib/tracker_api/endpoints/me.rb +17 -0
  39. data/tracker_api/lib/tracker_api/endpoints/memberships.rb +20 -0
  40. data/tracker_api/lib/tracker_api/endpoints/notifications.rb +20 -0
  41. data/tracker_api/lib/tracker_api/endpoints/project.rb +17 -0
  42. data/tracker_api/lib/tracker_api/endpoints/projects.rb +18 -0
  43. data/tracker_api/lib/tracker_api/endpoints/stories.rb +20 -0
  44. data/tracker_api/lib/tracker_api/endpoints/story.rb +37 -0
  45. data/tracker_api/lib/tracker_api/endpoints/tasks.rb +20 -0
  46. data/tracker_api/lib/tracker_api/error.rb +18 -0
  47. data/tracker_api/lib/tracker_api/logger.rb +31 -0
  48. data/tracker_api/lib/tracker_api/resources/account.rb +18 -0
  49. data/tracker_api/lib/tracker_api/resources/activity.rb +24 -0
  50. data/tracker_api/lib/tracker_api/resources/base.rb +71 -0
  51. data/tracker_api/lib/tracker_api/resources/change.rb +15 -0
  52. data/tracker_api/lib/tracker_api/resources/comment.rb +20 -0
  53. data/tracker_api/lib/tracker_api/resources/epic.rb +17 -0
  54. data/tracker_api/lib/tracker_api/resources/file_attachment.rb +23 -0
  55. data/tracker_api/lib/tracker_api/resources/iteration.rb +24 -0
  56. data/tracker_api/lib/tracker_api/resources/label.rb +14 -0
  57. data/tracker_api/lib/tracker_api/resources/me.rb +21 -0
  58. data/tracker_api/lib/tracker_api/resources/membership_summary.rb +15 -0
  59. data/tracker_api/lib/tracker_api/resources/notification.rb +26 -0
  60. data/tracker_api/lib/tracker_api/resources/person.rb +14 -0
  61. data/tracker_api/lib/tracker_api/resources/primary_resource.rb +13 -0
  62. data/tracker_api/lib/tracker_api/resources/project.rb +131 -0
  63. data/tracker_api/lib/tracker_api/resources/project_membership.rb +16 -0
  64. data/tracker_api/lib/tracker_api/resources/story.rb +102 -0
  65. data/tracker_api/lib/tracker_api/resources/task.rb +16 -0
  66. data/tracker_api/lib/tracker_api/resources/time_zone.rb +13 -0
  67. data/tracker_api/lib/tracker_api/version.rb +3 -0
  68. data/tracker_api/lib/tracker_api.rb +60 -0
  69. metadata +202 -53
  70. data/lib/git-pivotal-tracker-integration/command/command.rb +0 -20
  71. data/lib/git-pivotal-tracker-integration/util/util.rb +0 -20
  72. data/lib/git-pivotal-tracker-integration/version-update/version_update.rb +0 -20
  73. data/lib/git_pivotal_tracker_integration.rb +0 -18
@@ -13,361 +13,274 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require 'git-pivotal-tracker-integration/command/command'
17
- require 'git-pivotal-tracker-integration/command/configuration'
18
- require 'git-pivotal-tracker-integration/util/git'
19
- require 'pivotal-tracker'
20
- require 'parseconfig'
21
- require 'logger'
22
- require 'os'
23
-
24
- # An abstract base class for all commands
25
- # @abstract Subclass and override {#run} to implement command functionality
26
- class GitPivotalTrackerIntegration::Command::Base
27
-
28
- # Common initialization functionality for all command classes. This
29
- # enforces that:
30
- # * the command is being run within a valid Git repository
31
- # * the user has specified their Pivotal Tracker API token
32
- # * all communication with Pivotal Tracker will be protected with SSL
33
- # * the user has configured the project id for this repository
34
- def initialize
35
- self.start_logging
36
- self.check_version
37
-
38
- git_global_push_default = (GitPivotalTrackerIntegration::Util::Shell.exec "git config --global push.default", false).chomp
39
- if git_global_push_default != "simple"
40
- puts "git config --global push.default simple"
41
- puts GitPivotalTrackerIntegration::Util::Shell.exec "git config --global push.default simple"
42
- end
43
-
44
- @repository_root = GitPivotalTrackerIntegration::Util::Git.repository_root
45
- @configuration = GitPivotalTrackerIntegration::Command::Configuration.new
46
- @toggl = Toggl.new
47
-
48
- PivotalTracker::Client.token = @configuration.api_token
49
- PivotalTracker::Client.use_ssl = true
16
+ module GitPivotalTrackerIntegration
17
+ module Command
18
+
19
+ # An abstract base class for all commands
20
+ # @abstract Subclass and override {#run} to implement command functionality
21
+ class Base
22
+
23
+ # Common initialization functionality for all command classes. This
24
+ # enforces that:
25
+ # * the command is being run within a valid Git repository
26
+ # * the user has specified their Pivotal Tracker API token
27
+ # * all communication with Pivotal Tracker will be protected with SSL
28
+ # * the user has configured the project id for this repository
29
+ def initialize
30
+ self.start_logging
31
+ self.check_version
32
+
33
+ git_global_push_default = (Util::Shell.exec "git config --global push.default", false).chomp
34
+ if git_global_push_default != "simple"
35
+ puts "git config --global push.default simple"
36
+ puts Util::Shell.exec "git config --global push.default simple"
37
+ end
38
+
39
+ @repository_root = Util::Git.repository_root
40
+ @toggl = Toggl.new
41
+ @configuration = Command::Configuration.new
42
+
43
+ @configuration.check_for_config_file
44
+ @configuration.check_for_config_contents
45
+
46
+ @client = TrackerApi::Client.new(:token => @configuration.api_token)
47
+ @platform = @configuration.platform_name
48
+
49
+ current_project_id = @configuration.project_id.to_i
50
+ @project = @client.project current_project_id
51
+ my_projects = @client.projects
52
+
53
+ unless my_projects && my_projects.map(&:id).include?(current_project_id)
54
+ project_manager_name = @configuration.pconfig["project"]["project-manager"]
55
+ project_manager_email = @configuration.pconfig["project"]["project-manager-email"]
56
+ project_name = @configuration.pconfig["project"]["project-name"]
57
+ abort "This project requires access to the Pivotal Tracker project [#{project_name} - #{current_project_id}]. Please speak with project manager [#{project_manager_name} - #{project_manager_email}] and ask him to add you to the project in Pivotal Tracker."
58
+ end
59
+ end
50
60
 
51
- @project = PivotalTracker::Project.find @configuration.project_id
52
- @platform = @configuration.platform_name
61
+ def finish_toggle(configuration, time_spent)
62
+ current_story = @configuration.story(@project)
63
+
64
+ # If a story gets rejected and the developer works on it, then we need to check if the task is already created or not.
65
+ params = parameters(configuration, time_spent)
66
+ if params[:tid].nil?
67
+ begin
68
+ @toggl.create_task(parameters(configuration, time_spent))
69
+ rescue TogglException => te
70
+ puts ""
71
+ end
72
+ end
73
+
74
+ #If for some reason time entry cannot be done, then catch exception and continue.
75
+ begin
76
+ @toggl.create_time_entry(parameters(configuration, time_spent))
77
+ rescue TogglException => te
78
+ puts "Unable to log the time."
79
+ end
80
+ end
53
81
 
54
- my_projects = PivotalTracker::Project.all
55
- my_all_projects_ids = Array.new
56
- my_projects.collect{|project| my_all_projects_ids.push project.id.to_i }
57
- current_project_id = @configuration.project_id.to_i
58
- project_manager_name = @configuration.pconfig["project"]["project-manager"]
59
- project_manager_email = @configuration.pconfig["project"]["project-manager-email"]
60
- project_name = @configuration.pconfig["project"]["project-name"]
61
- abort "This project requires access to the Pivotal Tracker project [#{project_name} - #{current_project_id}]. Please speak with project manager [#{project_manager_name} - #{project_manager_email}] and ask him to add you to the project in Pivotal Tracker." unless my_all_projects_ids.include?(current_project_id)
62
- end
82
+ def start_logging
83
+ $LOG = Logger.new("#{logger_filename}", 'weekly')
84
+ end
63
85
 
64
- def finish_toggle(configuration, time_spent)
65
- current_story = @configuration.story(@project)
86
+ def logger_filename
87
+ return "#{Dir.home}/.v2gpti_local.log"
88
+ end
66
89
 
67
- # If a story gets rejected and the developer works on it, then we need to check if the task is already created or not.
68
- params = parameters(configuration, time_spent)
69
- if params[:tid].nil?
70
- begin
71
- @toggl.create_task(parameters(configuration, time_spent))
72
- rescue TogglException => te
90
+ def check_version
91
+ gem_latest_version = (Util::Shell.exec "gem list v2gpti --remote")[/\(.*?\)/].delete "()"
92
+ gem_installed_version = Gem.loaded_specs["v2gpti"].version.version
93
+ if (gem_installed_version == gem_latest_version)
94
+ $LOG.info("v2gpti verison #{gem_installed_version} is up to date.")
95
+ else
96
+ $LOG.fatal("Out of date")
97
+ if OS.windows?
98
+ abort "\n\nYou are using v2gpti version #{gem_installed_version}, but the current version is #{gem_latest_version}.\nPlease update your gem with the following command.\n\n gem update v2gpti\n\n"
99
+ else
100
+ abort "\n\nYou are using v2gpti version #{gem_installed_version}, but the current version is #{gem_latest_version}.\nPlease update your gem with the following command.\n\n sudo gem update v2gpti\n\n"
101
+ end
102
+ end
103
+ rescue StandardError => se
73
104
  puts ""
74
105
  end
75
- end
76
106
 
77
- #If for some reason time entry cannot be done, then catch exception and continue.
78
- begin
79
- @toggl.create_time_entry(parameters(configuration, time_spent))
80
- rescue TogglException => te
81
- puts "Unable to log the time."
82
- end
83
- end
84
-
85
- def start_logging
86
- $LOG = Logger.new("#{logger_filename}", 'weekly')
87
- end
107
+ # The main entry point to the command's execution
108
+ # @abstract Override this method to implement command functionality
109
+ def run
110
+ raise NotImplementedError
111
+ end
88
112
 
89
- def logger_filename
90
- return "#{Dir.home}/.v2gpti_local.log"
91
- end
113
+ # Toggl keys
114
+ # name : The name of the task (string, required, unique in project)
115
+ # pid : project ID for the task (integer, required)
116
+ # wid : workspace ID, where the task will be saved (integer, project's workspace id is used when not supplied)
117
+ # uid : user ID, to whom the task is assigned to (integer, not required)
118
+ # estimated_seconds : estimated duration of task in seconds (integer, not required)
119
+ # active : whether the task is done or not (boolean, by default true)
120
+ # at : timestamp that is sent in the response for PUT, indicates the time task was last updated
121
+ # -- Additional fields --
122
+ # done_seconds : duration (in seconds) of all the time entries registered for this task
123
+ # uname : full name of the person to whom the task is assigned to
124
+ TIMER_TOKENS = {
125
+ "m" => (60),
126
+ "h" => (60 * 60),
127
+ "d" => (60 * 60 * 8) # a work day is 8 hours
128
+ }
129
+ def parameters(configuration, time_spent)
130
+ current_story = configuration.story(@project)
131
+ params = Hash.new
132
+ params[:name] = "#{current_story.id}" + " - " + "#{current_story.name}"
133
+ params[:estimated_seconds] = estimated_seconds current_story
134
+ params[:pid] = configuration.toggl_project_id
135
+ params[:uid] = @toggl.me["id"]
136
+ params[:tags] = [current_story.story_type]
137
+ params[:active] = false
138
+ params[:description] = "#{current_story.id}" + " commit:" + "#{(Util::Shell.exec "git rev-parse HEAD").chomp[0..6]}"
139
+ params[:created_with] = "v2gpti"
140
+ params[:duration] = seconds_spent(time_spent)
141
+ params[:start] = (Time.now - params[:duration]).iso8601
142
+ task = @toggl.get_project_task_with_name(configuration.toggl_project_id, "#{current_story.id}")
143
+ if !task.nil?
144
+ params[:tid] = task['id']
145
+ end
146
+ params
147
+ end
148
+ def seconds_spent(time_spent)
149
+ seconds = 0
150
+ time_spent.scan(/(\d+)(\w)/).each do |amount, measure|
151
+ seconds += amount.to_i * TIMER_TOKENS[measure]
152
+ end
153
+ seconds
154
+ end
155
+ def estimated_seconds(story)
156
+ estimate = story.estimate
157
+ seconds = 0
158
+ case estimate
159
+ when 0
160
+ estimate = 15 * 60
161
+ when 1
162
+ estimate = 1.25 * 60 * 60
163
+ when 2
164
+ estimate = 3 * 60 * 60
165
+ when 3
166
+ estimate = 8 * 60 * 60
167
+ else
168
+ estimate = -1 * 60 * 60
169
+ end
170
+ estimate
171
+ end
92
172
 
93
- def check_version
94
- gem_latest_version = (GitPivotalTrackerIntegration::Util::Shell.exec "gem list v2gpti --remote")[/\(.*?\)/].delete "()"
95
- gem_installed_version = Gem.loaded_specs["v2gpti"].version.version
96
- if (gem_installed_version == gem_latest_version)
97
- $LOG.info("v2gpti verison #{gem_installed_version} is up to date.")
98
- else
99
- $LOG.fatal("Out of date")
100
- if OS.windows?
101
- abort "\n\nYou are using v2gpti version #{gem_installed_version}, but the current version is #{gem_latest_version}.\nPlease update your gem with the following command.\n\n gem update v2gpti\n\n"
102
- else
103
- abort "\n\nYou are using v2gpti version #{gem_installed_version}, but the current version is #{gem_latest_version}.\nPlease update your gem with the following command.\n\n sudo gem update v2gpti\n\n"
104
- end
105
- end
106
- rescue StandardError => se
107
- puts ""
108
- end
173
+ def create_story(args)
174
+ story_types = {"f" => "feature", "b" => "bug", "c" => "chore"}
175
+ new_story_type = nil
176
+ new_story_title = nil
177
+ new_story_estimate = -1
178
+ args.each do |arg|
179
+ new_story_type = story_types[arg[-1]] if arg.include? '-n'
180
+ new_story_title = arg if arg[0] != "-"
181
+ end
109
182
 
110
- # The main entry point to the command's execution
111
- # @abstract Override this method to implement command functionality
112
- def run
113
- raise NotImplementedError
114
- end
183
+ while new_story_type.nil?
184
+ nst = ask("Please enter f for feature, b for bug, or c for chore")
185
+ new_story_type = story_types[nst]
186
+ end
115
187
 
116
- # Toggl keys
117
- # name : The name of the task (string, required, unique in project)
118
- # pid : project ID for the task (integer, required)
119
- # wid : workspace ID, where the task will be saved (integer, project's workspace id is used when not supplied)
120
- # uid : user ID, to whom the task is assigned to (integer, not required)
121
- # estimated_seconds : estimated duration of task in seconds (integer, not required)
122
- # active : whether the task is done or not (boolean, by default true)
123
- # at : timestamp that is sent in the response for PUT, indicates the time task was last updated
124
- # -- Additional fields --
125
- # done_seconds : duration (in seconds) of all the time entries registered for this task
126
- # uname : full name of the person to whom the task is assigned to
127
- TIMER_TOKENS = {
128
- "m" => (60),
129
- "h" => (60 * 60),
130
- "d" => (60 * 60 * 8) # a work day is 8 hours
131
- }
132
- def parameters(configuration, time_spent)
133
- current_story = configuration.story(@project)
134
- params = Hash.new
135
- params[:name] = "#{current_story.id}" + " - " + "#{current_story.name}"
136
- params[:estimated_seconds] = estimated_seconds current_story
137
- params[:pid] = configuration.toggl_project_id
138
- params[:uid] = @toggl.me["id"]
139
- params[:tags] = [current_story.story_type]
140
- params[:active] = false
141
- params[:description] = "#{current_story.id}" + " commit:" + "#{(GitPivotalTrackerIntegration::Util::Shell.exec "git rev-parse HEAD").chomp[0..6]}"
142
- params[:created_with] = "v2gpti"
143
- params[:duration] = seconds_spent(time_spent)
144
- params[:start] = (Time.now - params[:duration]).iso8601
145
- task = @toggl.get_project_task_with_name(configuration.toggl_project_id, "#{current_story.id}")
146
- if !task.nil?
147
- params[:tid] = task['id']
148
- end
149
- params
150
- end
151
- def seconds_spent(time_spent)
152
- seconds = 0
153
- time_spent.scan(/(\d+)(\w)/).each do |amount, measure|
154
- seconds += amount.to_i * TIMER_TOKENS[measure]
155
- end
156
- seconds
157
- end
158
- def estimated_seconds(story)
159
- estimate = story.estimate
160
- seconds = 0
161
- case estimate
162
- when 0
163
- estimate = 15 * 60
164
- when 1
165
- estimate = 1.25 * 60 * 60
166
- when 2
167
- estimate = 3 * 60 * 60
168
- when 3
169
- estimate = 8 * 60 * 60
170
- else
171
- estimate = -1 * 60 * 60
172
- end
173
- estimate
174
- end
188
+ while (new_story_title.nil? || new_story_title.empty?)
189
+ new_story_title = ask("Please enter the title for this #{new_story_type}.")
190
+ end
175
191
 
176
- def create_story(args)
177
- story_types = {"f" => "feature", "b" => "bug", "c" => "chore"}
178
- new_story_type = nil
179
- new_story_title = nil
180
- new_story_estimate = -1
181
- args.each do |arg|
182
- new_story_type = story_types[arg[-1]] if arg.include? '-n'
183
- new_story_title = arg if arg[0] != "-"
184
- end
192
+ if (new_story_type == "feature" && (new_story_estimate < 0 || new_story_estimate > 3))
193
+ new_story_estimate = estimate_story
194
+ end
185
195
 
186
- while new_story_type.nil?
187
- nst = ask("Please enter f for feature, b for bug, or c for chore")
188
- new_story_type = story_types[nst]
189
- end
196
+ attrs = {:story_type => new_story_type, :current_state => 'unstarted', :name => new_story_title}
197
+ attrs[:estimate] = new_story_estimate if new_story_type == "feature"
190
198
 
191
- while (new_story_title.nil? || new_story_title.empty?)
192
- new_story_title = ask("Please enter the title for this #{new_story_type}.")
193
- end
199
+ @project.create_story(attrs)
194
200
 
195
- while (new_story_type == "feature" && (new_story_estimate < 0 || new_story_estimate > 3))
196
- nse = ask("Please enter an estimate for this #{new_story_type}. (0,1,2,3)")
197
- if !nse.empty?
198
- new_story_estimate = nse.to_i
199
201
  end
200
- end
201
202
 
202
- new_story = PivotalTracker::Story.new
203
- new_story.project_id = @project.id
204
- new_story.story_type = new_story_type
205
- new_story.current_state = "unstarted"
206
- new_story.name = new_story_title
207
- if new_story_type == "feature"
208
- new_story.estimate = new_story_estimate
209
- end
203
+ def create_icebox_bug_story(args)
204
+ create_story_with_type_state("bug", "unscheduled", args)
205
+ end
210
206
 
211
- uploaded_story = new_story.create
207
+ def create_backlog_bug_story(args)
208
+ create_story_with_type_state("bug", "unstarted", args)
209
+ end
212
210
 
213
- end
211
+ def create_icebox_feature_story(args)
212
+ create_story_with_type_state("feature", "unscheduled", args)
213
+ end
214
214
 
215
- def create_icebox_bug_story(args)
216
- new_bug_story_title = nil
217
- args.each do |arg|
218
- new_bug_story_title = arg if arg[0] != "-"
215
+ def create_backlog_feature_story(args)
216
+ create_story_with_type_state("feature", "unstarted", args)
219
217
  end
220
- while (new_bug_story_title.nil? || new_bug_story_title.empty?)
221
- new_bug_story_title = ask("Please enter the title for this bug story")
222
- end
223
- icebox_stories = Array.new
224
- @project.stories.all.collect{|story| icebox_stories.push story if story.current_state == "unscheduled"}
225
- new_bug_story = PivotalTracker::Story.new
226
- new_bug_story.project_id = @project.id
227
- new_bug_story.story_type = "bug"
228
- new_bug_story.current_state = "unscheduled"
229
- new_bug_story.name = new_bug_story_title
230
-
231
- if args.any?{|arg| arg.include?("-tl") } && !(icebox_stories.empty? || icebox_stories.nil?)
232
- icebox_first_story = icebox_stories.first
233
- (new_bug_story.create).move(:before, icebox_first_story)
234
- elsif args.any?{|arg| arg.include?("-bl")} && !(icebox_stories.empty? || icebox_stories.nil?)
235
- icebox_last_story = icebox_stories.last
236
- (new_bug_story.create).move(:after, icebox_last_story)
237
- else
238
- new_bug_story.create
239
- end
240
- end
241
218
 
242
- def create_backlog_bug_story(args)
243
- new_bug_story_title = nil
244
- args.each do |arg|
245
- new_bug_story_title = arg if arg[0] != "-"
246
- end
247
- while (new_bug_story_title.nil? || new_bug_story_title.empty?)
248
- new_bug_story_title = ask("Please enter the title for this bug story")
249
- end
250
- backlog_stories = Array.new
251
- @project.stories.all.collect{|story| backlog_stories.push story if story.current_state == "unstarted" && story.story_type != "release"}
252
- new_bug_story = PivotalTracker::Story.new
253
- new_bug_story.project_id = @project.id
254
- new_bug_story.story_type = "bug"
255
- new_bug_story.current_state = "unstarted"
256
- new_bug_story.name = new_bug_story_title
257
- if args.any?{|arg| arg.include?("-tl")} && !(backlog_stories.empty? || backlog_stories.nil?)
258
- backlog_first_story = backlog_stories.first
259
- (new_bug_story.create).move(:before, backlog_first_story)
260
- elsif args.any?{|arg| arg.include?("-bl")} && !(backlog_stories.empty? || backlog_stories.nil?)
261
- backlog_last_story = backlog_stories.last
262
- (new_bug_story.create).move(:after, backlog_last_story)
263
- else
264
- new_bug_story.create
265
- end
266
- end
219
+ private
267
220
 
268
- def create_icebox_feature_story(args)
269
- new_feature_story_title = nil
270
- new_feature_story_points = nil
271
- args.each do |arg|
272
- new_feature_story_title = arg if arg[0] != "-"
273
- end
274
- while (new_feature_story_title.nil? || new_feature_story_title.empty?)
275
- new_feature_story_title = ask("\nPlease enter the title for this feature story")
221
+ def pwd
222
+ command = OS.windows? ? 'echo %cd%': 'pwd'
223
+ Util::Shell.exec(command).chop
276
224
  end
277
- icebox_stories = Array.new
278
- @project.stories.all.collect{|story| icebox_stories.push story if story.current_state == "unscheduled"}
279
- new_feature_story = PivotalTracker::Story.new
280
- new_feature_story.project_id = @project.id
281
- new_feature_story.story_type = "feature"
282
- new_feature_story.current_state = "unscheduled"
283
- new_feature_story.name = new_feature_story_title
284
-
285
- args.each do |arg|
286
- new_feature_story_points = arg[2] if arg[0] == "-" && arg[1].downcase == "p"
287
- end
288
- while (new_feature_story_points.nil? || new_feature_story_points.empty?)
289
- new_feature_story_points = ask("\nPlease enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n")
290
- end
291
- while (!["0","1","2","3","n"].include?(new_feature_story_points.downcase))
292
- new_feature_story_points = ask("\nInvalid entry...Please enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n")
225
+
226
+ def estimate_story
227
+ estimate = ask("Please enter the estimate points(0/1/2/3) for this story.") do |q|
228
+ q.in = ["0", "1", "2", "3"]
229
+ q.responses[:not_in_range] = "Invalid entry...Please enter the estimate points(0/1/2/3) for this story."
230
+ end
231
+ estimate.to_i
293
232
  end
294
- if new_feature_story_points.downcase == "n"
295
- new_feature_story.estimate = -1
296
- else
297
- new_feature_story.estimate = new_feature_story_points
233
+
234
+ def estimate_story_optional
235
+ estimate = ask("Please enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n") do |q|
236
+ q.in = ["0", "1", "2", "3", "n"]
237
+ q.responses[:not_in_range] = "Invalid entry...Please enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n"
238
+ end
239
+ if estimate == "n"
240
+ estimate = nil
241
+ else
242
+ estimate.to_i
243
+ end
298
244
  end
299
245
 
246
+ def create_story_with_type_state(type, state, args)
247
+ story_title = nil
248
+ story_points = nil
300
249
 
301
- if args.any?{|arg| arg.include?("-tl") } && !(icebox_stories.empty? || icebox_stories.nil?)
302
- icebox_first_story = icebox_stories.first
303
- (new_feature_story.create).move(:before, icebox_first_story)
304
- elsif args.any?{|arg| arg.include?("-bl")} && !(icebox_stories.empty? || icebox_stories.nil?)
305
- icebox_last_story = icebox_stories.last
306
- (new_feature_story.create).move(:after, icebox_last_story)
307
- else
308
- new_feature_story.create
309
- end
310
- end
250
+ args.each {|arg| story_title = arg if arg[0] != "-" }
311
251
 
312
- def create_backlog_feature_story(args)
313
- new_feature_story_title = nil
314
- new_feature_story_points = nil
315
- args.each do |arg|
316
- new_feature_story_title = arg if arg[0] != "-"
317
- end
318
- while (new_feature_story_title.nil? || new_feature_story_title.empty?)
319
- new_feature_story_title = ask("\nPlease enter the title for this feature story")
320
- end
321
- backlog_stories = Array.new
322
- @project.stories.all.collect{|story| backlog_stories.push story if story.current_state == "unstarted" && story.story_type != "release"}
323
- new_feature_story = PivotalTracker::Story.new
324
- new_feature_story.project_id = @project.id
325
- new_feature_story.story_type = "feature"
326
- new_feature_story.current_state = "unstarted"
327
- new_feature_story.name = new_feature_story_title
328
-
329
- args.each do |arg|
330
- new_feature_story_points = arg[2] if arg[0] == "-" && arg[1].downcase == "p"
331
- end
332
- while (new_feature_story_points.nil? || new_feature_story_points.empty?)
333
- new_feature_story_points = ask("\nPlease enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n")
334
- end
335
- while (!["0","1","2","3","n"].include?(new_feature_story_points.downcase))
336
- new_feature_story_points = ask("\nInvalid entry...Please enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n")
337
- end
338
- if new_feature_story_points.downcase == "n"
339
- new_feature_story.estimate = -1
340
- else
341
- new_feature_story.estimate = new_feature_story_points
342
- end
252
+ while (story_title.nil? || story_title.empty?)
253
+ story_title = ask("Please enter the title for the story")
254
+ end
343
255
 
344
- if args.any?{|arg| arg.include?("-tl")} && !(backlog_stories.empty? || backlog_stories.nil?)
345
- backlog_first_story = backlog_stories.first
346
- (new_feature_story.create).move(:before, backlog_first_story)
347
- elsif args.any?{|arg| arg.include?("-bl")} && !(backlog_stories.empty? || backlog_stories.nil?)
348
- backlog_last_story = backlog_stories.last
349
- (new_feature_story.create).move(:after, backlog_last_story)
350
- else
351
- new_feature_story.create
352
- end
353
- end
256
+ story_params = {:story_type => type, :current_state => state, :name => story_title}
354
257
 
355
- private
258
+ # if it is a feature, get the estimate for the story.
259
+ # if it is not provided in the command line, ask for it
260
+ if type == "feature" #set the story points if it is feature story
261
+ args.each do |arg|
262
+ story_points = arg[2] if arg[0] == "-" && arg[1].downcase == "p"
263
+ end
264
+ story_points = estimate_story_optional if story_points.nil? || story_points.empty?
265
+ story_params[:estimate] = story_points unless story_points.nil?
266
+ end
356
267
 
357
- def pwd
358
- command = OS.windows? ? 'echo %cd%': 'pwd'
359
- GitPivotalTrackerIntegration::Util::Shell.exec(command).chop
360
- end
268
+ story = @project.create_story(story_params)
269
+
270
+ #move the story
271
+ stories = @project.stories(:with_state => state, :fields => 'name')
272
+
273
+ if args.any?{|arg| arg.include?("-tl") } && !(stories.empty? || stories.nil?)
274
+ story.before_id = stories.first.id
275
+ elsif args.any?{|arg| arg.include?("-bl")} && !(stories.empty? || stories.nil?)
276
+ story.after_id = stories.last.id
277
+ end
278
+
279
+ story.save
280
+ story
281
+ end
361
282
 
362
- def estimate_story(story)
363
- story_points = nil
364
- while (story_points.nil? || story_points.empty?)
365
- story_points = ask("\nPlease enter the estimate points(0/1/2/3) for this story.")
366
- end
367
- while (!["0","1","2","3"].include?(story_points))
368
- story_points = ask("\nInvalid entry...Please enter the estimate points(0/1/2/3) for this story.")
369
283
  end
370
- story.update(:estimate => story_points)
371
- end
372
284
 
285
+ end
373
286
  end