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.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/Gemfile +3 -2
- data/MuranoCLI.gemspec +2 -2
- data/README.markdown +107 -10
- data/lib/MrMurano/Product-Resources.rb +10 -0
- data/lib/MrMurano/ProjectFile.rb +7 -0
- data/lib/MrMurano/Solution-Endpoint.rb +24 -12
- data/lib/MrMurano/Solution-File.rb +17 -5
- data/lib/MrMurano/Solution-ServiceConfig.rb +7 -5
- data/lib/MrMurano/Solution-Services.rb +61 -31
- data/lib/MrMurano/SyncUpDown.rb +200 -49
- data/lib/MrMurano/commands/gb.rb +4 -3
- data/lib/MrMurano/commands/init.rb +55 -3
- data/lib/MrMurano/commands/login.rb +20 -0
- data/lib/MrMurano/commands/password.rb +12 -9
- data/lib/MrMurano/commands/status.rb +5 -1
- data/lib/MrMurano/commands.rb +1 -1
- data/lib/MrMurano/version.rb +1 -1
- data/spec/Account_spec.rb +8 -0
- data/spec/ConfigMigrate_spec.rb +3 -0
- data/spec/Config_spec.rb +16 -1
- data/spec/Solution-Endpoint_spec.rb +28 -20
- data/spec/Solution-ServiceEventHandler_spec.rb +27 -21
- data/spec/Solution-ServiceModules_spec.rb +42 -43
- data/spec/SyncUpDown_spec.rb +75 -68
- data/spec/cmd_init_spec.rb +303 -9
- data/spec/cmd_status_spec.rb +14 -12
- data/spec/spec_helper.rb +4 -1
- metadata +7 -6
@@ -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
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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.
|
208
|
-
|
236
|
+
if remote.service.nil? or remote.event.nil? then
|
237
|
+
raise "Missing parts! #{remote.to_h.to_json}"
|
209
238
|
else
|
210
|
-
|
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.
|
216
|
-
|
244
|
+
if remote.service.nil? or remote.event.nil? then
|
245
|
+
raise "Missing parts! #{remote.to_h.to_json}"
|
217
246
|
else
|
218
|
-
|
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 =
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
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 =
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
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
|
data/lib/MrMurano/SyncUpDown.rb
CHANGED
@@ -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
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
60
|
-
#
|
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
|
-
#
|
74
|
+
# @param opt [Hash{Symbol=>Boolean}] Options hash of which to select from
|
74
75
|
#
|
75
|
-
#
|
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
|
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
|
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
|
121
|
-
# @param item Hash
|
122
|
-
# @param modify Bool
|
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 [
|
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
|
-
|
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
|
167
|
-
# @param itemkey Symbol
|
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
|
181
|
-
# @param item
|
182
|
-
# @return Pathname
|
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]
|
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
|
-
# @
|
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
|
209
|
-
# @
|
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
|
220
|
-
# @param item
|
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
|
247
|
-
# @param item
|
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
|
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
|
331
|
-
# @return Array
|
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
|
-
#
|
457
|
-
# @
|
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
|
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
|