schubert-minglr 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -0
- data/VERSION.yml +2 -2
- data/bin/minglr +11 -11
- data/bin/mtx +1 -1
- data/lib/minglr.rb +18 -10
- data/lib/minglr/action.rb +75 -0
- data/lib/minglr/config_parser.rb +49 -0
- data/lib/minglr/extensions/array.rb +23 -0
- data/lib/minglr/input_cache.rb +3 -3
- data/lib/minglr/options_parser.rb +79 -0
- data/lib/minglr/resources/attachment.rb +46 -0
- data/lib/minglr/resources/base.rb +42 -0
- data/lib/minglr/resources/card.rb +107 -0
- data/lib/minglr/resources/project.rb +25 -0
- data/lib/minglr/resources/property_definition.rb +12 -0
- data/lib/minglr/resources/transition_execution.rb +6 -0
- data/lib/minglr/resources/user.rb +25 -0
- data/minglr.gemspec +30 -28
- data/minglrconfig.sample +19 -0
- data/test/extensions/array_test.rb +41 -0
- data/test/resources/attachment_test.rb +40 -0
- data/test/resources/base_test.rb +45 -0
- data/test/resources/card_test.rb +89 -0
- data/test/resources/project_test.rb +26 -0
- data/test/resources/property_definition_test.rb +25 -0
- data/test/resources/user_test.rb +39 -0
- data/test/test_helper.rb +15 -5
- metadata +27 -15
- data/lib/minglr/attachment.rb +0 -7
- data/lib/minglr/card.rb +0 -2
- data/lib/minglr/mingle_resource.rb +0 -5
- data/lib/minglr/minglr_action.rb +0 -200
- data/lib/minglr/minglr_config_parser.rb +0 -44
- data/lib/minglr/minglr_options_parser.rb +0 -70
- data/lib/minglr/property_definition.rb +0 -2
- data/lib/minglr/transition_execution.rb +0 -2
- data/lib/minglr/user.rb +0 -2
- data/test/attachment_test.rb +0 -24
- data/test/minglr_resource_test.rb +0 -24
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Resources
|
4
|
+
|
5
|
+
class ProjectTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context Project do
|
8
|
+
|
9
|
+
context "configure" do
|
10
|
+
|
11
|
+
should "subtract the project name from the url" do
|
12
|
+
options = { :username => "user",
|
13
|
+
:password => "pass",
|
14
|
+
:url => "proto://somehost.com:1234/projects/my_project" }
|
15
|
+
Base.configure(options)
|
16
|
+
Project.configure
|
17
|
+
assert_equal "/projects", Project.prefix
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Resources
|
4
|
+
|
5
|
+
class PropertyDefinitionTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context PropertyDefinition do
|
8
|
+
|
9
|
+
context "project_options" do
|
10
|
+
|
11
|
+
should "collect all property definitions into an array of arrays" do
|
12
|
+
property1 = stub("PropertyDefinition", :column_name => "cp_name", :name => "Name")
|
13
|
+
property2 = stub("PropertyDefinition", :column_name => "cp_accepted_on_iteration_card_id", :name => "Accepted in Iteration")
|
14
|
+
PropertyDefinition.expects(:find).with(:all).returns([property1, property2])
|
15
|
+
|
16
|
+
assert_equal PropertyDefinition.project_options, [[:cp_name, "Name"], [:cp_accepted_on_iteration_card_id, "Accepted in Iteration"]]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Resources
|
4
|
+
|
5
|
+
class UserTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context User do
|
8
|
+
|
9
|
+
context "print_all" do
|
10
|
+
|
11
|
+
should "warn if there are no users" do
|
12
|
+
User.expects(:find).with(:all).returns([])
|
13
|
+
User.expects(:warn).with("No users in project")
|
14
|
+
User.print_all
|
15
|
+
end
|
16
|
+
|
17
|
+
should "print the users found with format" do
|
18
|
+
user1 = stub("UserXml", :user => stub("User", :login => "user1", :name => "User One", :email => "user1@test"))
|
19
|
+
user2 = stub("UserXml", :user => stub("User", :login => "user22", :name => "User TwoTwo", :email => "user22@test"))
|
20
|
+
User.expects(:find).with(:all).returns([user1, user2])
|
21
|
+
User.expects(:puts).with(" user1 - User One - user1@test")
|
22
|
+
User.expects(:puts).with("user22 - User TwoTwo - user22@test")
|
23
|
+
User.print_all
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
context "find_user_id_for_user" do
|
29
|
+
|
30
|
+
should_eventually "return the owner_id of the user matching the username" do
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,10 +1,20 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
1
|
+
require "rubygems"
|
2
|
+
require "test/unit"
|
3
|
+
begin
|
4
|
+
require "shoulda"
|
5
|
+
rescue LoadError
|
6
|
+
puts "Missing shoulda: sudo gem install thoughtbot-shoulda --source=http://gems.github.com/"
|
7
|
+
end
|
8
|
+
begin
|
9
|
+
require "mocha"
|
10
|
+
rescue LoadError
|
11
|
+
puts "Missing mocha: sudo gem install mocha"
|
12
|
+
end
|
4
13
|
|
5
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
6
15
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
-
|
16
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__), "resources")
|
17
|
+
require "minglr"
|
8
18
|
|
9
19
|
class Test::Unit::TestCase
|
10
20
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schubert-minglr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Schubert
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2009-07-
|
14
|
+
date: 2009-07-26 00:00:00 -07:00
|
15
15
|
default_executable:
|
16
16
|
dependencies: []
|
17
17
|
|
@@ -36,23 +36,30 @@ files:
|
|
36
36
|
- bin/minglr
|
37
37
|
- bin/mtx
|
38
38
|
- lib/minglr.rb
|
39
|
-
- lib/minglr/
|
40
|
-
- lib/minglr/
|
39
|
+
- lib/minglr/action.rb
|
40
|
+
- lib/minglr/config_parser.rb
|
41
|
+
- lib/minglr/extensions/array.rb
|
41
42
|
- lib/minglr/input_cache.rb
|
42
|
-
- lib/minglr/mingle_resource.rb
|
43
|
-
- lib/minglr/minglr_action.rb
|
44
|
-
- lib/minglr/minglr_config_parser.rb
|
45
|
-
- lib/minglr/minglr_options_parser.rb
|
46
43
|
- lib/minglr/mtx_options_parser.rb
|
47
|
-
- lib/minglr/
|
48
|
-
- lib/minglr/
|
49
|
-
- lib/minglr/
|
44
|
+
- lib/minglr/options_parser.rb
|
45
|
+
- lib/minglr/resources/attachment.rb
|
46
|
+
- lib/minglr/resources/base.rb
|
47
|
+
- lib/minglr/resources/card.rb
|
48
|
+
- lib/minglr/resources/project.rb
|
49
|
+
- lib/minglr/resources/property_definition.rb
|
50
|
+
- lib/minglr/resources/transition_execution.rb
|
51
|
+
- lib/minglr/resources/user.rb
|
50
52
|
- minglr.gemspec
|
51
53
|
- minglrconfig.sample
|
52
54
|
- tasks/commit.sample.rake
|
53
55
|
- tasks/svn.sample.rake
|
54
|
-
- test/
|
55
|
-
- test/
|
56
|
+
- test/extensions/array_test.rb
|
57
|
+
- test/resources/attachment_test.rb
|
58
|
+
- test/resources/base_test.rb
|
59
|
+
- test/resources/card_test.rb
|
60
|
+
- test/resources/project_test.rb
|
61
|
+
- test/resources/property_definition_test.rb
|
62
|
+
- test/resources/user_test.rb
|
56
63
|
- test/test_helper.rb
|
57
64
|
has_rdoc: true
|
58
65
|
homepage: http://github.com/schubert/minglr
|
@@ -81,6 +88,11 @@ signing_key:
|
|
81
88
|
specification_version: 2
|
82
89
|
summary: command line user tool for Mingle (http://mingle.thoughtworks.com/mingle-agile-project-management)
|
83
90
|
test_files:
|
84
|
-
- test/
|
85
|
-
- test/
|
91
|
+
- test/extensions/array_test.rb
|
92
|
+
- test/resources/attachment_test.rb
|
93
|
+
- test/resources/base_test.rb
|
94
|
+
- test/resources/card_test.rb
|
95
|
+
- test/resources/project_test.rb
|
96
|
+
- test/resources/property_definition_test.rb
|
97
|
+
- test/resources/user_test.rb
|
86
98
|
- test/test_helper.rb
|
data/lib/minglr/attachment.rb
DELETED
data/lib/minglr/card.rb
DELETED
data/lib/minglr/minglr_action.rb
DELETED
@@ -1,200 +0,0 @@
|
|
1
|
-
class MinglrAction
|
2
|
-
|
3
|
-
ACTIONS = ["cards", "card", "create", "update", "move", "users", "attach", "fetch"].sort!
|
4
|
-
|
5
|
-
def self.execute(action, options = [], flag_options = {}, config = {})
|
6
|
-
MinglrAction.new(action.to_sym, options, flag_options, config)
|
7
|
-
end
|
8
|
-
|
9
|
-
attr_reader :action, :options, :flag_options, :config
|
10
|
-
|
11
|
-
def initialize(action, options, flag_options, config)
|
12
|
-
@action = action
|
13
|
-
if action == options[0].to_sym
|
14
|
-
options.shift
|
15
|
-
else
|
16
|
-
options.shift; options.shift
|
17
|
-
end
|
18
|
-
@options = options
|
19
|
-
@flag_options = flag_options
|
20
|
-
@config = config
|
21
|
-
begin
|
22
|
-
self.send(action)
|
23
|
-
rescue ActiveResource::ResourceNotFound => error
|
24
|
-
puts error.message + " for URL #{MingleResource.site}..."
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def cards
|
29
|
-
attributes = [:number, :card_type_name, @config[:status_property].to_sym, :name]
|
30
|
-
cards = Card.find(:all)
|
31
|
-
cards = filter_collection(cards, attributes, @options)
|
32
|
-
print_collection(cards, attributes)
|
33
|
-
end
|
34
|
-
|
35
|
-
def users
|
36
|
-
attributes = [:login, :name, :email]
|
37
|
-
users = User.find(:all).collect! { |user| user.user }
|
38
|
-
users = filter_collection(users, attributes, @options)
|
39
|
-
print_collection(users, attributes, "right")
|
40
|
-
end
|
41
|
-
|
42
|
-
def card
|
43
|
-
card_number = @options.first
|
44
|
-
attributes = [:number, :card_type_name, @config[:status_property].to_sym, :name, :description]
|
45
|
-
card = card_by_number(card_number)
|
46
|
-
attachments = Attachment.find(:all, :params => { :card_number => card_number })
|
47
|
-
attachments = attachments.collect do |attachment|
|
48
|
-
"* #{attachment.file_name}: #{MingleResource.site + attachment.url}"
|
49
|
-
end
|
50
|
-
output = <<-EOS
|
51
|
-
Number: #{card.number}
|
52
|
-
Name: #{card.name}
|
53
|
-
Type: #{card.card_type_name}
|
54
|
-
Status: #{card.send(@config[:status_property].to_sym)}
|
55
|
-
Description: #{card.description}
|
56
|
-
|
57
|
-
Attachments:
|
58
|
-
#{attachments.join("\n")}
|
59
|
-
EOS
|
60
|
-
puts output
|
61
|
-
end
|
62
|
-
|
63
|
-
def attach
|
64
|
-
card_number = @options.first
|
65
|
-
if card_to_update = card_by_number(card_number)
|
66
|
-
url = Attachment.site
|
67
|
-
url = (url.to_s.gsub(/#{url.path}$/, '')) + Attachment.collection_path(:card_number => card_number)
|
68
|
-
file_name = @flag_options[:file_attachment]
|
69
|
-
require 'httpclient'
|
70
|
-
if File.exist?(file_name)
|
71
|
-
File.open(file_name) do |file|
|
72
|
-
body = { 'file' => file, "filename" => file_name }
|
73
|
-
client = HTTPClient.new
|
74
|
-
client.set_auth(nil, @config[:username], @config[:password])
|
75
|
-
res = client.post(url, body)
|
76
|
-
if res.status_code == 201
|
77
|
-
puts "File '#{file_name}' attached to card #{card_number}"
|
78
|
-
else
|
79
|
-
puts "Error attaching file '#{file_name}' to card #{card_number} (Got back HTTP code #{res.status_code})"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
else
|
83
|
-
puts "Unable to open file '#{file_name}'"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def fetch
|
89
|
-
card_number = @options.first
|
90
|
-
if card_to_update = card_by_number(card_number)
|
91
|
-
attachments = Attachment.find(:all, :params => { :card_number => card_number })
|
92
|
-
attachments.each do |attachment|
|
93
|
-
url = MingleResource.site + attachment.url
|
94
|
-
url.userinfo = nil, nil
|
95
|
-
puts "Downloading #{url.to_s}:"
|
96
|
-
`curl --insecure --progress-bar --output #{attachment.file_name} --user #{@config[:username]}:#{@config[:password]} #{url}`
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def create
|
102
|
-
@flag_options.merge!({ @config[:status_property].to_sym => "New", :cp_owner_user_id => owner_id })
|
103
|
-
card = Card.new(@flag_options)
|
104
|
-
card.save
|
105
|
-
card.reload
|
106
|
-
puts "Card #{card.number} created"
|
107
|
-
end
|
108
|
-
|
109
|
-
def update
|
110
|
-
@flag_options.merge!({ :cp_owner_user_id => owner_id })
|
111
|
-
card_number = @options.first
|
112
|
-
card_to_update = card_by_number(card_number)
|
113
|
-
@flag_options.each do |attribute, value|
|
114
|
-
card_to_update.send("#{attribute.to_s}=".to_sym, value)
|
115
|
-
end
|
116
|
-
card_to_update.save
|
117
|
-
puts "Card #{card_to_update.number} updated\n\n"
|
118
|
-
card
|
119
|
-
end
|
120
|
-
|
121
|
-
def move
|
122
|
-
card_number = @options.first
|
123
|
-
card_to_move = card_by_number(card_number)
|
124
|
-
transition_options = { :card => card_number }
|
125
|
-
transition_options.merge!({ :comment => @flag_options[:comment]}) if @flag_options[:comment]
|
126
|
-
current_status = card_to_move.send(@config[:status_property])
|
127
|
-
next_transition = nil
|
128
|
-
|
129
|
-
case card_to_move.card_type_name.downcase
|
130
|
-
when /task/
|
131
|
-
status_states = @config.select do |key, value|
|
132
|
-
key.to_s =~ /^task_state_/
|
133
|
-
end
|
134
|
-
when /story/
|
135
|
-
status_states = @config.select do |key, value|
|
136
|
-
key.to_s =~ /^story_state/
|
137
|
-
end
|
138
|
-
else
|
139
|
-
puts "No transitions defined for card of type #{card_to_move.card_type_name}"
|
140
|
-
end
|
141
|
-
status_states = status_states.collect {|state| state.last }.collect {|state| state.split(">").collect { |value| value.strip } }
|
142
|
-
next_transition = status_states.select {|state| state.first.downcase == current_status.downcase }.first.last
|
143
|
-
transition_options.merge!({ :transition => next_transition })
|
144
|
-
|
145
|
-
if response = TransitionExecution.create(transition_options)
|
146
|
-
if response.attributes["status"] == "completed"
|
147
|
-
puts "Moved card from #{current_status} to #{next_transition}"
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def pickup
|
153
|
-
raise "not implemented yet"
|
154
|
-
end
|
155
|
-
|
156
|
-
private
|
157
|
-
|
158
|
-
def filter_collection(collection, attributes, words)
|
159
|
-
words.each do |word|
|
160
|
-
collection = collection.select do |element|
|
161
|
-
output = ""
|
162
|
-
attributes.each { |attribute| output << element.send(attribute).to_s + " " }
|
163
|
-
output =~ /#{word}/i
|
164
|
-
end
|
165
|
-
end
|
166
|
-
collection
|
167
|
-
end
|
168
|
-
|
169
|
-
def print_collection(collection, attributes, align = "left")
|
170
|
-
output = []
|
171
|
-
longest_attributes = Array.new(attributes.length, 0)
|
172
|
-
alignment = (align == "left" ? :ljust : :rjust)
|
173
|
-
collection.each do |element|
|
174
|
-
entry = []
|
175
|
-
attributes.each_with_index do |attribute, index|
|
176
|
-
attribute_value = element.send(attribute).to_s
|
177
|
-
longest_attributes[index] = attribute_value.length if attribute_value.length > longest_attributes[index]
|
178
|
-
entry << attribute_value
|
179
|
-
end
|
180
|
-
output << entry
|
181
|
-
end
|
182
|
-
output.each do |entry|
|
183
|
-
row = []
|
184
|
-
entry.each_with_index do |part, index|
|
185
|
-
row << [part.send(alignment, longest_attributes[index])]
|
186
|
-
end
|
187
|
-
puts row.join(" - ")
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def card_by_number(number)
|
192
|
-
Card.find(number)
|
193
|
-
end
|
194
|
-
|
195
|
-
def owner_id
|
196
|
-
user = User.find(:all).select { |user| user.user.login == @config[:username] }.first
|
197
|
-
user.user_id
|
198
|
-
end
|
199
|
-
|
200
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
class MinglrConfigParser
|
2
|
-
CONFIG_FILE = ".minglrconfig"
|
3
|
-
attr_reader :config
|
4
|
-
|
5
|
-
def self.parse
|
6
|
-
config_files = [File.join(ENV["HOME"], CONFIG_FILE), File.join(ENV["PWD"], CONFIG_FILE)]
|
7
|
-
config_files.each do |config_file_name|
|
8
|
-
if File.exist?(config_file_name)
|
9
|
-
return self.new(File.read(config_file_name)).config
|
10
|
-
end
|
11
|
-
end
|
12
|
-
puts "Unable to find #{CONFIG_FILE} in #{config_files.join(", ")}"
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(config_contents)
|
16
|
-
@config = {}
|
17
|
-
@current_section = nil
|
18
|
-
config_contents.each_line do |line|
|
19
|
-
line = line.strip!
|
20
|
-
case line
|
21
|
-
when ""
|
22
|
-
next
|
23
|
-
when /\[(.*)\]/
|
24
|
-
define_section($1.to_s)
|
25
|
-
else
|
26
|
-
define_var(line)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
@config
|
30
|
-
end
|
31
|
-
|
32
|
-
def define_section(section_name)
|
33
|
-
@config[section_name.to_sym] = {} unless @config.has_key?(section_name.to_sym)
|
34
|
-
@current_section = section_name.to_sym
|
35
|
-
end
|
36
|
-
|
37
|
-
def define_var(line)
|
38
|
-
key, value = line.split("=")
|
39
|
-
key.strip!
|
40
|
-
value.strip!
|
41
|
-
@config[@current_section][key.to_sym] = value
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|