story_branch 0.2.0 → 0.2.1

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 (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/story_branch.rb +81 -41
  4. metadata +11 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 51fb5eb1e204d970116356bb1f2f273ac0de0804
4
- data.tar.gz: 6ae1d58a21ae39e5def105f4b58d327147fd83a9
3
+ metadata.gz: d9cc200c930d34b90699a03c634f1de29e2c599b
4
+ data.tar.gz: 7abb7d7e9c1001d9e4d1c2236925995de29ff39b
5
5
  SHA512:
6
- metadata.gz: 010f313b23b8b1604af7dd9fd679d60f9c67b8109fc4083c39932480be23f1ed544fcbe8ad5a3e488df9b3a68af67581e7e8c3a7edec2f82f7553d3650913fea
7
- data.tar.gz: 2d227dfd93c2a3655f78a512f1ee3d7adf5d57c2c41c6fb96264bd88dc738bd94185dc5c611057d1ea52d3a997704b87d14f0f24bf249e9db418714a45ad94e0
6
+ metadata.gz: dd86ebf0d42dcbc66a70ab1e4e2d9403996ddce94a422b8ae2ccd46921cd5ddb1eec096f127678f7f506604f219083be4717c2760e21b2f9390b8363c637236b
7
+ data.tar.gz: 4e7e215be23201bd48cc94fec811f76dcb87eaae3bd3214994bae5c1e3b4d25761b4638d7c36b899dd1e3bad64f378dc35e43f59adc53fdadf6da2b7ed9d850e
data/README.md CHANGED
@@ -17,8 +17,8 @@ accept. The branch will be created (the story_id will automatically
17
17
  be used as a suffix in the branch name)
18
18
 
19
19
  **git start**: Start a story in Pivotal Tracker from the terminal.
20
- List all unstarted stories in your current project. Entering a
21
- partial string will fuzzy match against the list.
20
+ Lists all unstarted stories in your current project. Select a story
21
+ from the displayed list, and it will tell Pivotal Tracker to start it.
22
22
 
23
23
  **git finish**: Create a finishing commit + message, for example:
24
24
  "[Finishes #1234567] My Story Title" - optionally Finishes the story
data/lib/story_branch.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Dominic Wong <dominic.wong.617@gmail.com>
6
6
  # Gabe Hollombe <gabe@neo.com>
7
7
  #
8
- # Version: 0.2.0
8
+ # Version: 0.2.1
9
9
  #
10
10
  # ## Description
11
11
  #
@@ -77,10 +77,17 @@ require 'git'
77
77
  require 'active_support/core_ext/string/inflections'
78
78
  require 'levenshtein'
79
79
 
80
+ trap('INT') {exit}
81
+
80
82
  module StoryBranch
81
83
 
82
84
  class Main
83
85
 
86
+ ERRORS = {
87
+ "Stories in the started state must be estimated." =>
88
+ "Error: Pivotal won't allow you to start an unestimated story"
89
+ }
90
+
84
91
  PIVOTAL_CONFIG_FILES = ['.story_branch',"#{ENV['HOME']}/.story_branch"]
85
92
 
86
93
  attr_accessor :p
@@ -97,13 +104,14 @@ module StoryBranch
97
104
 
98
105
  def create_story_branch
99
106
  begin
107
+ puts "Connecting with Pivotal Tracker"
100
108
  @p.get_project
101
- stories = @p.display_stories :started
109
+ puts "Getting stories..."
110
+ stories = @p.display_stories :started, false
102
111
  if stories.length < 1
103
- puts "No stories started... exiting"
112
+ puts "No stories started, exiting"
104
113
  exit
105
114
  end
106
- puts "[0] Exit"
107
115
  story = @p.select_story stories
108
116
  if story
109
117
  @p.create_feature_branch story
@@ -114,16 +122,20 @@ module StoryBranch
114
122
  end
115
123
  end
116
124
 
117
- def story_start
125
+ def pick_and_update filter, hash, msg, is_estimated
118
126
  begin
127
+ puts "Connecting with Pivotal Tracker"
119
128
  @p.get_project
120
- # TODO: Use a predicate for Estimated and Backlog'ed stories
121
- stories = @p.display_stories :unstarted
122
- puts "[0] Exit"
129
+ puts "Getting stories..."
130
+ stories = @p.filtered_stories_list filter, is_estimated
123
131
  story = @p.select_story stories
124
132
  if story
125
- story.update :current_state => "started"
126
- puts "#{story.id} started"
133
+ result = story.update hash
134
+ if result.errors.count > 0
135
+ puts result.errors.to_a.uniq.map{|e| ERRORS[e] }
136
+ return nil
137
+ end
138
+ puts "#{story.id} #{msg}"
127
139
  end
128
140
  rescue RestClient::Unauthorized
129
141
  puts "Pivotal API key or Project ID invalid"
@@ -131,16 +143,24 @@ module StoryBranch
131
143
  end
132
144
  end
133
145
 
146
+ def story_start
147
+ pick_and_update(:unstarted, {:current_state => "started"}, "started", true)
148
+ end
149
+
134
150
  def story_unstart
135
- # TODO: unstart a started story.
151
+ pick_and_update(:started, {:current_state => "unstarted"}, "unstarted", false)
152
+ end
153
+
154
+ def story_estimate
155
+ # TODO: estimate a story
136
156
  end
137
157
 
138
158
  def story_finish
139
159
  begin
160
+ puts "Connecting with Pivotal Tracker"
140
161
  @p.get_project
141
162
  unless @p.is_current_branch_a_story?
142
- puts "Your current branch: #{GitUtils.current_branch}"
143
- puts "is not linked to a started story."
163
+ puts "Your current branch: '#{GitUtils.current_branch}' is not linked to a Pivotal Tracker story."
144
164
  return
145
165
  end
146
166
 
@@ -158,7 +178,7 @@ module StoryBranch
158
178
  end
159
179
 
160
180
  puts "Use standard finishing commit message: [y/N]?"
161
- commit_message = "[Finishes ##{GitUtils.current_branch_story_parts[:id]}] #{GitUtils.current_branch_story_parts[:description]}"
181
+ commit_message = "[Finishes ##{GitUtils.current_branch_story_parts[:id]}] #{GitUtils.current_branch_story_parts[:description].StringUtils.undashed}"
162
182
  puts commit_message
163
183
 
164
184
  if gets.chomp!.downcase == "y"
@@ -202,6 +222,10 @@ module StoryBranch
202
222
  s.tr '\'"%!@#$(){}[]*\\?', ''
203
223
  end
204
224
 
225
+ def self.undashed s
226
+ s.underscore.humanize
227
+ end
228
+
205
229
  end
206
230
 
207
231
  class GitUtils
@@ -297,8 +321,9 @@ module StoryBranch
297
321
  end
298
322
 
299
323
  def is_current_branch_a_story?
324
+ GitUtils.current_story and
300
325
  GitUtils.current_story.length == 3 and
301
- filtered_stories_list(:started).map(&:id).include? GitUtils.current_story[2].to_i
326
+ filtered_stories_list(:started, true).map(&:id).include? GitUtils.current_story[2].to_i
302
327
  end
303
328
 
304
329
  def story_from_current_branch
@@ -310,32 +335,46 @@ module StoryBranch
310
335
  # Filtering on tags/labels
311
336
  # Filtering on estimation (estimated?, 0 point, 1 point etc.)
312
337
 
313
- def filtered_stories_list state
338
+ def filtered_stories_list state, estimated
314
339
  project = get_project
315
- project.stories.all({current_state: state})
340
+ stories = project.stories.all({current_state: state})
341
+ if estimated
342
+ stories.select{|s| s.estimate and s.estimate > 1 }
343
+ else
344
+ stories
345
+ end
316
346
  end
317
347
 
318
- def display_stories state
319
- filtered_stories_list(state).each_with_index {|s,i| puts one_line_story s, i}
348
+ def display_stories state, estimated
349
+ filtered_stories_list(state, estimated).each {|s| puts one_line_story s }
320
350
  end
321
351
 
322
- def one_line_story s, i
323
- "[#{i+1}] ##{s.id} : #{s.name}"
352
+ def one_line_story s
353
+ "#{s.id} - #{s.name}"
324
354
  end
325
355
 
326
356
  def select_story stories
327
- story_selection = nil
328
- while story_selection == nil or story_selection.to_i > stories.length + 1
329
- puts "invalid selection" if story_selection != nil
330
- story_texts = Range.new(1,stories.length).to_a.map(&:to_s)
331
- story_selection = readline("Select a story: ", story_texts)
357
+ story_texts = stories.map{|s| one_line_story s }
358
+ puts "Leave blank to exit, use <up>/<down> to scroll through stories, TAB to list all and auto-complete"
359
+ story_selection = readline("Select a story: ", story_texts)
360
+ if story_selection == "" or story_selection.nil?
361
+ return nil
332
362
  end
333
- if story_selection.to_i == 0
363
+ story = stories.select{|s| story_matcher s, story_selection }.first
364
+ if story.nil?
365
+ puts "Not found: #{story_selection}"
334
366
  return nil
367
+ else
368
+ puts "Selected : #{one_line_story story}"
369
+ return story
335
370
  end
336
- story = stories[story_selection.to_i - 1]
337
- puts "Selected : ##{story.id} : #{story.name}"
338
- return story
371
+ end
372
+
373
+ def story_matcher story, selection
374
+ m = selection.match(/^(\d*) /)
375
+ return false unless m
376
+ id = m.captures.first
377
+ return story.id.to_s == id
339
378
  end
340
379
 
341
380
  def create_feature_branch story
@@ -343,7 +382,7 @@ module StoryBranch
343
382
  feature_branch_name = nil
344
383
  puts "You are checked out at: #{GitUtils.current_branch}"
345
384
  while feature_branch_name == nil or feature_branch_name == ""
346
- puts "Provide a new branch name... (C-p or <up> for suggested name)" if [nil, ""].include? feature_branch_name
385
+ puts "Provide a new branch name... (TAB for suggested name)" if [nil, ""].include? feature_branch_name
347
386
  feature_branch_name = readline("Name of feature branch: ", [dashed_story_name])
348
387
  end
349
388
  feature_branch_name.chomp!
@@ -361,14 +400,14 @@ module StoryBranch
361
400
  end
362
401
  existing_name_score = GitUtils.is_existing_branch?(name)
363
402
  unless existing_name_score == -1
364
- puts <<-END.strip_heredoc
403
+ puts <<-EOD.strip_heredoc
365
404
  Name Collision Error:
366
405
 
367
406
  #{name}
368
407
 
369
408
  This is too similar to the name of an existing
370
409
  branch, a more unique name is required
371
- END
410
+ EOD
372
411
  end
373
412
  end
374
413
 
@@ -379,15 +418,16 @@ module StoryBranch
379
418
  name.match valid
380
419
  end
381
420
 
382
- def readline prompt, history=[]
383
- if history.length > 0
384
- history.each {|i| Readline::HISTORY.push i}
385
- end
386
- begin
387
- Readline.readline(prompt, false)
388
- rescue Interrupt
421
+ def readline prompt, completions=[]
422
+ # Store the state of the terminal
423
+ Readline::HISTORY.clear
424
+ if completions.length > 0
425
+ completions.each {|i| Readline::HISTORY.push i}
426
+ Readline.special_prefixes = " .{}()[]!?\"'_-#@$%^&*"
427
+ Readline.completion_proc = proc {|s| completions.grep(/#{Regexp.escape(s)}/) }
428
+ Readline.completion_append_character = ""
389
429
  end
430
+ Readline.readline(prompt, false)
390
431
  end
391
-
392
432
  end
393
433
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: story_branch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Milkins
@@ -17,56 +17,56 @@ dependencies:
17
17
  name: pivotal-tracker
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - "~>"
20
+ - - ~>
21
21
  - !ruby/object:Gem::Version
22
22
  version: '0.5'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - "~>"
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0.5'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: git
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
- - - "~>"
34
+ - - ~>
35
35
  - !ruby/object:Gem::Version
36
36
  version: '1.2'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
- - - "~>"
41
+ - - ~>
42
42
  - !ruby/object:Gem::Version
43
43
  version: '1.2'
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: levenshtein-ffi
46
46
  requirement: !ruby/object:Gem::Requirement
47
47
  requirements:
48
- - - "~>"
48
+ - - ~>
49
49
  - !ruby/object:Gem::Version
50
50
  version: '1.0'
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - "~>"
55
+ - - ~>
56
56
  - !ruby/object:Gem::Version
57
57
  version: '1.0'
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
60
  requirement: !ruby/object:Gem::Requirement
61
61
  requirements:
62
- - - "~>"
62
+ - - ~>
63
63
  - !ruby/object:Gem::Version
64
64
  version: '3.0'
65
65
  type: :development
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
- - - "~>"
69
+ - - ~>
70
70
  - !ruby/object:Gem::Version
71
71
  version: '3.0'
72
72
  description: Simple gem that fetches the available stories in your pivotaltracker
@@ -120,12 +120,12 @@ require_paths:
120
120
  - lib
121
121
  required_ruby_version: !ruby/object:Gem::Requirement
122
122
  requirements:
123
- - - ">="
123
+ - - '>='
124
124
  - !ruby/object:Gem::Version
125
125
  version: 1.9.3
126
126
  required_rubygems_version: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - ">="
128
+ - - '>='
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
131
  requirements: []