MuranoCLI 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|