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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/story_branch.rb +81 -41
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9cc200c930d34b90699a03c634f1de29e2c599b
|
4
|
+
data.tar.gz: 7abb7d7e9c1001d9e4d1c2236925995de29ff39b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
21
|
-
|
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.
|
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
|
-
|
109
|
+
puts "Getting stories..."
|
110
|
+
stories = @p.display_stories :started, false
|
102
111
|
if stories.length < 1
|
103
|
-
puts "No stories started
|
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
|
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
|
-
|
121
|
-
stories = @p.
|
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
|
126
|
-
|
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
|
-
|
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).
|
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
|
323
|
-
"
|
352
|
+
def one_line_story s
|
353
|
+
"#{s.id} - #{s.name}"
|
324
354
|
end
|
325
355
|
|
326
356
|
def select_story stories
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
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
|
-
|
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
|
-
|
337
|
-
|
338
|
-
|
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... (
|
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 <<-
|
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
|
-
|
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,
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
Readline.
|
388
|
-
|
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.
|
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: []
|