yuyi 1.0.8 → 1.1.3

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.
data/lib/yuyi/menu.rb CHANGED
@@ -1,155 +1,65 @@
1
- class Yuyi::Menu
2
- @rolls = {}
1
+ require 'readline'
3
2
 
4
- # DSL Helper methods
3
+ class Yuyi::Menu
4
+ # Stores a single menu instance on the class
5
+ # If a new menu is initialized, it will become the only menu accessible through Yuyi::Menu.menu
5
6
  #
6
- def self.instance; @@instance; end
7
-
8
- def self.object; @object; end
9
- def object; self.class.object; end
10
-
11
- def self.sources; @@instance.sources; end
12
- def sources; @sources; end
13
-
14
- def self.rolls; @rolls; end
15
- def rolls; self.class.rolls; end
16
-
17
- def self.path
18
- @@instance.path
19
- end
20
- def path; @path; end
7
+ @@menu = nil
21
8
 
22
- def self.on_the_menu? roll
23
- @@instance.on_the_menu? roll
24
- end
25
-
26
- def self.find_roll name, options = {}
27
- @@instance.find_roll name, options
28
- end
9
+ # Create a new menu that stores the raw yaml file
10
+ # along with source, roll, and roll model instances
11
+ #
12
+ def initialize path
13
+ # make menu instance accessible by the class
14
+ @@menu = self
15
+ @rolls = {}
16
+ @sources = []
29
17
 
30
- def self.set_sources
31
- @@instance.set_sources
32
- end
18
+ # load a yaml file
19
+ load_from_file path
33
20
 
34
- def self.upgrade? boolean = nil
35
- @@instance.upgrade? boolean
21
+ # create objects from the menu
22
+ set_sources
23
+ set_roll_models
24
+ set_rolls
36
25
  end
37
26
 
38
- def self.options roll
39
- @@instance.options roll
27
+ def options roll
28
+ @yaml[:rolls][roll] || {}
40
29
  end
41
30
 
42
- # Attempt to load a menu from a file path
31
+ # DSL METHODS
43
32
  #
44
- def self.load_from_file path = path
45
- menu = begin
46
- File.open(File.expand_path(path))
47
- rescue
48
- response = Yuyi.run "curl -sS #{path}"
49
- $?.success? ? response : nil
50
- end
51
-
52
- @object = begin
53
- YAML.load(menu).deep_symbolize_keys!
54
- rescue
55
- nil
56
- end
33
+ def self.sources
34
+ menu.send :sources
57
35
  end
58
36
 
59
37
  # Add rolls to hash in format of {file_name: RollInstance}
60
- # Called from yuyi/roll.rb#self.inherited
38
+ # Called from Yuyi::Roll when a roll is inherited
61
39
  #
62
40
  def self.add_roll file_name, klass
63
- @rolls[file_name] = klass.new
64
- end
65
-
66
- # Get/Set upgrade flag
67
- #
68
- def upgrade? boolean = nil
69
- @upgrade = boolean.nil? ? @upgrade : boolean
70
- end
71
-
72
- # Check if a roll is on the menu
73
- #
74
- def on_the_menu? roll
75
- object[:rolls].keys.include? roll
76
- end
77
-
78
- # Download & create all sources on the menu
79
- #
80
- def set_sources
81
- if object[:sources].empty?
82
- Yuyi.say 'No rolls could be found because no sources were set in your menu.'
83
- return
41
+ unless klass.to_s.include? 'RollModel'
42
+ rolls[file_name] = klass.new
84
43
  end
85
-
86
- @sources = []
87
- object[:sources].each do |source|
88
- source.each do |name, path|
89
- @sources << Yuyi::Source.new(name, path)
90
- end
91
- end
92
-
93
- @sources
94
44
  end
95
45
 
96
- def options roll
97
- object[:rolls][roll.file_name] || {}
46
+ def self.on_the_menu? roll
47
+ menu.send :on_the_menu?, roll
98
48
  end
99
49
 
