tpope-pickler 0.0.4 → 0.0.5
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.
- data/README.rdoc +12 -11
- data/lib/pickler/feature.rb +1 -22
- data/lib/pickler/runner.rb +333 -68
- data/lib/pickler/tracker/iteration.rb +4 -0
- data/lib/pickler/tracker/note.rb +1 -1
- data/lib/pickler/tracker/story.rb +9 -3
- data/lib/pickler/tracker.rb +8 -4
- data/lib/pickler.rb +5 -5
- data/pickler.gemspec +1 -1
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -7,6 +7,7 @@ Synchronize user stories in Pivotal Tracker with Cucumber features.
|
|
7
7
|
gem install tpope-pickler --source=http://gems.github.com
|
8
8
|
echo "api_token: ..." > ~/.tracker.yml
|
9
9
|
echo "project_id: ..." > ~/my/app/features/tracker.yml
|
10
|
+
pickler --help
|
10
11
|
|
11
12
|
For details about the Pivotal Tracker API, including where to find your API
|
12
13
|
token and project id, see http://www.pivotaltracker.com/help/api .
|
@@ -19,9 +20,7 @@ feature's body. Keep this in mind when entering stories into Pivotal Tracker.
|
|
19
20
|
|
20
21
|
pickler pull
|
21
22
|
|
22
|
-
Download all well formed stories to the features/ directory.
|
23
|
-
unseen stories will be given a numeric filename that you are encouraged to
|
24
|
-
change.
|
23
|
+
Download all well formed stories to the features/ directory.
|
25
24
|
|
26
25
|
pickler push
|
27
26
|
|
@@ -31,19 +30,21 @@ Upload all features with a tracker url in a comment on the first line.
|
|
31
30
|
|
32
31
|
List all stories matching the given query.
|
33
32
|
|
34
|
-
pickler
|
33
|
+
pickler start <story>
|
35
34
|
|
36
|
-
|
35
|
+
Pull a given feature and change its state to started.
|
37
36
|
|
38
|
-
pickler
|
37
|
+
pickler finish <story>
|
39
38
|
|
40
|
-
|
41
|
-
and no local file exists, features/basename.feature will be created in lieu
|
42
|
-
of features/id.feature.
|
39
|
+
Push a given feature and change its state to finished.
|
43
40
|
|
44
|
-
pickler
|
41
|
+
pickler --help
|
45
42
|
|
46
|
-
|
43
|
+
Full list of commands.
|
44
|
+
|
45
|
+
pickler <command> --help
|
46
|
+
|
47
|
+
Further help for a given command.
|
47
48
|
|
48
49
|
== Disclaimer
|
49
50
|
|
data/lib/pickler/feature.rb
CHANGED
@@ -47,10 +47,8 @@ class Pickler
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def pull(default = nil)
|
50
|
-
body = "# http://www.pivotaltracker.com/story/show/#{id}\n" <<
|
51
|
-
normalize_feature(story.to_s)
|
52
50
|
filename = filename() || pickler.features_path("#{default||id}.feature")
|
53
|
-
File.open(filename,'w') {|f| f.puts
|
51
|
+
File.open(filename,'w') {|f| f.puts story}
|
54
52
|
@filename = filename
|
55
53
|
end
|
56
54
|
|
@@ -84,24 +82,5 @@ class Pickler
|
|
84
82
|
@story ||= @pickler.project.story(id) if id
|
85
83
|
end
|
86
84
|
|
87
|
-
protected
|
88
|
-
|
89
|
-
def normalize_feature(body)
|
90
|
-
return body unless ast = pickler.parser.parse(body)
|
91
|
-
feature = ast.compile
|
92
|
-
new = ''
|
93
|
-
(feature.header.chomp << "\n").each_line do |l|
|
94
|
-
new << ' ' unless new.empty?
|
95
|
-
new << l.strip << "\n"
|
96
|
-
end
|
97
|
-
feature.scenarios.each do |scenario|
|
98
|
-
new << "\n Scenario: #{scenario.name}\n"
|
99
|
-
scenario.steps.each do |step|
|
100
|
-
new << " #{step.keyword} #{step.name}\n"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
new
|
104
|
-
end
|
105
|
-
|
106
85
|
end
|
107
86
|
end
|
data/lib/pickler/runner.rb
CHANGED
@@ -1,15 +1,331 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
1
3
|
class Pickler
|
2
4
|
class Runner
|
3
5
|
|
4
|
-
|
6
|
+
class Base
|
7
|
+
attr_reader :argv
|
8
|
+
|
9
|
+
def initialize(argv)
|
10
|
+
@argv = argv
|
11
|
+
@tty = $stdout.tty?
|
12
|
+
@opts = OptionParser.new
|
13
|
+
@opts.version = "0.0"
|
14
|
+
@opts.banner = "Usage: pickler #{self.class.command_name} #{self.class.banner_arguments}"
|
15
|
+
@opts.base.long["help"] = OptionParser::Switch::NoArgument.new do
|
16
|
+
help = @opts.help.chomp.chomp + "\n"
|
17
|
+
help += "\n#{self.class.description}" if self.class.description
|
18
|
+
puts help
|
19
|
+
@exit = 0
|
20
|
+
end
|
21
|
+
@opts.separator("")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.options
|
25
|
+
@options ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.on(*args, &block)
|
29
|
+
options << args
|
30
|
+
define_method("option_#{args.object_id}", &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.banner_arguments(value = nil)
|
34
|
+
if value
|
35
|
+
@banner_arguments = value
|
36
|
+
else
|
37
|
+
@banner_arguments || (arity.zero? ? "" : "...")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.summary(value = nil)
|
42
|
+
if value
|
43
|
+
@summary = value
|
44
|
+
else
|
45
|
+
@summary
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.description(value = nil)
|
50
|
+
if value
|
51
|
+
@description = value
|
52
|
+
else
|
53
|
+
@description || "#@summary."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.command_name
|
58
|
+
name.split('::').last.gsub(/(.)([A-Z])/) {"#$1-#$2"}.downcase
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.method_name
|
62
|
+
command_name.gsub('-','_')
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.process(&block)
|
66
|
+
define_method(:process, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.arity
|
70
|
+
instance_method(:process).arity
|
71
|
+
end
|
72
|
+
|
73
|
+
def arity
|
74
|
+
self.class.arity
|
75
|
+
end
|
76
|
+
|
77
|
+
def pickler
|
78
|
+
@pickler ||= Pickler.new(Dir.getwd)
|
79
|
+
end
|
80
|
+
|
81
|
+
def abort(message)
|
82
|
+
raise Error, message
|
83
|
+
end
|
84
|
+
|
85
|
+
def too_many
|
86
|
+
abort "too many arguments"
|
87
|
+
end
|
88
|
+
|
89
|
+
def run
|
90
|
+
self.class.options.each do |arguments|
|
91
|
+
@opts.on(*arguments, &method("option_#{arguments.object_id}"))
|
92
|
+
end
|
93
|
+
begin
|
94
|
+
@opts.parse!(@argv)
|
95
|
+
rescue OptionParser::InvalidOption
|
96
|
+
abort $!.message
|
97
|
+
end
|
98
|
+
return @exit if @exit
|
99
|
+
minimum = arity < 0 ? -1 - arity : arity
|
100
|
+
if arity >= 0 && arity < @argv.size
|
101
|
+
too_many
|
102
|
+
elsif minimum > @argv.size
|
103
|
+
abort "not enough arguments"
|
104
|
+
end
|
105
|
+
process(*@argv)
|
106
|
+
end
|
107
|
+
|
108
|
+
def process(*argv)
|
109
|
+
pickler.send(self.class.method_name,*argv)
|
110
|
+
end
|
111
|
+
|
112
|
+
def color?
|
113
|
+
case pickler.config["color"]
|
114
|
+
when "always" then true
|
115
|
+
when "never" then false
|
116
|
+
else
|
117
|
+
@tty && RUBY_PLATFORM !~ /mswin|mingw/
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def puts_summary(story)
|
122
|
+
summary = "%6d " % story.id
|
123
|
+
type = story.estimate || TYPE_SYMBOLS[story.story_type]
|
124
|
+
state = STATE_SYMBOLS[story.current_state]
|
125
|
+
if color?
|
126
|
+
summary << "\e[3#{STATE_COLORS[story.current_state]}m#{state}\e[00m "
|
127
|
+
summary << "\e[01;3#{TYPE_COLORS[story.story_type]}m#{type}\e[00m "
|
128
|
+
else
|
129
|
+
summary << "#{state} #{type} "
|
130
|
+
end
|
131
|
+
summary << story.name
|
132
|
+
puts summary
|
133
|
+
end
|
134
|
+
|
135
|
+
def paginated_output
|
136
|
+
stdout = $stdout
|
137
|
+
if @tty && pager = pickler.config["pager"]
|
138
|
+
# Modeled after git
|
139
|
+
ENV["LESS"] ||= "FRSX"
|
140
|
+
IO.popen(pager,"w") do |io|
|
141
|
+
$stdout = io
|
142
|
+
yield
|
143
|
+
end
|
144
|
+
else
|
145
|
+
yield
|
146
|
+
end
|
147
|
+
ensure
|
148
|
+
$stdout = stdout
|
149
|
+
end
|
5
150
|
|
6
|
-
|
7
|
-
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.[](command)
|
154
|
+
klass_name = command.to_s.capitalize.gsub(/[-_](.)/) { $1.upcase }
|
155
|
+
if klass_name =~ /^[A-Z]\w*$/ && const_defined?(klass_name)
|
156
|
+
klass = const_get(klass_name)
|
157
|
+
if Class === klass && klass < Base
|
158
|
+
return klass
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.commands
|
164
|
+
constants.map {|c| Runner.const_get(c)}.select {|c| Class === c && c < Runner::Base}.sort_by {|r| r.command_name}.uniq
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.command(name, &block)
|
168
|
+
const_set(name.to_s.capitalize.gsub(/[-_](.)/) { $1.upcase },Class.new(Base,&block))
|
169
|
+
end
|
170
|
+
|
171
|
+
command :show do
|
172
|
+
banner_arguments "<story>"
|
173
|
+
summary "Show details for a story"
|
174
|
+
|
175
|
+
process do |*args|
|
176
|
+
case args.size
|
177
|
+
when 0
|
178
|
+
puts "#{pickler.project_id} #{pickler.project.name}"
|
179
|
+
when 1
|
180
|
+
story = pickler.project.story(args.first)
|
181
|
+
paginated_output do
|
182
|
+
puts story
|
183
|
+
end
|
184
|
+
else
|
185
|
+
too_many
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
command :search do
|
191
|
+
banner_arguments "[query]"
|
192
|
+
summary "List all stories matching a query"
|
193
|
+
|
194
|
+
def modifications
|
195
|
+
@modifications ||= {}
|
196
|
+
end
|
197
|
+
[:label, :type, :state].each do |o|
|
198
|
+
on "--#{o} #{o.to_s.upcase}" do |value|
|
199
|
+
modifications[o] = value
|
200
|
+
end
|
201
|
+
end
|
202
|
+
[:requester, :owner, :mywork].each do |o|
|
203
|
+
on "--#{o} USERNAME" do |value|
|
204
|
+
modifications[o] = value
|
205
|
+
end
|
206
|
+
end
|
207
|
+
on "--[no-]includedone", "include accepted stories" do |value|
|
208
|
+
modifications[:includedone] = value
|
209
|
+
end
|
210
|
+
|
211
|
+
attr_writer :current
|
212
|
+
on "-c", "--current", "filter results to current iteration" do |b|
|
213
|
+
self.current = b
|
214
|
+
end
|
215
|
+
|
216
|
+
process do |*argv|
|
217
|
+
argv << modifications unless modifications.empty?
|
218
|
+
if argv == [{:includedone => true}]
|
219
|
+
# Bypass the 200 search results limitation
|
220
|
+
stories = pickler.project.stories
|
221
|
+
else
|
222
|
+
stories = pickler.project.stories(*argv)
|
223
|
+
end
|
224
|
+
stories.reject! {|s| !s.current?} if argv.empty? || @current
|
225
|
+
paginated_output do
|
226
|
+
stories.each do |story|
|
227
|
+
puts_summary story
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
command :push do
|
234
|
+
banner_arguments "[story] ..."
|
235
|
+
summary "Upload stories"
|
236
|
+
description <<-EOF
|
237
|
+
Upload the given story or all features with a tracker url in a comment on the
|
238
|
+
first line.
|
239
|
+
EOF
|
240
|
+
end
|
241
|
+
|
242
|
+
command :pull do
|
243
|
+
banner_arguments "[story] ..."
|
244
|
+
summary "Download stories"
|
245
|
+
description <<-EOF
|
246
|
+
Download the given story or all well formed stories to the features/ directory.
|
247
|
+
Previously unseen stories will be given a numeric filename that you are
|
248
|
+
encouraged to change.
|
249
|
+
EOF
|
250
|
+
end
|
251
|
+
|
252
|
+
command :start do
|
253
|
+
banner_arguments "<story> [basename]"
|
254
|
+
summary "Pull a story and mark it started"
|
255
|
+
description <<-EOF
|
256
|
+
Pull a given story and change its state to started. If basename is given
|
257
|
+
and no local file exists, features/basename.feature will be created in lieu
|
258
|
+
of features/id.feature.
|
259
|
+
EOF
|
260
|
+
|
261
|
+
process do |story_id, *args|
|
262
|
+
pickler.start(story_id, args.first)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
command :finish do
|
267
|
+
banner_arguments "<story>"
|
268
|
+
summary "Push a story and mark it finished"
|
269
|
+
|
270
|
+
process do |story_id|
|
271
|
+
super
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
command :deliver do
|
276
|
+
banner_arguments "[story] ..."
|
277
|
+
summary "Mark stories delivered"
|
278
|
+
on "--all-finished", "deliver all finished stories" do
|
279
|
+
@all = true
|
280
|
+
end
|
281
|
+
process do |*args|
|
282
|
+
if @all
|
283
|
+
pickler.deliver_all_finished_stories
|
284
|
+
end
|
285
|
+
args.each do |arg|
|
286
|
+
pickler.story(arg).transition!('delivered')
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
command :browse do
|
292
|
+
banner_arguments "[story]"
|
293
|
+
summary "Open a story in the web browser"
|
294
|
+
description <<-EOF
|
295
|
+
Open project or a story in the web browser.
|
296
|
+
|
297
|
+
Requires launchy (gem install launchy).
|
298
|
+
EOF
|
299
|
+
|
300
|
+
on "--dashboard" do
|
301
|
+
@special = "dashboard"
|
302
|
+
end
|
303
|
+
on "--faq" do
|
304
|
+
@special = "help"
|
305
|
+
end
|
306
|
+
on "--profile", "get your API Token here" do
|
307
|
+
@special = "profile"
|
308
|
+
end
|
309
|
+
on "--time", "not publicly available" do
|
310
|
+
@special = "time_shifts?project=#{pickler.project_id}"
|
311
|
+
end
|
312
|
+
|
313
|
+
process do |*args|
|
314
|
+
too_many if args.size > 1 || @special && args.first
|
315
|
+
if args.first
|
316
|
+
url = pickler.story(args.first).url
|
317
|
+
elsif @special
|
318
|
+
url = "http://www.pivotaltracker.com/#@special"
|
319
|
+
else
|
320
|
+
url = "http://www.pivotaltracker.com/projects/#{pickler.project_id}/stories"
|
321
|
+
end
|
322
|
+
require 'launchy'
|
323
|
+
Launchy.open(url)
|
324
|
+
end
|
8
325
|
end
|
9
326
|
|
10
327
|
def initialize(argv)
|
11
328
|
@argv = argv
|
12
|
-
@tty = $stdout.tty?
|
13
329
|
end
|
14
330
|
|
15
331
|
COLORS = {
|
@@ -58,73 +374,22 @@ class Pickler
|
|
58
374
|
"bug" => "/"
|
59
375
|
}
|
60
376
|
|
61
|
-
def color?
|
62
|
-
case pickler.config["color"]
|
63
|
-
when "always" then true
|
64
|
-
when "never" then false
|
65
|
-
else
|
66
|
-
@tty && RUBY_PLATFORM !~ /mswin|mingw/
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def puts_summary(story)
|
71
|
-
summary = "%6d " % story.id
|
72
|
-
type = story.estimate || TYPE_SYMBOLS[story.story_type]
|
73
|
-
state = STATE_SYMBOLS[story.current_state]
|
74
|
-
if color?
|
75
|
-
summary << "\e[3#{STATE_COLORS[story.current_state]}m#{state}\e[00m "
|
76
|
-
summary << "\e[01;3#{TYPE_COLORS[story.story_type]}m#{type}\e[00m "
|
77
|
-
else
|
78
|
-
summary << "#{state} #{type} "
|
79
|
-
end
|
80
|
-
summary << story.name
|
81
|
-
puts summary
|
82
|
-
end
|
83
|
-
|
84
|
-
def paginated_output
|
85
|
-
stdout = $stdout
|
86
|
-
if @tty && pager = pickler.config["pager"]
|
87
|
-
# Modeled after git
|
88
|
-
ENV["LESS"] ||= "FRSX"
|
89
|
-
IO.popen(pager,"w") do |io|
|
90
|
-
$stdout = io
|
91
|
-
yield
|
92
|
-
end
|
93
|
-
else
|
94
|
-
yield
|
95
|
-
end
|
96
|
-
ensure
|
97
|
-
$stdout = stdout
|
98
|
-
end
|
99
|
-
|
100
377
|
def run
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
stories.each do |story|
|
112
|
-
puts_summary story
|
113
|
-
end
|
378
|
+
command = @argv.shift
|
379
|
+
if klass = self.class[command]
|
380
|
+
result = klass.new(@argv).run
|
381
|
+
exit result.respond_to?(:to_int) ? result.to_int : 0
|
382
|
+
elsif ['help', '--help', '-h', '', nil].include?(command)
|
383
|
+
puts "usage: pickler <command> [options] [arguments]"
|
384
|
+
puts
|
385
|
+
puts "Commands:"
|
386
|
+
self.class.commands.each do |command|
|
387
|
+
puts " %-19s %s" % [command.command_name, command.summary]
|
114
388
|
end
|
115
|
-
|
116
|
-
pickler
|
117
|
-
when 'pull'
|
118
|
-
pickler.pull(*argv)
|
119
|
-
when 'start'
|
120
|
-
pickler.start(argv.first,argv[1])
|
121
|
-
when 'finish'
|
122
|
-
pickler.finish(argv.first)
|
123
|
-
when 'help', '--help', '-h', '', nil
|
124
|
-
puts 'pickler commands: [show|start|finish] <id>, search <query>, push, pull'
|
389
|
+
puts
|
390
|
+
puts "Run pickler <command> --help for help with a given command"
|
125
391
|
else
|
126
|
-
|
127
|
-
exit 1
|
392
|
+
raise Error, "Unknown pickler command #{command}"
|
128
393
|
end
|
129
394
|
rescue Pickler::Error
|
130
395
|
$stderr.puts "#$!"
|
@@ -18,6 +18,10 @@ class Pickler
|
|
18
18
|
start...finish
|
19
19
|
end
|
20
20
|
|
21
|
+
def include?(date)
|
22
|
+
range.include?(date)
|
23
|
+
end
|
24
|
+
|
21
25
|
def succ
|
22
26
|
self.class.new(project, 'number' => number.succ.to_s, 'start' => @attributes['finish'], 'finish' => (finish + (finish - start)).strftime("%b %d, %Y"))
|
23
27
|
end
|
data/lib/pickler/tracker/note.rb
CHANGED
@@ -28,6 +28,10 @@ class Pickler
|
|
28
28
|
raise Pickler::Tracker::Error, Array(error).join("\n"), caller unless error == true
|
29
29
|
end
|
30
30
|
|
31
|
+
def current?(as_of = Date.today)
|
32
|
+
iteration && iteration.include?(as_of)
|
33
|
+
end
|
34
|
+
|
31
35
|
def complete?
|
32
36
|
%w(finished delivered accepted).include?(current_state)
|
33
37
|
end
|
@@ -84,14 +88,16 @@ class Pickler
|
|
84
88
|
|
85
89
|
def comment!(body)
|
86
90
|
raise ArgumentError if body.strip.empty? || body.size > 5000
|
87
|
-
response = tracker.request_xml(:post, "#{resource_url}/notes",{:text => body}.to_xml(:root => 'note'))
|
91
|
+
response = tracker.request_xml(:post, "#{resource_url}/notes",{:text => body}.to_xml(:dasherize => false, :root => 'note'))
|
88
92
|
Note.new(self, response["note"])
|
89
93
|
end
|
90
94
|
|
91
95
|
def to_xml
|
92
|
-
hash = @attributes.
|
96
|
+
hash = @attributes.reject do |k,v|
|
97
|
+
!%w(current_state deadline description estimate name owned_by requested_by story_type).include?(k)
|
98
|
+
end
|
93
99
|
hash["labels"] = Array(@attributes["labels"]).join(", ")
|
94
|
-
hash.to_xml(:root => "story")
|
100
|
+
hash.to_xml(:dasherize => false, :root => "story")
|
95
101
|
end
|
96
102
|
|
97
103
|
def destroy
|
data/lib/pickler/tracker.rb
CHANGED
@@ -12,7 +12,8 @@ class Pickler
|
|
12
12
|
attr_reader :token
|
13
13
|
|
14
14
|
def initialize(token)
|
15
|
-
require 'active_support'
|
15
|
+
require 'active_support/core_ext/blank'
|
16
|
+
require 'active_support/core_ext/hash'
|
16
17
|
@token = token
|
17
18
|
end
|
18
19
|
|
@@ -52,8 +53,11 @@ class Pickler
|
|
52
53
|
end
|
53
54
|
|
54
55
|
class Abstract
|
55
|
-
def initialize(attributes)
|
56
|
-
@attributes =
|
56
|
+
def initialize(attributes = {})
|
57
|
+
@attributes = {}
|
58
|
+
(attributes || {}).each do |k,v|
|
59
|
+
@attributes[k.to_s] = v
|
60
|
+
end
|
57
61
|
yield self if block_given?
|
58
62
|
end
|
59
63
|
|
@@ -78,7 +82,7 @@ class Pickler
|
|
78
82
|
reader :id
|
79
83
|
|
80
84
|
def to_xml(options = nil)
|
81
|
-
@attributes.to_xml({:root => self.class.name.split('::').last.downcase}.merge(options||{}))
|
85
|
+
@attributes.to_xml({:dasherize => false, :root => self.class.name.split('::').last.downcase}.merge(options||{}))
|
82
86
|
end
|
83
87
|
|
84
88
|
end
|
data/lib/pickler.rb
CHANGED
@@ -5,6 +5,10 @@ class Pickler
|
|
5
5
|
class Error < RuntimeError
|
6
6
|
end
|
7
7
|
|
8
|
+
autoload :Runner, 'pickler/runner'
|
9
|
+
autoload :Feature, 'pickler/feature'
|
10
|
+
autoload :Tracker, 'pickler/tracker'
|
11
|
+
|
8
12
|
def self.config
|
9
13
|
@config ||= {'api_token' => ENV["TRACKER_API_TOKEN"]}.merge(
|
10
14
|
if File.exist?(path = File.expand_path('~/.tracker.yml'))
|
@@ -14,7 +18,6 @@ class Pickler
|
|
14
18
|
end
|
15
19
|
|
16
20
|
def self.run(argv)
|
17
|
-
require 'pickler/runner'
|
18
21
|
Runner.new(argv).run
|
19
22
|
end
|
20
23
|
|
@@ -91,7 +94,7 @@ class Pickler
|
|
91
94
|
def pull(*args)
|
92
95
|
if args.empty?
|
93
96
|
args = project.stories(scenario_word, :includedone => true).reject do |s|
|
94
|
-
s.current_state
|
97
|
+
%(unscheduled unstarted).include?(s.current_state)
|
95
98
|
end.select do |s|
|
96
99
|
s.to_s =~ /^\s*#{Regexp.escape(scenario_word)}:/ && parser.parse(s.to_s)
|
97
100
|
end
|
@@ -120,6 +123,3 @@ class Pickler
|
|
120
123
|
protected
|
121
124
|
|
122
125
|
end
|
123
|
-
|
124
|
-
require 'pickler/feature'
|
125
|
-
require 'pickler/tracker'
|
data/pickler.gemspec
CHANGED