MrMurano 1.6.3 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -2
  3. data/Gemfile +1 -1
  4. data/MrMurano.gemspec +1 -1
  5. data/README.markdown +4 -0
  6. data/TODO.taskpaper +17 -4
  7. data/lib/MrMurano/Account.rb +5 -1
  8. data/lib/MrMurano/Config.rb +3 -1
  9. data/lib/MrMurano/Product-Resources.rb +239 -0
  10. data/lib/MrMurano/Product.rb +51 -2
  11. data/lib/MrMurano/Solution-Cors.rb +81 -0
  12. data/lib/MrMurano/Solution-Endpoint.rb +8 -4
  13. data/lib/MrMurano/Solution-File.rb +4 -2
  14. data/lib/MrMurano/Solution-ServiceConfig.rb +74 -1
  15. data/lib/MrMurano/Solution-Services.rb +4 -2
  16. data/lib/MrMurano/Solution-Users.rb +6 -3
  17. data/lib/MrMurano/Solution.rb +6 -274
  18. data/lib/MrMurano/SyncUpDown.rb +433 -0
  19. data/lib/MrMurano/commands/completion.rb +152 -0
  20. data/lib/MrMurano/commands/content.rb +15 -14
  21. data/lib/MrMurano/commands/cors.rb +11 -38
  22. data/lib/MrMurano/commands/exportImport.rb +4 -3
  23. data/lib/MrMurano/commands/keystore.rb +15 -16
  24. data/lib/MrMurano/commands/logs.rb +2 -2
  25. data/lib/MrMurano/commands/productCreate.rb +4 -4
  26. data/lib/MrMurano/commands/productDelete.rb +6 -8
  27. data/lib/MrMurano/commands/productSpec.rb +31 -36
  28. data/lib/MrMurano/commands/productWrite.rb +9 -7
  29. data/lib/MrMurano/commands/serialNumberCmds.rb +4 -4
  30. data/lib/MrMurano/commands/solutionCreate.rb +4 -4
  31. data/lib/MrMurano/commands/solutionDelete.rb +5 -5
  32. data/lib/MrMurano/commands/status.rb +9 -42
  33. data/lib/MrMurano/commands/sync.rb +15 -71
  34. data/lib/MrMurano/commands/timeseries.rb +23 -29
  35. data/lib/MrMurano/commands/tsdb.rb +202 -0
  36. data/lib/MrMurano/commands/zshcomplete.erb +112 -0
  37. data/lib/MrMurano/commands.rb +4 -1
  38. data/lib/MrMurano/http.rb +4 -3
  39. data/lib/MrMurano/makePretty.rb +15 -6
  40. data/lib/MrMurano/verbosing.rb +71 -0
  41. data/lib/MrMurano/version.rb +1 -1
  42. data/lib/MrMurano.rb +1 -0
  43. data/spec/ConfigFile_spec.rb +3 -3
  44. data/spec/ProductContent_spec.rb +2 -2
  45. data/spec/ProductResources_spec.rb +152 -0
  46. data/spec/Product_spec.rb +38 -1
  47. data/spec/Solution-Cors_spec.rb +134 -0
  48. data/spec/Solution-ServiceConfig_spec.rb +198 -0
  49. data/spec/SyncRoot_spec.rb +74 -0
  50. data/spec/cmd_config_spec.rb +51 -0
  51. data/spec/fixtures/.mrmuranorc +9 -0
  52. data/spec/{testfiles → fixtures}/configfile +0 -0
  53. data/spec/fixtures/mrmuranorc_deleted_bob +8 -0
  54. data/spec/fixtures/product_spec_files/example.exoline.spec.yaml +116 -0
  55. data/spec/fixtures/product_spec_files/example.murano.spec.yaml +14 -0
  56. data/spec/fixtures/product_spec_files/gwe.exoline.spec.yaml +21 -0
  57. data/spec/fixtures/product_spec_files/gwe.murano.spec.yaml +16 -0
  58. data/spec/{lightbulb.yaml → fixtures/product_spec_files/lightbulb.yaml} +0 -0
  59. data/spec/spec_helper.rb +4 -4
  60. metadata +47 -19
