flux 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.flux.local.rb.sample +3 -0
- data/.flux.rb.sample +4 -0
- data/Gemfile +2 -0
- data/README.md +52 -2
- data/VERSION +1 -1
- data/flux.gemspec +18 -11
- data/lib/flux.rb +27 -31
- data/lib/flux/cli.rb +3 -0
- data/lib/flux/cli/feature.rb +39 -0
- data/lib/flux/cli/pivotal_tracker.rb +72 -0
- data/lib/flux/cli/review.rb +190 -0
- data/lib/flux/git.rb +81 -0
- data/lib/flux/pivotal_tracker.rb +81 -0
- data/lib/flux/rcs.rb +1 -0
- data/lib/flux/rcs/git.rb +132 -15
- data/lib/flux/util.rb +0 -1
- data/lib/flux/workflows/mojotech.rb +23 -17
- data/spec/flux_spec.rb +17 -28
- metadata +51 -28
- data/.flux +0 -9
- data/.flux.local.sample +0 -3
- data/lib/flux/trackers/pivotal_tracker.rb +0 -146
- data/lib/flux/util/table.rb +0 -99
- data/spec/flux/rcs/git_spec.rb +0 -47
- data/spec/flux/trackers/pivotal_tracker_spec.rb +0 -164
- data/spec/flux/util/table_spec.rb +0 -47
- data/spec/support/matchers/print_table.rb +0 -46
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flux
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-02-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
16
|
-
requirement: &
|
16
|
+
requirement: &76495720 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.14.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *76495720
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: pivotal-tracker
|
27
|
-
requirement: &
|
27
|
+
requirement: &76494370 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.4.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *76494370
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: grit
|
38
|
-
requirement: &
|
38
|
+
requirement: &76510480 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,32 @@ dependencies:
|
|
43
43
|
version: 2.4.0
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *76510480
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: hirb
|
49
|
+
requirement: &76509210 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *76509210
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: github_api
|
60
|
+
requirement: &76504870 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *76504870
|
47
69
|
- !ruby/object:Gem::Dependency
|
48
70
|
name: rspec
|
49
|
-
requirement: &
|
71
|
+
requirement: &76516560 !ruby/object:Gem::Requirement
|
50
72
|
none: false
|
51
73
|
requirements:
|
52
74
|
- - ~>
|
@@ -54,10 +76,10 @@ dependencies:
|
|
54
76
|
version: '2.0'
|
55
77
|
type: :development
|
56
78
|
prerelease: false
|
57
|
-
version_requirements: *
|
79
|
+
version_requirements: *76516560
|
58
80
|
- !ruby/object:Gem::Dependency
|
59
81
|
name: bundler
|
60
|
-
requirement: &
|
82
|
+
requirement: &76529460 !ruby/object:Gem::Requirement
|
61
83
|
none: false
|
62
84
|
requirements:
|
63
85
|
- - ~>
|
@@ -65,10 +87,10 @@ dependencies:
|
|
65
87
|
version: 1.0.0
|
66
88
|
type: :development
|
67
89
|
prerelease: false
|
68
|
-
version_requirements: *
|
90
|
+
version_requirements: *76529460
|
69
91
|
- !ruby/object:Gem::Dependency
|
70
92
|
name: jeweler
|
71
|
-
requirement: &
|
93
|
+
requirement: &76525990 !ruby/object:Gem::Requirement
|
72
94
|
none: false
|
73
95
|
requirements:
|
74
96
|
- - ~>
|
@@ -76,10 +98,10 @@ dependencies:
|
|
76
98
|
version: 1.6.2
|
77
99
|
type: :development
|
78
100
|
prerelease: false
|
79
|
-
version_requirements: *
|
101
|
+
version_requirements: *76525990
|
80
102
|
- !ruby/object:Gem::Dependency
|
81
103
|
name: rcov
|
82
|
-
requirement: &
|
104
|
+
requirement: &76524520 !ruby/object:Gem::Requirement
|
83
105
|
none: false
|
84
106
|
requirements:
|
85
107
|
- - ! '>='
|
@@ -87,10 +109,10 @@ dependencies:
|
|
87
109
|
version: '0'
|
88
110
|
type: :development
|
89
111
|
prerelease: false
|
90
|
-
version_requirements: *
|
112
|
+
version_requirements: *76524520
|
91
113
|
- !ruby/object:Gem::Dependency
|
92
114
|
name: rr
|
93
|
-
requirement: &
|
115
|
+
requirement: &76523420 !ruby/object:Gem::Requirement
|
94
116
|
none: false
|
95
117
|
requirements:
|
96
118
|
- - ~>
|
@@ -98,7 +120,7 @@ dependencies:
|
|
98
120
|
version: 1.0.0
|
99
121
|
type: :development
|
100
122
|
prerelease: false
|
101
|
-
version_requirements: *
|
123
|
+
version_requirements: *76523420
|
102
124
|
description:
|
103
125
|
email: david@mojotech.com
|
104
126
|
executables:
|
@@ -109,8 +131,8 @@ extra_rdoc_files:
|
|
109
131
|
- README.md
|
110
132
|
files:
|
111
133
|
- .document
|
112
|
-
- .flux
|
113
|
-
- .flux.
|
134
|
+
- .flux.local.rb.sample
|
135
|
+
- .flux.rb.sample
|
114
136
|
- .rspec
|
115
137
|
- Gemfile
|
116
138
|
- LICENSE.txt
|
@@ -120,19 +142,20 @@ files:
|
|
120
142
|
- bin/flux
|
121
143
|
- flux.gemspec
|
122
144
|
- lib/flux.rb
|
145
|
+
- lib/flux/cli.rb
|
146
|
+
- lib/flux/cli/feature.rb
|
147
|
+
- lib/flux/cli/pivotal_tracker.rb
|
148
|
+
- lib/flux/cli/review.rb
|
123
149
|
- lib/flux/ext/pivotal-tracker.rb
|
150
|
+
- lib/flux/git.rb
|
151
|
+
- lib/flux/pivotal_tracker.rb
|
152
|
+
- lib/flux/rcs.rb
|
124
153
|
- lib/flux/rcs/git.rb
|
125
|
-
- lib/flux/trackers/pivotal_tracker.rb
|
126
154
|
- lib/flux/util.rb
|
127
155
|
- lib/flux/util/output.rb
|
128
|
-
- lib/flux/util/table.rb
|
129
156
|
- lib/flux/workflows/mojotech.rb
|
130
|
-
- spec/flux/rcs/git_spec.rb
|
131
|
-
- spec/flux/trackers/pivotal_tracker_spec.rb
|
132
|
-
- spec/flux/util/table_spec.rb
|
133
157
|
- spec/flux_spec.rb
|
134
158
|
- spec/spec_helper.rb
|
135
|
-
- spec/support/matchers/print_table.rb
|
136
159
|
- spec/support/rr.rb
|
137
160
|
homepage: http://github.com/mojotech/flux
|
138
161
|
licenses:
|
@@ -149,7 +172,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
149
172
|
version: '0'
|
150
173
|
segments:
|
151
174
|
- 0
|
152
|
-
hash:
|
175
|
+
hash: 863655699
|
153
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
177
|
none: false
|
155
178
|
requirements:
|
@@ -158,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
181
|
version: '0'
|
159
182
|
requirements: []
|
160
183
|
rubyforge_project:
|
161
|
-
rubygems_version: 1.8.
|
184
|
+
rubygems_version: 1.8.11
|
162
185
|
signing_key:
|
163
186
|
specification_version: 3
|
164
187
|
summary: Command line workflow manager.
|
data/.flux
DELETED
data/.flux.local.sample
DELETED
@@ -1,146 +0,0 @@
|
|
1
|
-
require 'pivotal-tracker'
|
2
|
-
require 'flux/ext/pivotal-tracker'
|
3
|
-
|
4
|
-
module Flux
|
5
|
-
module Trackers
|
6
|
-
class PivotalTracker < Thor
|
7
|
-
include Flux::Util
|
8
|
-
|
9
|
-
namespace :stories
|
10
|
-
|
11
|
-
default_task :list
|
12
|
-
|
13
|
-
desc "list", "list stories, excluding icebox by default"
|
14
|
-
def list
|
15
|
-
list_stories pt::Iteration.
|
16
|
-
current_backlog(fake_project).map { |i| i.stories }.flatten
|
17
|
-
end
|
18
|
-
|
19
|
-
desc "finish STORY_ID", "finish the given story"
|
20
|
-
method_option :estimate, :type => :numeric, :aliases => '-e'
|
21
|
-
def finish(story_id)
|
22
|
-
update_state story_id, 'finished'
|
23
|
-
end
|
24
|
-
|
25
|
-
desc "grab STORY_ID", "assign yourself the given story"
|
26
|
-
method_option :estimate, :type => :numeric, :aliases => '-e'
|
27
|
-
def grab(story_id)
|
28
|
-
attrs = {:owner => me.name}
|
29
|
-
attrs[:estimate] = options[:estimate] if options[:estimate]
|
30
|
-
|
31
|
-
update_attributes story_id, attrs
|
32
|
-
end
|
33
|
-
|
34
|
-
desc "start STORY_ID", "start the given story"
|
35
|
-
method_option :estimate, :type => :numeric, :aliases => '-e'
|
36
|
-
def start(story_id)
|
37
|
-
update_state story_id, 'started'
|
38
|
-
end
|
39
|
-
|
40
|
-
STATES_W_ESTIMATE = %w(started finished delivered accepted rejected)
|
41
|
-
STATES = %w(unscheduled unstarted) + STATES_W_ESTIMATE
|
42
|
-
|
43
|
-
MAPPINGS = Hash.new { |h, k| h[k] = k }
|
44
|
-
MAPPINGS['owner'] = 'owned_by'
|
45
|
-
MAPPINGS['state'] = 'current_state'
|
46
|
-
|
47
|
-
desc "update STORY_ID", "update a story's attributes"
|
48
|
-
method_option :attributes, :type => :hash, :required => true
|
49
|
-
def update(story_id)
|
50
|
-
update_attributes story_id, options[:attributes]
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def config
|
56
|
-
Flux.environment['trackers']
|
57
|
-
end
|
58
|
-
|
59
|
-
def fake_project
|
60
|
-
@fp ||= OpenStruct.new(:id => config['project_id'])
|
61
|
-
end
|
62
|
-
|
63
|
-
def fake_story(id)
|
64
|
-
pt::Story.new(:id => id,
|
65
|
-
:project_id => config['project_id'])
|
66
|
-
end
|
67
|
-
|
68
|
-
STORY_LIST_HEADERS = %w(ID STATE ASSIGNEE >EST. STORY)
|
69
|
-
|
70
|
-
def list_stories(stories)
|
71
|
-
puts_table [STORY_LIST_HEADERS] + stories.map { |s|
|
72
|
-
[s.id,
|
73
|
-
s.current_state,
|
74
|
-
s.owned_by,
|
75
|
-
normalize_estimate(s.estimate).to_s,
|
76
|
-
s.name.strip]
|
77
|
-
}
|
78
|
-
end
|
79
|
-
|
80
|
-
def login
|
81
|
-
::PivotalTracker::Client.token = config['token']
|
82
|
-
end
|
83
|
-
|
84
|
-
def me
|
85
|
-
ms = pt::Membership.all(fake_project)
|
86
|
-
|
87
|
-
ms.find { |m| m.email == config['email'] }
|
88
|
-
end
|
89
|
-
|
90
|
-
def normalize_estimate(estimate)
|
91
|
-
(estimate && estimate < 0) ? nil : estimate
|
92
|
-
end
|
93
|
-
|
94
|
-
def pt
|
95
|
-
login and return ::PivotalTracker
|
96
|
-
end
|
97
|
-
|
98
|
-
def story(id)
|
99
|
-
pt::Story.find(id, config['project_id'])
|
100
|
-
end
|
101
|
-
|
102
|
-
def story!(id)
|
103
|
-
story(id) or raise TrackerError, "Couldn't find story #{id}."
|
104
|
-
end
|
105
|
-
|
106
|
-
def update_attributes(story_id, attrs)
|
107
|
-
story = story!(story_id)
|
108
|
-
native, custom =
|
109
|
-
attrs.
|
110
|
-
map { |k, v| [MAPPINGS[k.to_s], v] }.
|
111
|
-
partition { |(k, v)| story.respond_to?("#{k}=") }
|
112
|
-
|
113
|
-
native_h = Hash[*native.flatten]
|
114
|
-
|
115
|
-
if native_h['current_state']
|
116
|
-
unless STATES.include?(native_h['current_state'])
|
117
|
-
raise TrackerError, "Invalid state: #{native_h['current_state']}"
|
118
|
-
end
|
119
|
-
|
120
|
-
if STATES_W_ESTIMATE.include?(native_h['current_state']) &&
|
121
|
-
! normalize_estimate(story.estimate) &&
|
122
|
-
! native_h['estimate']
|
123
|
-
raise TrackerError,
|
124
|
-
"Need an estimate for state `#{native_h['current_state']}'."
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
story.update(native_h) unless native.empty?
|
129
|
-
|
130
|
-
unless custom.empty?
|
131
|
-
str = YAML.dump(Hash[*custom.flatten])
|
132
|
-
|
133
|
-
pt::Note.new(:owner => story, :text => str).create
|
134
|
-
end
|
135
|
-
|
136
|
-
end
|
137
|
-
|
138
|
-
def update_state(story_id, state)
|
139
|
-
attrs = {:state => state}
|
140
|
-
attrs[:estimate] = options[:estimate] if options[:estimate]
|
141
|
-
|
142
|
-
update_attributes story_id, attrs
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
data/lib/flux/util/table.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
module Flux
|
2
|
-
module Util
|
3
|
-
# Initialize a new Table.
|
4
|
-
#
|
5
|
-
# @param [Array<Array>] raw_data the table's annotated data
|
6
|
-
# @param field_sep the string used to separate columns
|
7
|
-
# @param [Integer] max_width the maximum width for this table.
|
8
|
-
# Lines exceeding this width will be truncated.
|
9
|
-
# @param shell the shell object used by the current task
|
10
|
-
def puts_table(raw_data, field_sep = ' ', max_width = nil)
|
11
|
-
$stdout.puts Table.new(shell, raw_data, field_sep, max_width)
|
12
|
-
end
|
13
|
-
|
14
|
-
# A table pretty printer that allows us to take a peek at the data after
|
15
|
-
# it's been stripped of formatting information. It exists to make testing
|
16
|
-
# easier.
|
17
|
-
#
|
18
|
-
# If any cell in the first row is prefixed with '>', then that column's
|
19
|
-
# contents will be right-aligned. This is useful when showing numbers.
|
20
|
-
class Table
|
21
|
-
ALIGN_RIGHT = '>'
|
22
|
-
|
23
|
-
attr_reader :field_sep, :raw_data, :shell, :max_width
|
24
|
-
|
25
|
-
# @see Flux::Util#puts_table
|
26
|
-
def initialize(shell, raw_data, field_sep, max_width)
|
27
|
-
@shell = shell
|
28
|
-
@raw_data = raw_data
|
29
|
-
@field_sep = field_sep
|
30
|
-
@max_width = max_width || terminal_width
|
31
|
-
end
|
32
|
-
|
33
|
-
# @return whether a given column's contents will be aligned to the right
|
34
|
-
def align_right?(index)
|
35
|
-
meta[index].include?(ALIGN_RIGHT)
|
36
|
-
end
|
37
|
-
|
38
|
-
# @return all rows but the first
|
39
|
-
def body
|
40
|
-
@body ||= raw_data[1..-1]
|
41
|
-
end
|
42
|
-
|
43
|
-
# @return the table data, stripped of format information
|
44
|
-
def data
|
45
|
-
@data ||= body.unshift(headers)
|
46
|
-
end
|
47
|
-
|
48
|
-
# @return the table's first row
|
49
|
-
def headers
|
50
|
-
@headers = raw_data.first.each_with_index.map { |e, i|
|
51
|
-
align_right?(i) ? e[1..-1] : e
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
# @return the table's format information
|
56
|
-
def meta
|
57
|
-
@meta ||= @raw_data.first.inject([]) { |a, e|
|
58
|
-
a << (e =~ /^>/ ? ALIGN_RIGHT : '')
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
def to_s
|
63
|
-
@s ||=
|
64
|
-
begin
|
65
|
-
widths = data.transpose.inject([]) { |a, col|
|
66
|
-
a << col.max { |a, b| a.to_s.size <=> b.to_s.size }.to_s.size
|
67
|
-
}
|
68
|
-
|
69
|
-
# we don't need the last column's width if it is to be left-aligned
|
70
|
-
widths[-1] = nil unless align_right?(-1)
|
71
|
-
|
72
|
-
format = meta.each_with_index.inject('') { |a, (e, i)|
|
73
|
-
w = widths[i] ? widths[i].to_s : ''
|
74
|
-
align = align_right?(i) ? '' : '-'
|
75
|
-
|
76
|
-
a << "#{field_sep}%" << align << w << 's'
|
77
|
-
}.strip
|
78
|
-
|
79
|
-
max_width
|
80
|
-
|
81
|
-
data.inject('') { |a, r|
|
82
|
-
l =
|
83
|
-
a << truncate(format % r, max_width) << "\n"
|
84
|
-
}
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
def truncate(string, width)
|
91
|
-
shell.send(:truncate, string, width)
|
92
|
-
end
|
93
|
-
|
94
|
-
def terminal_width
|
95
|
-
shell.send(:terminal_width)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|