flux 0.0.3 → 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/.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
|