@@ -1,54 +1,27 @@
1
-
2
- module MrMurano
3
- class Cors < SolutionBase
4
- def initialize
5
- super
6
- @uriparts << 'cors'
7
- @location = $cfg['location.cors']
8
- end
9
-
10
- def fetch()
11
- ret = get()
12
- ret[:cors]
13
- end
14
-
15
- # TODO: fill out other metheds so this could be part of sync up/down.
16
-
17
- ##
18
- # Upload CORS
19
- # :local path to file to push
20
- # :remote hash of method and endpoint path (ignored for now)
21
- def upload(local, remote)
22
- local = Pathname.new(local) unless local.kind_of? Pathname
23
- raise "no file" unless local.exist?
24
-
25
- local.open do |io|
26
- data = YAML.load(io)
27
- put('', data)
28
- end
29
- end
30
-
31
- def tolocalpath(into, item)
32
- into
33
- end
34
- end
35
- end
1
+ require 'yaml'
2
+ require 'MrMurano/Solution-Cors'
36
3
 
37
4
  command :cors do |c|
38
5
  c.syntax = %{mr cors [options]}
39
- c.description = %{Get or set the CORS for the solution.}
6
+ c.summary = %{Get or set the CORS for the solution. [Deprecated]}
7
+ c.description = %{Get or set the CORS for the solution.
8
+
9
+ This is deprecated. Use `mr syncup --cors` or `mr syncdown --cors` instead.
10
+ }
40
11
  c.option '-f','--file FILE', String, %{File to set CORS from}
41
12
 
42
13
  c.action do |args,options|
14
+ say_warning "This is deprecated. Use `mr syncup --cors` or `mr syncdown --cors` instead."
43
15
  sol = MrMurano::Cors.new
44
16
 
45
17
  if options.file then
46
18
  #set
47
- pp sol.upload(options.file, {})
19
+ data = sol.localitems(options.file)
20
+ sol.outf sol.upload(options.file, data.first)
48
21
  else
49
22
  # get
50
23
  ret = sol.fetch()
51
- puts ret
24
+ sol.outf ret
52
25
  end
53
26
  end
54
27
 
@@ -8,7 +8,7 @@ command 'config export' do |c|
8
8
  c.description = %{Export data to Solutionfiles
9
9
 
10
10
  This will write to the Solutionfile.json and .Solutionfile.secret used by the
11
- exosite-cil tool.
11
+ exosite-cli tool.
12
12
 
13
13
  This also will merge all of the endpoints into a single 'routes.lua' file.
14
14
  }
@@ -23,8 +23,9 @@ command 'config export' do |c|
23
23
  solsecret = Pathname.new($cfg['location.base'] + '.Solutionfile.secret')
24
24
 
25
25
  if not options.force and (solfile.exist? or solsecret.exist?) then
26
- say_error "Solutionfile.json or .Solutionfile.secret already exist."
27
- say "Use --force to overwrite"
26
+ sol = MrMurano::Solution.new
27
+ sol.error "Solutionfile.json or .Solutionfile.secret already exist."
28
+ sol.error "Use --force to overwrite"
28
29
  end
29
30
 
