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
data/Rakefile
CHANGED
data/VERSION.yml
CHANGED
data/bin/minglr
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'minglr'))
|
4
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'minglr', "minglr_action"))
|
5
4
|
|
6
|
-
rc_config =
|
5
|
+
rc_config = Minglr::ConfigParser.parse
|
7
6
|
uri_options = rc_config[:global] || {}
|
8
7
|
project = rc_config[:global][:default].to_sym if rc_config[:global][:default]
|
9
8
|
original_arguments = ARGV
|
10
9
|
|
11
|
-
if
|
10
|
+
if Minglr::Action.valid_action?(ARGV[0])
|
12
11
|
action = ARGV[0]
|
13
12
|
else
|
14
13
|
if ARGV[0] && (ARGV[0] =~ /^--/).nil?
|
@@ -17,13 +16,14 @@ else
|
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
|
-
|
19
|
+
unless project.nil?
|
20
|
+
if action.nil?
|
21
|
+
puts "No action specified. Valid actions are: #{Minglr::Action.valid_actions.join(", ")}"
|
22
|
+
exit 1
|
23
|
+
end
|
21
24
|
uri_options.merge! rc_config[project]
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
Attachment.configure
|
27
|
-
extra_options = MinglrOptionsParser.parse(original_arguments)
|
28
|
-
MinglrAction.execute(action, ARGV, extra_options, rc_config[project])
|
25
|
+
Resources::Base.configure uri_options
|
26
|
+
Resources::Attachment.configure
|
27
|
+
extra_options = Minglr::OptionsParser.parse(original_arguments)
|
28
|
+
Minglr::Action.execute(action, ARGV, extra_options, rc_config[project])
|
29
29
|
end
|
data/bin/mtx
CHANGED
@@ -4,7 +4,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'minglr'
|
|
4
4
|
|
5
5
|
uri_options, execution_options = MtxOptionsParser.parse(ARGV, :card, :transition)
|
6
6
|
|
7
|
-
|
7
|
+
Resources::Base.configure uri_options
|
8
8
|
|
9
9
|
if card = Card.find(execution_options[:card])
|
10
10
|
execution = TransitionExecution.create(execution_options)
|
data/lib/minglr.rb
CHANGED
@@ -3,16 +3,24 @@ require 'activesupport'
|
|
3
3
|
require 'activeresource'
|
4
4
|
require 'optparse'
|
5
5
|
|
6
|
-
|
7
|
-
require File.
|
8
|
-
require File.
|
9
|
-
require File.
|
10
|
-
|
11
|
-
require File.
|
12
|
-
require File.
|
13
|
-
|
14
|
-
require File.
|
15
|
-
|
6
|
+
prefix = File.join(File.dirname(__FILE__), "minglr")
|
7
|
+
require File.join(prefix, "action")
|
8
|
+
require File.join(prefix, "options_parser")
|
9
|
+
require File.join(prefix, "config_parser")
|
10
|
+
|
11
|
+
require File.join(prefix, "mtx_options_parser")
|
12
|
+
require File.join(prefix, "input_cache")
|
13
|
+
|
14
|
+
require File.join(prefix, "resources", "base")
|
15
|
+
resources = File.join(prefix, "resources", "*")
|
16
|
+
Dir[resources].each do |file_name|
|
17
|
+
load file_name
|
18
|
+
end
|
19
|
+
|
20
|
+
extensions = File.join(prefix, "extensions", "*")
|
21
|
+
Dir[extensions].each do |file_name|
|
22
|
+
load file_name
|
23
|
+
end
|
16
24
|
|
17
25
|
$:.unshift(File.dirname(__FILE__)) unless
|
18
26
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Minglr
|
2
|
+
|
3
|
+
class Action
|
4
|
+
|
5
|
+
def self.execute(action, options = [], flag_options = {}, config = {})
|
6
|
+
if action == options[0].to_sym
|
7
|
+
options.shift
|
8
|
+
else
|
9
|
+
options.shift
|
10
|
+
options.shift
|
11
|
+
end
|
12
|
+
begin
|
13
|
+
Commands.send(action, options, flag_options, config)
|
14
|
+
rescue ActiveResource::ResourceNotFound => error
|
15
|
+
puts error.message + " for URL #{Resources::Base.site}..."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.valid_actions
|
20
|
+
Commands.methods(false)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.valid_action?(action)
|
24
|
+
valid_actions.include? action
|
25
|
+
end
|
26
|
+
|
27
|
+
class Commands
|
28
|
+
|
29
|
+
def self.attach(options, flag_options, config)
|
30
|
+
card_number = options.first
|
31
|
+
file_name = flag_options[:file_attachment]
|
32
|
+
Resources::Attachment.attach(card_number, file_name, config[:username], config[:password])
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.card(options, flag_options, config)
|
36
|
+
card_number = options.first
|
37
|
+
Resources::Card.print_card(options.first, config[:status_property])
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.cards(options, flag_options, config)
|
41
|
+
Resources::Card.print_all(options, config[:status_property])
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.create(options, flag_options, config)
|
45
|
+
Resources::Card.create(flag_options, config[:status_property])
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.fetch(options, flag_options, config)
|
49
|
+
card_number = options.first
|
50
|
+
Resources::Attachment.fetch(card_number, config[:username], config[:password])
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.move(options, flag_options, config)
|
54
|
+
card_number = options.first
|
55
|
+
Resources::Card.move(card_number, flag_options, config)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.projects(options, flag_options, config)
|
59
|
+
Resources::Project.print_all(options, config[:status_property])
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.update(options, flag_options, config)
|
63
|
+
card_number = options.first
|
64
|
+
Resources::Card.update(card_number, flag_options)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.users(options, flag_options, config)
|
68
|
+
Resources::User.print_all(options)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Minglr
|
2
|
+
|
3
|
+
class ConfigParser
|
4
|
+
|
5
|
+
CONFIG_FILE = ".minglrconfig"
|
6
|
+
attr_reader :config
|
7
|
+
|
8
|
+
def self.parse
|
9
|
+
config_files = [File.join(ENV["HOME"], CONFIG_FILE), File.join(ENV["PWD"], CONFIG_FILE)]
|
10
|
+
config_files.each do |config_file_name|
|
11
|
+
if File.exist?(config_file_name)
|
12
|
+
return self.new(File.read(config_file_name)).config
|
13
|
+
end
|
14
|
+
end
|
15
|
+
puts "Unable to find #{CONFIG_FILE} in #{config_files.join(", ")}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(config_contents)
|
19
|
+
@config = {}
|
20
|
+
@current_section = nil
|
21
|
+
config_contents.each_line do |line|
|
22
|
+
line = line.strip!
|
23
|
+
case line
|
24
|
+
when "", /^#.*$/
|
25
|
+
next
|
26
|
+
when /\[(.*)\]/
|
27
|
+
define_section($1.to_s)
|
28
|
+
else
|
29
|
+
define_var(line)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
@config
|
33
|
+
end
|
34
|
+
|
35
|
+
def define_section(section_name)
|
36
|
+
@config[section_name.to_sym] = {} unless @config.has_key?(section_name.to_sym)
|
37
|
+
@current_section = section_name.to_sym
|
38
|
+
end
|
39
|
+
|
40
|
+
def define_var(line)
|
41
|
+
key, value = line.split("=")
|
42
|
+
key.strip!
|
43
|
+
value.strip!
|
44
|
+
@config[@current_section][key.to_sym] = value
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Minglr
|
2
|
+
|
3
|
+
module Extensions
|
4
|
+
|
5
|
+
module Array
|
6
|
+
|
7
|
+
def filter(attributes, words)
|
8
|
+
collection = self
|
9
|
+
words.each do |word|
|
10
|
+
collection = self.select do |element|
|
11
|
+
output = ""
|
12
|
+
attributes.each { |attribute| output << element.send(attribute).to_s + " " }
|
13
|
+
output =~ /#{word}/i
|
14
|
+
end
|
15
|
+
end
|
16
|
+
collection
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/minglr/input_cache.rb
CHANGED
@@ -3,7 +3,7 @@ class InputCache
|
|
3
3
|
def put(key, content)
|
4
4
|
File.open(file_pathname(key), File::CREAT | File::WRONLY | File::TRUNC) { |file| file.write content }
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def get(key)
|
8
8
|
if content = File.read(file_pathname(key))
|
9
9
|
return nil if content.blank?
|
@@ -12,9 +12,9 @@ class InputCache
|
|
12
12
|
rescue
|
13
13
|
nil
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
protected
|
17
|
-
|
17
|
+
|
18
18
|
def file_pathname(key)
|
19
19
|
File.join(Dir::tmpdir, "#{key.to_s.gsub(/[^\w]/, '')}.entry")
|
20
20
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Minglr
|
2
|
+
class OptionsParser
|
3
|
+
def self.parse(args, *required_by_command)
|
4
|
+
project_options = []
|
5
|
+
|
6
|
+
if Resources::Base.site
|
7
|
+
begin
|
8
|
+
project_options = Resources::PropertyDefinition.project_options
|
9
|
+
rescue ActiveResource::UnauthorizedAccess => exception
|
10
|
+
puts "Connection #{exception.message} to #{Resources::Base.site.to_s}"
|
11
|
+
puts "Did you set 'basic_authentication_enabled: true' in your auth_config.yml file?"
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
command_options = {}
|
17
|
+
|
18
|
+
parser = OptionParser.new do |opts|
|
19
|
+
opts.banner = "Usage: minglr [action] [options]"
|
20
|
+
opts.separator ""
|
21
|
+
opts.separator "Valid Commands Are: #{Minglr::Action.valid_actions.join(", ")}"
|
22
|
+
|
23
|
+
opts.on("-n NAME", String, "Short name of card") do |card_name|
|
24
|
+
command_options[:name] = card_name
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-d DESCRIPTION", String, "Description of card") do |card_description|
|
28
|
+
command_options[:description] = card_description
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-t TYPE", String, "Type of card") do |card_type|
|
32
|
+
command_options[:card_type_name] = card_type
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-c COMMENT", String, "Comment") do |comment|
|
36
|
+
command_options[:comment] = comment
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("-f FILE", String, "File to attach") do |file|
|
40
|
+
command_options[:file_attachment] = file
|
41
|
+
end
|
42
|
+
|
43
|
+
unless project_options.empty?
|
44
|
+
opts.separator ""
|
45
|
+
opts.separator "Project Specific Options"
|
46
|
+
|
47
|
+
project_options.each do |option_pair|
|
48
|
+
option_switch = option_pair[1].downcase.gsub(/\s|_/, "-").gsub(/--|---/, '-').gsub(/--/, '-')
|
49
|
+
opts.on("--#{option_switch}", String, "Set the #{option_pair[1]} for a card") do |option|
|
50
|
+
command_options[option_pair[0]] = option
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.separator ""
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on_tail("-h", "--help", "Show this help message.") do |help|
|
58
|
+
puts opts
|
59
|
+
exit
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on_tail("--version", "Show version") do
|
63
|
+
puts Minglr::VERSION
|
64
|
+
exit
|
65
|
+
end
|
66
|
+
|
67
|
+
if args.empty?
|
68
|
+
puts opts
|
69
|
+
exit
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
parser.parse! args
|
74
|
+
command_options
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'httpclient'
|
2
|
+
|
3
|
+
module Resources
|
4
|
+
|
5
|
+
class Attachment < Base
|
6
|
+
|
7
|
+
def self.configure
|
8
|
+
self.prefix += "cards/:card_number/"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.fetch(card_number, username, password)
|
12
|
+
if card_to_update = Card.find(card_number)
|
13
|
+
attachments = find(:all, :params => { :card_number => card_number })
|
14
|
+
attachments.each do |attachment|
|
15
|
+
url = self.site + attachment.url
|
16
|
+
url.userinfo = nil, nil
|
17
|
+
puts "Downloading #{url.to_s}:"
|
18
|
+
`curl --insecure --progress-bar --output #{attachment.file_name} --user #{username}:#{password} #{url}`
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.attach(card_number, file_name, username, password)
|
24
|
+
if card_to_update = Card.find(card_number)
|
25
|
+
url = (site.to_s.gsub(/#{site.path}$/, '')) + collection_path(:card_number => card_number)
|
26
|
+
if File.exist?(file_name)
|
27
|
+
File.open(file_name) do |file|
|
28
|
+
body = { 'file' => file, "filename" => file_name }
|
29
|
+
client = HTTPClient.new
|
30
|
+
client.set_auth(nil, username, password)
|
31
|
+
response = client.post(url, body)
|
32
|
+
if response.status_code == 201
|
33
|
+
puts "File '#{file_name}' attached to card #{card_number}"
|
34
|
+
else
|
35
|
+
puts "Error attaching file '#{file_name}' to card #{card_number} (Got back HTTP code #{response.status_code})"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
else
|
39
|
+
warn "Unable to open file '#{file_name}'"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
module Resources
|
4
|
+
|
5
|
+
class Base < ActiveResource::Base
|
6
|
+
|
7
|
+
def self.configure(uri_options)
|
8
|
+
uri = URI.parse(uri_options[:url])
|
9
|
+
uri.user = uri_options[:username]
|
10
|
+
uri.password = uri_options[:password]
|
11
|
+
self.site = uri
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.print_collection(collection, attributes, align = :left)
|
15
|
+
output = []
|
16
|
+
longest_attributes = Array.new(attributes.length, 0)
|
17
|
+
alignment = (align == :left ? :ljust : :rjust)
|
18
|
+
collection.each do |element|
|
19
|
+
entry = []
|
20
|
+
attributes.each_with_index do |attribute, index|
|
21
|
+
attribute_value = element.send(attribute).to_s
|
22
|
+
longest_attributes[index] = attribute_value.length if attribute_value.length > longest_attributes[index]
|
23
|
+
entry << attribute_value
|
24
|
+
end
|
25
|
+
output << entry
|
26
|
+
end
|
27
|
+
output.each do |entry|
|
28
|
+
row = []
|
29
|
+
entry.each_with_index do |part, index|
|
30
|
+
row << [part.send(alignment, longest_attributes[index])]
|
31
|
+
end
|
32
|
+
puts row.join(" - ")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.warn(message)
|
37
|
+
puts "Warning: #{message}"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|