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.
Files changed (39) hide show
  1. data/Rakefile +2 -0
  2. data/VERSION.yml +2 -2
  3. data/bin/minglr +11 -11
  4. data/bin/mtx +1 -1
  5. data/lib/minglr.rb +18 -10
  6. data/lib/minglr/action.rb +75 -0
  7. data/lib/minglr/config_parser.rb +49 -0
  8. data/lib/minglr/extensions/array.rb +23 -0
  9. data/lib/minglr/input_cache.rb +3 -3
  10. data/lib/minglr/options_parser.rb +79 -0
  11. data/lib/minglr/resources/attachment.rb +46 -0
  12. data/lib/minglr/resources/base.rb +42 -0
  13. data/lib/minglr/resources/card.rb +107 -0
  14. data/lib/minglr/resources/project.rb +25 -0
  15. data/lib/minglr/resources/property_definition.rb +12 -0
  16. data/lib/minglr/resources/transition_execution.rb +6 -0
  17. data/lib/minglr/resources/user.rb +25 -0
  18. data/minglr.gemspec +30 -28
  19. data/minglrconfig.sample +19 -0
  20. data/test/extensions/array_test.rb +41 -0
  21. data/test/resources/attachment_test.rb +40 -0
  22. data/test/resources/base_test.rb +45 -0
  23. data/test/resources/card_test.rb +89 -0
  24. data/test/resources/project_test.rb +26 -0
  25. data/test/resources/property_definition_test.rb +25 -0
  26. data/test/resources/user_test.rb +39 -0
  27. data/test/test_helper.rb +15 -5
  28. metadata +27 -15
  29. data/lib/minglr/attachment.rb +0 -7
  30. data/lib/minglr/card.rb +0 -2
  31. data/lib/minglr/mingle_resource.rb +0 -5
  32. data/lib/minglr/minglr_action.rb +0 -200
  33. data/lib/minglr/minglr_config_parser.rb +0 -44
  34. data/lib/minglr/minglr_options_parser.rb +0 -70
  35. data/lib/minglr/property_definition.rb +0 -2
  36. data/lib/minglr/transition_execution.rb +0 -2
  37. data/lib/minglr/user.rb +0 -2
  38. data/test/attachment_test.rb +0 -24
  39. data/test/minglr_resource_test.rb +0 -24
data/Rakefile CHANGED
@@ -63,3 +63,5 @@ Rake::RDocTask.new do |rdoc|
63
63
  rdoc.rdoc_files.include('lib/**/*.rb')
64
64
  end
65
65
 
66
+
67
+ task "dev" => ["test", "gemspec", "build"]
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :major: 1
3
- :minor: 1
2
+ :minor: 2
4
3
  :patch: 0
4
+ :major: 1
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 = MinglrConfigParser.parse
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 MinglrAction::ACTIONS.include?(ARGV[0])
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
- if project
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
- uri_options[:protocol] = uri_options[:url].slice(/^.*\:/).chop
23
- uri_options[:url].gsub!(/^(http|https)\:\/\//, "")
24
- uri_options[:host_and_port], uri_options[:project] = uri_options[:url].split("/projects/")
25
- MingleResource.configure uri_options
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
- MingleResource.configure uri_options
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
- require File.dirname(__FILE__) + '/minglr/mingle_resource'
7
- require File.dirname(__FILE__) + '/minglr/mtx_options_parser'
8
- require File.dirname(__FILE__) + '/minglr/minglr_options_parser'
9
- require File.dirname(__FILE__) + '/minglr/minglr_config_parser'
10
- require File.dirname(__FILE__) + '/minglr/card'
11
- require File.dirname(__FILE__) + '/minglr/user'
12
- require File.dirname(__FILE__) + '/minglr/property_definition'
13
- require File.dirname(__FILE__) + '/minglr/attachment'
14
- require File.dirname(__FILE__) + '/minglr/transition_execution'
15
- require File.dirname(__FILE__) + '/minglr/input_cache'
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
@@ -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