30
31
  solf = {
@@ -1,3 +1,4 @@
1
+ require 'MrMurano/Solution-ServiceConfig'
1
2
 
2
3
  module MrMurano
3
4
  class Keystore < ServiceConfig
@@ -7,29 +8,29 @@ module MrMurano
7
8
  end
8
9
 
9
10
  def keyinfo
10
- ret = get("/#{scid}/call/info")
11
+ call(:info)
11
12
  end
12
13
 
13
14
  def listkeys
14
- ret = get("/#{scid}/call/list")
15
+ ret = call(:list)
15
16
  ret[:keys]
16
17
  end
17
18
 
18
19
  def getkey(key)
19
- ret = post("/#{scid}/call/get", {:key=>key})
20
+ ret = call(:get, :post, {:key=>key})
20
21
  ret[:value]
21
22
  end
22
23
 
23
24
  def setkey(key, value)
24
- post("/#{scid}/call/set", { :key=>key, :value=>value })
25
+ call(:set, :post, { :key=>key, :value=>value })
25
26
  end
26
27
 
27
28
  def delkey(key)
28
- post("/#{scid}/call/delete", { :key=>key})
29
+ call(:delete, { :key=>key})
29
30
  end
30
31
 
31
32
  def command(key, cmd, args)
32
- post("/#{scid}/call/command", {:key=>key, :command=>cmd, :args=>args})
33
+ call(:command, {:key=>key, :command=>cmd, :args=>args})
33
34
  end
34
35
 
35
36
  end
@@ -40,7 +41,7 @@ command 'keystore info' do |c|
40
41
  c.description = %{Show info about the Keystore}
41
42
  c.action do |args,options|
42
43
  sol = MrMurano::Keystore.new
43
- pp sol.keyinfo
44
+ sol.outf sol.keyinfo
44
45
  end
45
46
  end
46
47
 
@@ -49,9 +50,7 @@ command 'keystore list' do |c|
49
50
  c.description = %{List all of the keys in the Keystore}
50
51
  c.action do |args,options|
51
52
  sol = MrMurano::Keystore.new
52
- sol.listkeys.each do |key|
53
- puts key
54
- end
53
+ sol.outf sol.listkeys
55
54
  end
56
55
  end
57
56
  alias_command :keystore, 'keystore list'
@@ -62,7 +61,7 @@ command 'keystore get' do |c|
62
61
  c.action do |args,options|
63
62
  sol = MrMurano::Keystore.new
64
63
  ret = sol.getkey(args[0])
65
- puts ret
64
+ sol.outf ret
66
65
  end
67
66
  end
68
67
 
@@ -98,16 +97,16 @@ See http://docs.exosite.com/murano/services/keystore/#command for current list.
98
97
  c.example %{mr keystore command lpush mykey A B C}, %{Push three values onto list}
99
98
  c.example %{mr keystore command lrem mykey 0 B}, %{Remove all B values from list}
100
99
  c.action do |args,options|
100
+ sol = MrMurano::Keystore.new
101
101
  if args.count < 2 then
102
- say_error "Not enough params"
102
+ sol.error "Not enough params"
103
103
  else
104
- sol = MrMurano::Keystore.new
105
104
  ret = sol.command(args[1], args[0], args[2..-1])
106
105
  if ret.has_key?(:value) then
107
- puts ret[:value]
106
+ sol.outf ret[:value]
108
107
  else
109
- say_error "#{ret[:code]}: #{ret.message}"
110
- pp ret[:error] if ($cfg['tool.debug'] and ret.has_key?(:error))
108
+ sol.error "#{ret[:code]}: #{ret.message}"
109
+ sol.outf ret[:error] if ($cfg['tool.debug'] and ret.has_key?(:error))
111
110
  end
112
111
  end
113
112
  end
@@ -38,7 +38,7 @@ command :logs do |c|
38
38
  :create_additions=>false})
39
39
  puts MrMurano::Pretties::makePretty(js, options)
40
40
  rescue
41
- say_error '=== JSON parse error, showing raw instead ==='
41
+ sol.error '=== JSON parse error, showing raw instead ==='
42
42
  puts m
43
43
  end
44
44
  end
@@ -68,7 +68,7 @@ command :logs do |c|
68
68
  end
69
69
  end
70
70
  else
71
- say_error "Couldn't get logs: #{ret}"
71
+ sol.error "Couldn't get logs: #{ret}"
72
72
  break
73
73
  end
74
74
 
@@ -4,22 +4,22 @@ command 'product create' do |c|
4
4
  c.description = %{Create a new product}
5
5
 
6
6
  c.action do |args, options|
7
+ acc = MrMurano::Account.new
7
8
  if args.count < 1 then
8
- say_error "Name of product missing"
9
+ acc.error "Name of product missing"
9
10
  return
10
11
  end
11
12
  name = args[0]
12
13
 
13
- acc = MrMurano::Account.new
14
14
  ret = acc.new_product(name)
15
15
  if not ret.kind_of?(Hash) and not ret.empty? then
16
- say_error "Create failed: #{ret.to_s}"
16
+ acc.error "Create failed: #{ret.to_s}"
17
17
  return
18
18
  end
19
19
 
20
20
  # create doesn't return anything, so we need to go look for it.
21
21
  ret = acc.products.select{|i| i[:label] == name}
22
- say ret.first[:modelId]
22
+ acc.outf ret.first[:modelId]
23
23
 
24
24
  end
25
25
  end
@@ -6,28 +6,26 @@ command 'product delete' do |c|
6
6
  c.description = %{Delete a product}
7
7
 
8
8
  c.action do |args, options|
9
+ acc = MrMurano::Account.new
9
10
  if args.count < 1 then
10
- say_error "Product id or name missing"
11
+ acc.error "Product id or name missing"
11
12
  return
