schubert-minglr 1.1.0 → 1.2.0
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/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
|