MuranoCLI 2.0.0 → 2.1.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.
@@ -24,11 +24,6 @@ module MrMurano
24
24
  # :nocov:
25
25
  end
26
26
 
27
- def list
28
- ret = get()
29
- ret[:items]
30
- end
31
-
32
27
  def fetch(name)
33
28
  raise "Missing name!" if name.nil?
34
29
  raise "Empty name!" if name.empty?
@@ -55,7 +50,7 @@ module MrMurano
55
50
  # we assume these are small enough to slurp.
56
51
  script = local.read
57
52
 
58
- pst = remote.merge ({
53
+ pst = remote.to_h.merge ({
59
54
  :solution_id => $cfg['solution.id'],
60
55
  :script => script,
61
56
  :alias=>mkalias(remote),
@@ -152,8 +147,20 @@ module MrMurano
152
147
  end
153
148
  end
154
149
 
155
- # …/library
150
+ # Libraries or better known as Modules.
156
151
  class Library < ServiceBase
152
+ # Module Specific details on an Item
153
+ class LibraryItem < Item
154
+ # @return [String] Internal Alias name
155
+ attr_accessor :alias
156
+ # @return [String] Timestamp when this was updated.
157
+ attr_accessor :updated_at
158
+ # @return [String] Timestamp when this was created.
159
+ attr_accessor :created_at
160
+ # @return [String] The solution.id that this is in
161
+ attr_accessor :solution_id
162
+ end
163
+
157
164
  def initialize
158
165
  super
159
166
  @uriparts << 'library'
@@ -167,24 +174,30 @@ module MrMurano
167
174
  end
168
175
 
169
176
  def mkalias(remote)
170
- if remote.has_key? :name then
177
+ unless remote.name.nil? then
171
178
  [$cfg['solution.id'], remote[:name]].join('_')
172
179
  else
173
- raise "Missing parts! #{remote.to_json}"
180
+ raise "Missing parts! #{remote.to_h.to_json}"
174
181
  end
175
182
  end
176
183
 
177
184
  def mkname(remote)
178
- if remote.has_key? :name then
185
+ unless remote.name.nil? then
179
186
  remote[:name]
180
187
  else
181
- raise "Missing parts! #{remote.to_json}"
188
+ raise "Missing parts! #{remote.to_h.to_json}"
182
189
  end
183
190
  end
184
191
 
192
+ def list
193
+ ret = get()
194
+ return [] unless ret.has_key? :items
195
+ ret[:items].map{|i| LibraryItem.new(i)}
196
+ end
197
+
185
198
  def toRemoteItem(from, path)
186
199
  name = path.basename.to_s.sub(/\..*/, '')
187
- {:name => name}
200
+ LibraryItem.new(:name => name)
188
201
  end
189
202
 
190
203
  def synckey(item)
@@ -193,8 +206,24 @@ module MrMurano
193
206
  end
194
207
  SyncRoot.add('modules', Library, 'M', %{Modules}, true)
195
208
 
196
- # …/eventhandler
209
+ # Services aka EventHandlers
197
210
  class EventHandler < ServiceBase
211
+ # EventHandler Specific details on an Item
212
+ class EventHandlerItem < Item
213
+ # @return [String] Internal Alias name
214
+ attr_accessor :alias
215
+ # @return [String] Timestamp when this was updated.
216
+ attr_accessor :updated_at
217
+ # @return [String] Timestamp when this was created.
218
+ attr_accessor :created_at
219
+ # @return [String] The solution.id that this is in
220
+ attr_accessor :solution_id
221
+ # @return [String] Which service triggers this script
222
+ attr_accessor :service
223
+ # @return [String] Which event triggers this script
224
+ attr_accessor :event
225
+ end
226
+
198
227
  def initialize
199
228
  super
200
229
  @uriparts << 'eventhandler'
@@ -204,18 +233,18 @@ module MrMurano
204
233
  end
205
234
 
206
235
  def mkalias(remote)
207
- if remote.has_key? :service and remote.has_key? :event then
208
- [$cfg['solution.id'], remote[:service], remote[:event]].join('_')
236
+ if remote.service.nil? or remote.event.nil? then
237
+ raise "Missing parts! #{remote.to_h.to_json}"
209
238
  else
210
- raise "Missing parts! #{remote.to_json}"
239
+ [$cfg['solution.id'], remote[:service], remote[:event]].join('_')
211
240
  end
212
241
  end
213
242
 
214
243
  def mkname(remote)
215
- if remote.has_key? :service and remote.has_key? :event then
216
- [remote[:service], remote[:event]].join('_')
244
+ if remote.service.nil? or remote.event.nil? then
245
+ raise "Missing parts! #{remote.to_h.to_json}"
217
246
  else
218
- raise "Missing parts! #{remote.to_json}"
247
+ [remote[:service], remote[:event]].join('_')
219
248
  end
220
249
  end
221
250
 
@@ -229,7 +258,7 @@ module MrMurano
229
258
  ( skiplist.include? i[:service] or
230
259
  skiplist.include? "#{i[:service]}.#{i[:event]}"
231
260
  )
232
- }
261
+ }.map{|i| EventHandlerItem.new(i)}
233
262
  end
234
263
 
235
264
  def fetch(name)
@@ -266,11 +295,11 @@ module MrMurano
266
295
  md = @match_header.match(line)
267
296
  if not md.nil? then
268
297
  # header line.
269
- cur = {:service=>md[:service],
270
- :event=>md[:event],
271
- :local_path=>path,
272
- :line=>lineno,
273
- :script=>line}
298
+ cur = EventHandlerItem.new(:service=>md[:service],
299
+ :event=>md[:event],
300
+ :local_path=>path,
301
+ :line=>lineno,
302
+ :script=>line)
274
303
  elsif not cur.nil? and not cur[:script].nil? then
275
304
  cur[:script] << line
276
305
  end
@@ -287,12 +316,13 @@ module MrMurano
287
316
  unless service.nil? or event.nil? then
288
317
  warning "Event in #{spath} missing header, but has legacy support."
289
318
  warning "Please add the header \"--#EVENT #{service} #{event}\""
290
- cur = {:service=>service,
291
- :event=>event,
292
- :local_path=>path,
293
- :line=>0,
294
- :line_end => lineno,
295
- :script=>path.read()} # FIXME: ick, fix this.
319
+ cur = EventHandlerItem.new(:service=>service,
320
+ :event=>event,
321
+ :local_path=>path,
322
+ :line=>0,
323
+ :line_end => lineno,
324
+ :script=>path.read() # FIXME: ick, fix this.
325
+ )
296
326
  end
297
327
  end
298
328
  cur
@@ -9,18 +9,19 @@ require 'MrMurano/hash'
9
9
  module MrMurano
10
10
  ## Track what things are syncable.
11
11
  class SyncRoot
12
+ # A thing that is syncable.
12
13
  Syncable = Struct.new(:name, :class, :type, :desc, :bydefault) do
13
14
  end
14
15
 
15
16
  ##
16
17
  # Add a new entry to syncable things
17
- # +name+:: The name to use for the long option
18
- # +klass+:: The class to instanciate from
19
- # +type+:: Single letter for short option and status listing
20
- # +desc+:: Summary of what this syncs.
21
- # +bydefault+:: Is this part of the default sync group
18
+ # @param name [String] The name to use for the long option
19
+ # @param klass [Class] The class to instanciate from
20
+ # @param type [String] Single letter for short option and status listing
21
+ # @param desc [String] Summary of what this syncs.
22
+ # @param bydefault [Boolean] Is this part of the default sync group
22
23
  #
23
- # returns nil
24
+ # @return [nil]
24
25
  def self.add(name, klass, type, desc, bydefault=false)
25
26
  @@syncset = [] unless defined?(@@syncset)
26
27
  @@syncset << Syncable.new(name.to_s, klass, type, desc, bydefault)
@@ -35,29 +36,29 @@ module MrMurano
35
36
 
36
37
  ##
37
38
  # Get the list of default syncables.
38
- # returns array of names
39
+ # @return [Array<String>] array of names
39
40
  def self.bydefault
40
41
  @@syncset.select{|a| a.bydefault }.map{|a| a.name}
41
42
  end
42
43
 
43
44
  ##
44
45
  # Iterate over all syncables
45
- # +block+:: code to run on each
46
+ # @param block code to run on each
46
47
  def self.each(&block)
47
48
  @@syncset.each{|a| yield a.name, a.type, a.class }
48
49
  end
49
50
 
50
51
  ##
51
52
  # Iterate over all syncables with option arguments.
52
- # +block+:: code to run on each
53
+ # @param block code to run on each
53
54
  def self.each_option(&block)
54
55
  @@syncset.each{|a| yield "-#{a.type.downcase}", "--[no-]#{a.name}", a.desc}
55
56
  end
56
57
 
57
58
  ##
58
59
  # Iterate over just the selected syncables.
59
- # +opt+:: Options hash of which to select from
60
- # +block+:: code to run on each
60
+ # @param opt [Hash{Symbol=>Boolean}] Options hash of which to select from
61
+ # @param block code to run on each
61
62
  def self.each_filtered(opt, &block)
62
63
  self.checkSAME(opt)
63
64
  @@syncset.each do |a|
@@ -70,9 +71,9 @@ module MrMurano
70
71
  ## Adjust options based on all or none
71
72
  # If none are selected, select the bydefault ones.
72
73
  #
73
- # +opt+:: Options hash of which to select from
74
+ # @param opt [Hash{Symbol=>Boolean}] Options hash of which to select from
74
75
  #
75
- # returns nil
76
+ # @return [nil]
76
77
  def self.checkSAME(opt)
77
78
  if opt[:all] then
78
79
  @@syncset.each {|a| opt[a.name.to_sym] = true }
@@ -88,7 +89,139 @@ module MrMurano
88
89
  end
89
90
  end
90
91
 
92
+ ## The functionality of a Syncable thing.
93
+ #
94
+ # This provides the logic for computing what things have changed, and pushing and
95
+ # pulling those things.
96
+ #
91
97
  module SyncUpDown
98
+
99
+ # This is one item that can be synced
100
+ class Item
101
+ # @return [String] The name of this item
102
+ attr_accessor :name
103
+ # @return [Pathname] Where this item lives
104
+ attr_accessor :local_path
105
+ # ??? what is this?
106
+ attr_accessor :id
107
+ # @return [String] The lua code for this item. (not all items use this.)
108
+ attr_accessor :script
109
+ # @return [Integer] The line in #local_path where this #script starts
110
+ attr_accessor :line
111
+ # @return [Integer] The line in #local_path where this #script ends
112
+ attr_accessor :line_end
113
+ # @return [String] If requested, the diff output
114
+ attr_accessor :diff
115
+ # @return [Boolean] When filtering, did this item pass.
116
+ attr_accessor :selected
117
+ # ???? what is this?
118
+ attr_accessor :synckey
119
+
120
+ # Initialize a new Item with a few, or all, attributes.
121
+ # @param hsh [Hash{Symbol=>Object}, Item] Initial values
122
+ #
123
+ # @example Initializing with a Hash
124
+ # Item.new(:name=>'Bob', :local_path => Pathname.new(…))
125
+ # @example Initializing with an Item
126
+ # item = Item.new(:name => 'get')
127
+ # Item.new(item)
128
+ def initialize(hsh={})
129
+ hsh.each_pair{|k,v| self[k] = v}
130
+ end
131
+
132
+ def as_inst(key)
133
+ return key if key.to_s[0] == '@'
134
+ return "@#{key}"
135
+ end
136
+ private :as_inst
137
+ def as_sym(key)
138
+ return key.to_sym if key.to_s[0] != '@'
139
+ return key.to_s[1..-1].to_sym
140
+ end
141
+ private :as_sym
142
+
143
+ # Get attribute as if this was a Hash
144
+ # @param key [String,Symbol] attribute name
145
+ # @return [Object] The value
146
+ def [](key)
147
+ public_send(key.to_sym)
148
+ end
149
+
150
+ # Set attribute as if this was a Hash
151
+ # @param key [String,Symbol] attribute name
152
+ # @param value [Object] value to set
153
+ def []=(key,value)
154
+ public_send("#{key}=", value)
155
+ end
156
+
157
+ # Delete a key
158
+ # @param key [String,Symbol] attribute name
159
+ # @return [Object] The value
160
+ def delete(key)
161
+ inst = as_inst(key)
162
+ remove_instance_variable(inst) if instance_variable_defined?(inst)
163
+ end
164
+
165
+ # @return [Hash{Symbol=>Object}] A hash that represents this Item
166
+ def to_h
167
+ Hash[ instance_variables.map{|k| [ as_sym(k), instance_variable_get(k)]} ]
168
+ end
169
+
170
+ # Adds the contents of item to self.
171
+ # @param item [Item,Hash] Stuff to merge
172
+ # @return [Item] ourself
173
+ def merge!(item)
174
+ item.each_pair{|k,v| self[k] = v}
175
+ self
176
+ end
177
+
178
+ # A new Item containing our plus items.
179
+ # @param item [Item,Hash] Stuff to merge
180
+ # @return [Item] New item with contents of both
181
+ def merge(item)
182
+ dup.merge!(item)
183
+ end
184
+
185
+ # Calls block once for each non-nil key
186
+ # @yieldparam key [Symbol] The name of the key
187
+ # @yieldparam value [Object] The value for that key
188
+ # @return [Item]
189
+ def each_pair(&block)
190
+ instance_variables.each do |key|
191
+ yield as_sym(key), instance_variable_get(key)
192
+ end
193
+ self
194
+ end
195
+
196
+ # Delete items in self that block returns true.
197
+ # @yieldparam key [Symbol] The name of the key
198
+ # @yieldparam value [Object] The value for that key
199
+ # @yieldreturn [Boolean] True to delete this key
200
+ # @return [Item] Ourself.
201
+ def reject!(&block)
202
+ instance_variables.each do |key|
203
+ drop = yield as_sym(key), instance_variable_get(key)
204
+ delete(key) if drop
205
+ end
206
+ self
207
+ end
208
+
209
+ # A new Item with keys deleted where block is true
210
+ # @yieldparam key [Symbol] The name of the key
211
+ # @yieldparam value [Object] The value for that key
212
+ # @yieldreturn [Boolean] True to delete this key
213
+ # @return [Item] New Item with keys deleted
214
+ def reject(&block)
215
+ dup.reject!(&block)
216
+ end
217
+
218
+ # For unit testing.
219
+ include Comparable
220
+ def <=>(anOther)
221
+ self.to_h <=> anOther.to_h
222
+ end
223
+ end
224
+
92
225
  #######################################################################
93
226
  # Methods that must be overridden
94
227
 
@@ -97,7 +230,7 @@ module MrMurano
97
230
  #
98
231
  # Children objects Must override this
99
232
  #
100
- # @return Array: of Hashes of item details
233
+ # @return [Array] of Hashes of item details
101
234
  def list()
102
235
  []
103
236
  end
@@ -106,7 +239,7 @@ module MrMurano
106
239
  #
107
240
  # Children objects Must override this
108
241
  #
109
- # @param itemkey String: The identifying key for this item
242
+ # @param itemkey [String] The identifying key for this item
110
243
  def remove(itemkey)
111
244
  # :nocov:
112
245
  raise "Forgotten implementation"
@@ -117,9 +250,9 @@ module MrMurano
117
250
  #
118
251
  # Children objects Must override this
119
252
  #
120
- # @param src Pathname: Full path of where to upload from
121
- # @param item Hash: The item details to upload
122
- # @param modify Bool: True if item exists already and this is changing it
253
+ # @param src [Pathname] Full path of where to upload from
254
+ # @param item [Hash] The item details to upload
255
+ # @param modify [Bool] True if item exists already and this is changing it
123
256
  def upload(src, item, modify)
124
257
  # :nocov:
125
258
  raise "Forgotten implementation"
@@ -148,14 +281,14 @@ module MrMurano
148
281
  #
149
282
  # @param root [Pathname,String] Root path for this resource type from config files
150
283
  # @param path [Pathname,String] Path to local item
151
- # @return [Hash] hash of the details for the remote item for this path
284
+ # @return [Item] hash of the details for the remote item for this path
152
285
  def toRemoteItem(root, path)
153
286
  # This mess brought to you by Windows short path names.
154
287
  path = Dir.glob(path.to_s).first
155
288
  root = Dir.glob(root.to_s).first
156
289
  path = Pathname.new(path)
157
290
  root = Pathname.new(root)
158
- {:name => path.realpath.relative_path_from(root.realpath).to_s}
291
+ Item.new(:name => path.realpath.relative_path_from(root.realpath).to_s)
159
292
  end
160
293
 
161
294
  ##
@@ -163,8 +296,8 @@ module MrMurano
163
296
  #
164
297
  # Children objects should override this or #tolocalpath
165
298
  #
166
- # @param item Hash: listing details for the item.
167
- # @param itemkey Symbol: Key for look up.
299
+ # @param item [Item] listing details for the item.
300
+ # @param itemkey [Symbol] Key for look up.
168
301
  def tolocalname(item, itemkey)
169
302
  item[itemkey].to_s
170
303
  end
@@ -177,11 +310,11 @@ module MrMurano
177
310
  #
178
311
  # Children objects should override this or #tolocalname
179
312
  #
180
- # @param into Pathname: Root path for this resource type from config files
181
- # @param item Hash: listing details for the item.
182
- # @return Pathname: path to save (or merge) remote item into
313
+ # @param into [Pathname] Root path for this resource type from config files
314
+ # @param item [Item] listing details for the item.
315
+ # @return [Pathname] path to save (or merge) remote item into
183
316
  def tolocalpath(into, item)
184
- return item[:local_path] if item.has_key? :local_path
317
+ return item[:local_path] unless item.local_path.nil?
185
318
  itemkey = @itemkey.to_sym
186
319
  name = tolocalname(item, itemkey)
187
320
  raise "Bad key(#{itemkey}) for #{item}" if name.nil?
@@ -196,7 +329,9 @@ module MrMurano
196
329
  #
197
330
  # Check child specific patterns against item
198
331
  #
199
- # @returns true or false
332
+ # @param item [Item] Item to be checked
333
+ # @param pattern [String] pattern to check with
334
+ # @return [Bool] true or false
200
335
  def match(item, pattern)
201
336
  false
202
337
  end
@@ -205,8 +340,8 @@ module MrMurano
205
340
  #
206
341
  # Children objects should override this if synckey is not @itemkey
207
342
  #
208
- # @param item Hash: The item to get a key from
209
- # @returns Object: The object to use a comparison key
343
+ # @param item [Item] The item to get a key from
344
+ # @return [Object] The object to use a comparison key
210
345
  def synckey(item)
211
346
  key = @itemkey.to_sym
212
347
  item[key]
@@ -216,13 +351,13 @@ module MrMurano
216
351
  #
217
352
  # Children objects should override this or implement #fetch()
218
353
  #
219
- # @param local Pathname: Full path of where to download to
220
- # @param item Hash: The item to download
354
+ # @param local [Pathname] Full path of where to download to
355
+ # @param item [Item] The item to download
221
356
  def download(local, item)
222
- if item[:bundled] then
223
- warning "Not downloading into bundled item #{synckey(item)}"
224
- return
225
- end
357
+ # if item[:bundled] then
358
+ # warning "Not downloading into bundled item #{synckey(item)}"
359
+ # return
360
+ # end
226
361
  local.dirname.mkpath
227
362
  id = item[@itemkey.to_sym]
228
363
  if id.nil? then
@@ -243,8 +378,8 @@ module MrMurano
243
378
  # Children objects should override this if move than just unlinking the local
244
379
  # item.
245
380
  #
246
- # @param dest Pathname: Full path of item to be removed
247
- # @param item Hash: Full details of item to be removed
381
+ # @param dest [Pathname] Full path of item to be removed
382
+ # @param item [Item] Full details of item to be removed
248
383
  def removelocal(dest, item)
249
384
  dest.unlink
250
385
  end
@@ -253,8 +388,7 @@ module MrMurano
253
388
  #######################################################################
254
389
 
255
390
 
256
- ##
257
- # So, for bundles this needs to look at all the places and build up the mered
391
+ # So, for bundles this needs to look at all the places and build up the merged
258
392
  # stack of local items.
259
393
  #
260
394
  # Which means it needs the from to be split into the base and the sub so we can
@@ -267,7 +401,7 @@ module MrMurano
267
401
  # #localitems
268
402
  #
269
403
  # This collects items in the project and all bundles.
270
- # @return Array: of Hashes of items
404
+ # @return [Array<Item>] items found
271
405
  def locallist()
272
406
  # so. if @locationbase/bundles exists
273
407
  # gather and merge: @locationbase/bundles/*/@location
@@ -303,6 +437,7 @@ module MrMurano
303
437
 
304
438
  ##
305
439
  # Get the full path for the local versions
440
+ # @return [Pathname] Location for local items
306
441
  def location
307
442
  raise "Missing @project_section" if @project_section.nil?
308
443
  Pathname.new($cfg['location.base']) + $project["#{@project_section}.location"]
@@ -310,12 +445,14 @@ module MrMurano
310
445
 
311
446
  ##
312
447
  # Returns array of globs to search for files
448
+ # @return [Array<String>] of Strings that are globs
313
449
  def searchFor
314
450
  raise "Missing @project_section" if @project_section.nil?
315
451
  $project["#{@project_section}.include"]
316
452
  end
317
453
 
318
454
  ## Returns array of globs of files to ignore
455
+ # @return [Array<String>] of Strings that are globs
319
456
  def ignoring
320
457
  raise "Missing @project_section" if @project_section.nil?
321
458
  $project["#{@project_section}.exclude"]
@@ -327,8 +464,8 @@ module MrMurano
327
464
  # Children rarely need to override this. Only when the locallist is not a set
328
465
  # of files in a directory will they need to override it.
329
466
  #
330
- # @param from Pathname: Directory of items to scan
331
- # @return Array: of Hashes of item details
467
+ # @param from [Pathname] Directory of items to scan
468
+ # @return [Array<Item>] Items found
332
469
  def localitems(from)
333
470
  # TODO: Profile this.
334
471
  debug "#{self.class.to_s}: Getting local items from: #{from}"
@@ -357,6 +494,8 @@ module MrMurano
357
494
  ##
358
495
  # Take a hash or something (a Commander::Command::Options) and return a hash
359
496
  #
497
+ # @param hsh [Hash, Commander::Command::Options] Thing we want to be a Hash
498
+ # @return [Hash] an actual Hash with default value of false
360
499
  def elevate_hash(hsh)
361
500
  # Commander::Command::Options stripped all of the methods from parent
362
501
  # objects. I have not nice thoughts about that.
@@ -374,6 +513,9 @@ module MrMurano
374
513
  #
375
514
  # This creates, uploads, and deletes things as needed up in Murano to match
376
515
  # what is in the local project directory.
516
+ #
517
+ # @param options [Hash, Commander::Command::Options] Options on opertation
518
+ # @param selected [Array<String>] Filters for _matcher
377
519
  def syncup(options={}, selected=[])
378
520
  options = elevate_hash(options)
379
521
  itemkey = @itemkey.to_sym
@@ -413,6 +555,9 @@ module MrMurano
413
555
  #
414
556
  # This creates, downloads, and deletes things as needed up in the local project
415
557
  # directory to match what is in Murano.
558
+ #
559
+ # @param options [Hash, Commander::Command::Options] Options on opertation
560
+ # @param selected [Array<String>] Filters for _matcher
416
561
  def syncdown(options={}, selected=[])
417
562
  options = elevate_hash(options)
418
563
  options[:asdown] = true
@@ -452,9 +597,11 @@ module MrMurano
452
597
  end
453
598
 
454
599
  ## Call external diff tool on item
600
+ #
455
601
  # WARNING: This will download the remote item to do the diff.
456
- # @param item Hash: The item to get a diff of
457
- # @return String: The diff output
602
+ #
603
+ # @param item [Item] The item to get a diff of
604
+ # @return [String] The diff output
458
605
  def dodiff(item)
459
606
  trmt = Tempfile.new([tolocalname(item, @itemkey)+'_remote_', '.lua'])
460
607
  tlcl = Tempfile.new([tolocalname(item, @itemkey)+'_local_', '.lua'])
@@ -487,6 +634,8 @@ module MrMurano
487
634
 
488
635
  ##
489
636
  # Check if an item matches a pattern.
637
+ # @param items [Array<Item>] Of items to filter
638
+ # @param patterns [Array<String>] Filters for _matcher
490
639
  def _matcher(items, patterns)
491
640
  items.map do |item|
492
641
  if patterns.empty? then
@@ -495,7 +644,7 @@ module MrMurano
495
644
  item[:selected] = patterns.any? do |pattern|
496
645
  if pattern.to_s[0] == '#' then
497
646
  match(item, pattern)
498
- elsif not item.has_key? :local_path then
647
+ elsif item.local_path.nil? then
499
648
  false
500
649
  else
501
650
  item[:local_path].fnmatch(pattern)
@@ -508,22 +657,24 @@ module MrMurano
508
657
  private :_matcher
509
658
 
510
659
  ## Get status of things here verses there
660
+ #
661
+ # @param options [Hash, Commander::Command::Options] Options on opertation
662
+ # @param selected [Array<String>] Filters for _matcher
663
+ # @return [Hash{Symbol=>Array<Item>}] Items grouped by the action that should be taken
511
664
  def status(options={}, selected=[])
512
665
  options = elevate_hash(options)
513
666
  itemkey = @itemkey.to_sym
514
667
 
515
- there = _matcher(list(), selected)
516
- here = _matcher(locallist(), selected)
668
+ there = _matcher(list(), selected) # Array<Item>
669
+ here = _matcher(locallist(), selected) # Array<Item>
517
670
 
518
671
  therebox = {}
519
672
  there.each do |item|
520
- item = Hash.transform_keys_to_symbols(item)
521
673
  item[:synckey] = synckey(item)
522
674
  therebox[ item[:synckey] ] = item
523
675
  end
524
676
  herebox = {}
525
677
  here.each do |item|
526
- item = Hash.transform_keys_to_symbols(item)
527
678
  item[:synckey] = synckey(item)
528
679
  herebox[ item[:synckey] ] = item
529
680
  end