12
13
  end
13
14
  name = args[0]
14
15
 
15
- acc = MrMurano::Account.new
16
16
 
17
17
  # Need to convert what we got into the internal PID.
18
18
  ret = acc.products.select{|i| i.has_value? name }
19
19
 
20
- if $cfg['tool.debug'] then
21
- say "Matches found:"
22
- pp ret
23
- end
20
+ acc.debug "Matches found:"
21
+ acc.outf(ret) if $cfg['tool.debug']
24
22
 
25
23
  if ret.empty? then
26
- say_error "No product matching '#{name}' found. Nothing to delete."
24
+ acc.error "No product matching '#{name}' found. Nothing to delete."
27
25
  else
28
26
  ret = acc.delete_product(ret.first[:pid])
29
27
  if not ret.kind_of?(Hash) and not ret.empty? then
30
- say_error "Delete failed: #{ret.to_s}"
28
+ acc.error "Delete failed: #{ret.to_s}"
31
29
  end
32
30
  end
33
31
  end
@@ -1,6 +1,8 @@
1
+ require 'MrMurano/Account'
1
2
  require 'MrMurano/Product'
2
3
  require 'MrMurano/hash'
3
4
  require 'yaml'
5
+ require 'terminal-table'
4
6
 
5
7
  command 'product spec convert' do |c|
6
8
  c.syntax = %{mr product spec convert FILE}
@@ -8,38 +10,22 @@ command 'product spec convert' do |c|
8
10
  c.option '-o', '--output FILE', %{Download to file instead of STDOUT}
9
11
 
10
12
  c.action do |args, options|
13
+ prd = MrMurano::Product.new
11
14
  if args.count == 0 then
12
- say_error "Missing file"
15
+ prd.error "Missing file"
13
16
  else
14
-
15
- File.open(args[0]) do |fin|
16
- spec = YAML.load(fin)
17
- unless spec.has_key?('dataports') then
18
- say_error "Not an exoline spec file"
19
- else
20
- dps = spec['dataports'].map do |dp|
21
- dp.delete_if{|k,v| k != 'alias' and k != 'format' and k != 'initial'}
22
- dp['format'] = 'string' if dp['format'][0..5] == 'string'
23
- dp
24
- end
25
-
26
- spec = {'resource'=>dps}
27
- if options.output then
28
- File.open(options.output, 'w') do |io|
29
- io << spec.to_yaml
30
- end
31
- else
32
- puts spec.to_yaml
33
- end
34
- end
35
- end
17
+ prd.outf prd.convert(args[0])
36
18
  end
37
19
  end
38
20
  end
39
21
 
40
22
  command 'product spec push' do |c|
41
23
  c.syntax = %{mr product spec push [--file FILE]}
42
- c.summary = %{Upload a new specification for a product}
24
+ c.summary = %{Upload a new specification for a product [Deprecated]}
25
+ c.description = %{Convert exoline spec file into Murano format
26
+
27
+ This is deprecated. Use `mr syncup --specs` instead.
28
+ }
43
29
 
44
30
  c.option '--file FILE', "The spec file to upload"
45
31
 
@@ -49,6 +35,8 @@ command 'product spec push' do |c|
49
35
  # - $cfg['product.spec']
50
36
 
51
37
  c.action do |args, options|
38
+ prd = MrMurano::Product.new
39
+ prd.warning "This is deprecated. Use `mr syncup --specs` instead."
52
40
 
53
41
  file = $cfg['product.spec']
54
42
  prid = $cfg['product.id']
@@ -56,10 +44,9 @@ command 'product spec push' do |c|
56
44
  file = options.file unless options.file.nil?
57
45
 
58
46
  if not file.nil? and FileTest.exist?(file) then
59
- prd = MrMurano::Product.new
60
- pp prd.update(file)
47
+ prd.outf prd.update(file)
61
48
  else
62
- say_error "No spec file to push: #{file}"
49
+ prd.error "No spec file to push: #{file}"
63
50
  end
64
51
  end
65
52
  end
@@ -69,27 +56,35 @@ command 'product spec pull' do |c|
69
56
  c.summary = %{Pull down the specification for a product}
70
57
 
71
58
  c.option '-o', '--output FILE', %{Download to file instead of STDOUT}
59
+ c.option '--aliasonly', 'Only return the aliases'
72
60
 
73
61
  c.action do |args, options|