100
- # Initialize all the rolls in order
101
- #
102
- def order_rolls
103
- header_length = 80
104
- all_rolls = sorted_rolls
105
-
106
-
107
- # pre installs
108
- #
109
- Yuyi.say '=' * header_length, :color => 35
110
- Yuyi.say 'APPETIZERS', :color => 35, :justify => :center, :padding => header_length
111
- Yuyi.say 'Pre Install', :justify => :center, :padding => header_length
112
- Yuyi.say
113
-
114
- all_rolls.each do |file_name|
115
- rolls[file_name].appetizers
116
- end
117
-
118
-
119
- # main installs
120
- #
121
- Yuyi.say '=' * header_length, :color => 36
122
- Yuyi.say 'ENTREES', :color => 36, :justify => :center, :padding => header_length
123
- Yuyi.say 'Main Install', :justify => :center, :padding => header_length
124
- Yuyi.say
125
-
126
- all_rolls.each do |file_name|
127
- rolls[file_name].entree
128
- end
129
-
130
-
131
- # post installs
132
- #
133
- Yuyi.say '=' * header_length, :color => 35
134
- Yuyi.say 'DESSERT', :color => 35, :justify => :center, :padding => header_length
135
- Yuyi.say 'Post Install', :justify => :center, :padding => header_length
136
- Yuyi.say
137
-
138
- all_rolls.each do |file_name|
139
- rolls[file_name].dessert
140
- end
141
-
50
+ def self.find_roll name, options = {}
51
+ menu.send :find_roll, name, options
52
+ end
142
53
 
143
- Yuyi.say '=' * header_length, :color => 36
144
- Yuyi.say 'YUYI COMPLETED', :color => 36, :justify => :center, :padding => header_length
145
- Yuyi.say '=' * header_length, :color => 36
146
- Yuyi.say
54
+ def self.load_from_file
55
+ menu.send :load_from_file
147
56
  end
148
57
 
149
- # Find the best roll in the source to be added
58
+ # Find the best roll match from the sources and require it
150
59
  #
151
60
  def find_roll name, options = {}
152
- options ||= {}
61
+ return if on_the_menu? name
62
+
153
63
  # return specific source roll if specified in the menu
154
64
  #
155
65
  if source = options[:source]
@@ -159,8 +69,8 @@ class Yuyi::Menu
159
69
  # look through the sources for the first roll that matches.
160
70
  # sources are listed in the menu in order of priority
161
71
  else
162
- sources.each do |source|
163
- if path = source.available_rolls[name]
72
+ @sources.each do |source|
73
+ if path = source.rolls[name]
164
74
  require_roll name, path
165
75
  return
166
76
  end
@@ -173,62 +83,111 @@ class Yuyi::Menu
173
83
  Yuyi.say
174
84
  end
175
85
 
176
- # Find the best roll in the source to be added
177
- #
178
- def find_roll_model name, path
179
- # look through the sources for the first roll model that matches.
180
- # sources are listed in the menu in order of priority
181
- sources.each do |source|
182
- if path = source.roll_models[name]
183
- require path
86
+ private
87
+
88
+ # CLASS METHODS
89
+ #
90
+ def self.menu; @@menu; end
91
+ def self.menu_path; @@menu.send :menu_path; end
92
+ def self.order; @@menu.send :order; end
93
+ def self.rolls; @@menu.send :rolls; end
94
+ def self.sources; @@menu.send :sources; end
95
+
96
+ def self.options roll
97
+ @@menu.options roll
98
+ end
99
+
100
+ # INSTANCE METHODS
101
+ #
102
+ def menu_path; @menu_path; end
103
+ def rolls; @rolls; end
104
+ def sources; @sources; end
105
+
106
+ # Attempt to load a menu from a file path
107
+ #
108
+ def load_from_file menu_path = @menu_path
109
+ if !menu_path || menu_path.empty?
110
+ get_menu_path
184
111
  return
185
112
  end
186
- end
187
- end
188
113
 
189
- private
114
+ unless @menu_path
115
+ # check if path is local first
116
+ begin
117
+ File.open(File.expand_path(menu_path))
118
+
119
+ @menu_path = File.expand_path(menu_path)
190
120
 
191
- def initialize path
192
- return unless Yuyi::Menu.load_from_file path
121
+ # otherwise assume it is remote and try to download it
122
+ rescue
123
+ # try to download the menu path
124
+ response = Yuyi.run "curl -sS #{menu_path}"
193
125
 
194
- @path = path
195
- @@instance = self
126
+ # save a local copy of the remote menu
127
+ if $?.success?
128
+ # if a menu was downloaded, save the response to a local file
129
+ local_file_name = Yuyi::DEFAULT_MENU.clone << '_remote'
196
130
 
197
- set_sources
198
- set_roll_models
199
- set_rolls
131
+ File.open local_file_name, 'w+' do |f|
132
+ f.write response
133
+ end
134
+
135
+ @menu_path = local_file_name
136
+ end
137
+ end
138
+ end
139
+
140
+ begin
141
+ @yaml = YAML.load(File.open(@menu_path)).deep_symbolize_keys!
142
+ rescue
143
+ Yuyi.say "No menu could be loaded from `#{menu_path}`", :type => :fail
144
+ get_menu_path
145
+ end
200
146
  end
201
147
 