74
62
  prd = MrMurano::Product.new
75
63
  ret = prd.info
76
64
 
77
- resources = ret[:resources].map do |r|
78
- r.delete(:rid)
79
- Hash.transform_keys_to_strings(r)
65
+ io=nil
66
+ if options.output then
67
+ io = File.open(options.output, 'w')
80
68
  end
81
69
 
82
- spec = { 'resources'=> resources }
70
+ if options.aliasonly then
71
+ ret = ret[:resources].map{|row| row[:alias]}
72
+ end
83
73
 
84
- if options.output then
85
- File.open(options.output, 'w') do |io|
86
- io << spec.to_yaml
74
+ prd.outf(ret, io) do |dd, ios|
75
+ if ret.kind_of? Array then
76
+ ios.puts ret.join(' ')
77
+ else
78
+ prd.tabularize({
79
+ :rows => ret[:resources].map{|r| [r[:alias], r[:format], r[:rid]]},
80
+ :headers => ['Alias', 'Format', 'RID']
81
+ }, ios)
87
82
  end
88
- else
89
- puts spec.to_yaml
90
83
  end
84
+ io.close unless io.nil?
91
85
  end
92
86
  end
93
87
  alias_command 'product spec', 'product spec pull'
88
+ alias_command 'product spec list', 'product spec pull', '--astable'
94
89
 
95
90
  # vim: set ai et sw=2 ts=2 :
@@ -6,17 +6,19 @@ command 'product write' do |c|
6
6
 
7
7
  c.action do |args,options|
8
8
  sn = args.shift
9
+ prd = MrMurano::Product.new
9
10
  if (args.count % 2) != 0 then
10
- say_error "Last alias is missing a value to write."
11
+ prd.error "Last alias is missing a value to write."
11
12
  else
12
13
  data = Hash[*args]
13
- prd = MrMurano::Product.new
14
14
  ret = prd.write(sn, data)
15
- ret.each_pair do |k,v|
16
- if v == 'ok' then
17
- say "#{k.to_s}: #{v}"
18
- else
19
- say_error "#{k.to_s}: #{v}"
15
+ prd.outf(ret) do |dd|
16
+ ret.each_pair do |k,v|
17
+ if v == 'ok' then
18
+ say "#{k.to_s}: #{v}"
19
+ else
20
+ prd.error "#{k.to_s}: #{v}"
21
+ end
20
22
  end
21
23
  end
22
24
  end
@@ -42,7 +42,7 @@ the activation call within this time, it will need to be enabled again.
42
42
  elsif args.count > 0 then
43
43
  prd.enable(args[0])
44
44
  else
45
- say_error "Missing a serial number to enable"
45
+ prd.error "Missing a serial number to enable"
46
46
  end
47
47
  end
48
48
  end
@@ -61,14 +61,14 @@ CIK again.
61
61
  }
62
62
 
63
63
  c.action do |args,options|
64
+ prd = MrMurano::ProductSerialNumber.new
64
65
  if args.count < 1 then
65
- say_error "Serial number missing"
66
+ prd.error "Serial number missing"
66
67
  return
67
68
  end
68
69
  sn = args.first
69
70
 
70
- prd = MrMurano::ProductSerialNumber.new
71
- pp prd.activate(sn)
71
+ prd.outf prd.activate(sn)
72
72
 
73
73
  end
74
74
  end
@@ -4,22 +4,22 @@ command 'solution create' do |c|
4
4
  c.description = %{Create a new solution}
5
5
 
6
6
  c.action do |args, options|
7
+ acc = MrMurano::Account.new
7
8
  if args.count < 1 then
8
- say_error "Name of solution missing"
9
+ acc.error "Name of solution missing"
9
10
  return
10
11
  end
11
12
  name = args[0]
12
13
 
13
- acc = MrMurano::Account.new
14
14
  ret = acc.new_solution(name)
15
15
  if not ret.kind_of?(Hash) and not ret.empty? then
16
- say_error "Create failed: #{ret.to_s}"
16
+ acc.error "Create failed: #{ret.to_s}"
17
17
  return
18
18
  end
19
19
 
20
20
  # create doesn't return anything, so we need to go look for it.
21
21
  ret = acc.solutions.select{|i| i[:domain] =~ /#{name}\./}
22
- say ret.first[:apiId]
22
+ acc.outf ret.first[:apiId]
23
23
 
24
24
  end
25
25
  end
@@ -5,28 +5,28 @@ command 'solution delete' do |c|
5
5
  c.description = %{Delete a solution}
6
6
 
7
7
  c.action do |args, options|
8
+ acc = MrMurano::Account.new
8
9
  if args.count < 1 then
9
- say_error "Solution id or name missing"
10
+ acc.error "Solution id or name missing"
10
11
  return
11
12
  end
12
13
  name = args[0]
13
14
 
14
- acc = MrMurano::Account.new
15
15
 
16
16
  # Need to convert what we got into the internal PID.
17
17
  ret = acc.solutions.select{|i| i.has_value?(name) or i[:domain] =~ /#{name}\./ }
18
18
 
19
19
  if $cfg['tool.debug'] then
20
20
  say "Matches found:"
21
- pp ret
21
+ acc.outf ret
22
22
  end
23
23
 
24
24
  if ret.empty? then
25
- say_error "No solution matching '#{name}' found. Nothing to delete."
25
+ acc.error "No solution matching '#{name}' found. Nothing to delete."
26
26
  else
27
27
  ret = acc.delete_solution(ret.first[:sid])
28
28
  if not ret.kind_of?(Hash) and not ret.empty? then
29
- say_error "Delete failed: #{ret.to_s}"
29
+ acc.error "Delete failed: #{ret.to_s}"
30
30
  end
31
31
  end
32
32
  end
@@ -3,24 +3,21 @@ command :status do |c|
3
3
  c.syntax = %{mr status [options]}
4
4
  c.description = %{Get the status of files}
5
5
  c.option '--all', 'Check everything'
6
- c.option '-s','--[no-]files', %{Static Files}
7
- c.option '-a','--[no-]endpoints', %{Endpoints}
8
- c.option '-m','--[no-]modules', %{Modules}
9
- c.option '-e','--[no-]eventhandlers', %{Event Handlers}
10
- c.option '--[no-]roles', %{Roles}
11
- c.option '--[no-]users', %{Users}
6
+
7
+ # Load options to control which things to status
8
+ MrMurano::SyncRoot.each_option do |s,l,d|
9
+ c.option s, l, d
10
+ end
12
11
 
13
12
  c.option '--[no-]asdown', %{Report as if syncdown instead of syncup}
14
13
  c.option '--[no-]diff', %{For modified items, show a diff}
15
14
  c.option '--[no-]grouped', %{Group all adds, deletes, and mods together}
16
15
  c.option '--[no-]showall', %{List unchanged as well}
17
-
16
+
18
17
  c.action do |args,options|
19
18
  options.default :delete=>true, :create=>true, :update=>true, :diff=>false,
20
19
  :grouped => true
21
20
 
22
- MrMurano.checkSAME(options)
23
-
24
21
  def fmtr(item)
25
22
  if item.has_key? :local_path then
26
23
  item[:local_path].relative_path_from(Pathname.pwd()).to_s
@@ -54,41 +51,11 @@ command :status do |c|
54
51
  pretty(ret, options)
55
52
  end
56
53
  end
57
-
58
- if options.endpoints then
59
- sol = MrMurano::Endpoint.new
60
- ret = sol.status(options)
61
- gmerge(ret, 'A', options)
62
- end
63
-
64
- if options.modules then
65
- sol = MrMurano::Library.new
66
- ret = sol.status(options)
67
- gmerge(ret, 'M', options)
68
- end
69
-
70
- if options.eventhandlers then
71
- sol = MrMurano::EventHandler.new
72
- ret = sol.status(options)
73
- gmerge(ret, 'E', options)
74
- end
75
-
76
- if options.roles then
77
- sol = MrMurano::Role.new
78
- ret = sol.status(options)
79
- gmerge(ret, 'R', options)
80
- end
81
-
82
- if options.users then
83
- sol = MrMurano::User.new
84
- ret = sol.status(options)
85
- gmerge(ret, 'U', options)
86
- end
87
54
 
88
- if options.files then
89
- sol = MrMurano::File.new
55
+ MrMurano::SyncRoot.each_filtered(options.__hash__) do |name, type, klass|
56
+ sol = klass.new
90
57
  ret = sol.status(options)
91
- gmerge(ret, 'S', options)
58
+ gmerge(ret, type, options)
92
59
  end
93
60
 
94
61
  pretty(@grouped, options) if options.grouped