202
- # Create all rolls on the menu
148
+ # prompt the user to enter a path to menu file
149
+ # keep prompting until path is valid
203
150
  #
204
- def set_roll_models
205
- object[:roll_models] = {}
206
-
207
- # collect all roll models from all sources
208
- sources.each do |source|
209
- source.roll_models.each do |name, path|
210
- object[:roll_models][name] = path
151
+ def get_menu_path
152
+ until @yaml
153
+ Yuyi.say 'Navigate to a menu file...', :type => :success
154
+ Yuyi.ask "...or just press enter to load `#{Yuyi::DEFAULT_MENU}`", :readline => true, :color => 36 do |user_path|
155
+ menu_path = user_path.empty? ? Yuyi::DEFAULT_MENU : user_path
156
+ load_from_file menu_path
211
157
  end
212
158
  end
159
+ end
160
+
161
+ # Initialize sources from menu
162
+ #
163
+ def set_sources
164
+ @yaml[:sources].each do |name, path|
165
+ @sources << Yuyi::Source.new(name, path)
166
+ end
167
+ end
213
168
 
214
- object[:roll_models].each do |name, path|
215
- find_roll_model name, path
169
+ # Loop through the roll models in the yaml file and find a matching roll
170
+ def set_roll_models
171
+ @sources.each do |source|
172
+ source.roll_models.values.each do |roll_model_path|
173
+ require roll_model_path
174
+ end
216
175
  end
217
176
  end
218
177
 
219
- # Create all rolls on the menu
178
+ # Loop through the rolls in the yaml file and find a matching roll
220
179
  #
221
180
  def set_rolls
222
- object[:rolls].each do |name, options|
223
- find_roll name, options
181
+ @yaml[:rolls].each do |roll_name, roll_options|
182
+ find_roll roll_name, roll_options || {}
224
183
  end
225
184
  end
226
185
 
227
- # Require a single roll
186
+ # Add a single roll to the menu
228
187
  #
229
188
  def require_roll name, path
230
189
  # check if already on the roll for when requiring dependencies
231
- return if roll_loaded? name
190
+ return if on_the_menu? name
232
191
 
233
192
  begin
234
193
  require path
@@ -239,17 +198,66 @@ private
239
198
  end
240
199
  end
241
200
 
242
- # Check if roll has already been required & loaded
201
+ # Check if roll has already been added
243
202
  #
244
- def roll_loaded? roll
245
- rolls.keys.include? roll
203
+ def on_the_menu? roll
204
+ @rolls.keys.include? roll
205
+ end
206
+
207
+ # Initialize all the rolls in order
208
+ #
209
+ def order
210
+ header_length = 80
211
+ all_rolls = sorted_rolls
212
+
213
+
214
+ # pre installs
215
+ #
216
+ Yuyi.say '=' * header_length, :color => 35
217
+ Yuyi.say 'APPETIZERS', :color => 35, :justify => :center, :padding => header_length
218
+ Yuyi.say 'Pre Install', :justify => :center, :padding => header_length
219
+ Yuyi.say
220
+
221
+ all_rolls.each do |file_name|
222
+ @rolls[file_name].appetizers
223
+ end
224
+
225
+
226
+ # main installs
227
+ #
228
+ Yuyi.say '=' * header_length, :color => 36
229
+ Yuyi.say 'ENTREES', :color => 36, :justify => :center, :padding => header_length
230
+ Yuyi.say 'Main Install', :justify => :center, :padding => header_length
231
+ Yuyi.say
232
+
233
+ all_rolls.each do |file_name|
234
+ @rolls[file_name].entree
235
+ end
236
+
237
+
238
+ # post installs
239
+ #
240
+ Yuyi.say '=' * header_length, :color => 35
241
+ Yuyi.say 'DESSERT', :color => 35, :justify => :center, :padding => header_length
242
+ Yuyi.say 'Post Install', :justify => :center, :padding => header_length
243
+ Yuyi.say
244
+
245
+ all_rolls.each do |file_name|
246
+ @rolls[file_name].dessert
247
+ end
248
+
249
+
250
+ Yuyi.say '=' * header_length, :color => 36
251
+ Yuyi.say 'YUYI COMPLETED', :color => 36, :justify => :center, :padding => header_length
252
+ Yuyi.say '=' * header_length, :color => 36
253
+ Yuyi.say
246
254
  end
247
255
 
248
256
  # Return an array of the topologically sorted rolls from the menu
249
257
  #
250
258
  def sorted_rolls
251
259
  tsort_hash = {}
252
- rolls.each do |file_name, roll|
260
+ @rolls.each do |file_name, roll|
253
261
  tsort_hash[file_name.to_s] = roll.dependencies.map(&:to_s)
254
262
  end
255
263