nutella_framework 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/README.md +3 -4
  4. data/VERSION +1 -1
  5. data/data/startup +3 -3
  6. data/framework_components/example_framework_interface/dandelion-flowers-card.jpg +0 -0
  7. data/framework_components/example_framework_interface/index.html +18 -0
  8. data/framework_components/main_interface/main_interface_bot.rb +183 -0
  9. data/framework_components/main_interface/public/index.html +54 -0
  10. data/framework_components/main_interface/views/index.erb +63 -0
  11. data/framework_components/order.json.example +6 -0
  12. data/framework_components/runs_list_bot/app_runs_list_bot.rb +15 -0
  13. data/lib/{core/commands → commands}/broker.rb +2 -2
  14. data/lib/{core/commands → commands}/checkup.rb +2 -2
  15. data/lib/commands/compile.rb +13 -0
  16. data/lib/commands/dependencies.rb +13 -0
  17. data/lib/commands/help.rb +35 -0
  18. data/lib/{core/commands → commands}/install.rb +19 -15
  19. data/lib/commands/meta/command.rb +19 -0
  20. data/lib/commands/meta/run_command.rb +114 -0
  21. data/lib/{core → commands/meta}/template_command.rb +1 -1
  22. data/lib/commands/new.rb +60 -0
  23. data/lib/commands/runs.rb +54 -0
  24. data/lib/commands/start.rb +321 -0
  25. data/lib/commands/stop.rb +101 -0
  26. data/lib/{core/commands → commands}/template.rb +59 -39
  27. data/lib/config/current_app_utils.rb +51 -0
  28. data/lib/config/persisted_hash.rb +14 -12
  29. data/lib/config/runlist.rb +116 -16
  30. data/lib/{cli → core}/nutella_cli.rb +1 -1
  31. data/lib/core/nutella_core.rb +2 -6
  32. data/lib/nutella_framework.rb +5 -3
  33. data/lib/nutella_lib_framework/api.rb +333 -0
  34. data/lib/tmux/tmux.rb +76 -0
  35. data/nutella_framework.gemspec +42 -29
  36. data/test/commands/test_cmd_cli_params_parsing.rb +56 -0
  37. data/test/commands/test_command_template.rb +31 -0
  38. data/test/config/test_current_app_utils.rb +34 -0
  39. data/test/config/test_persisted_hash.rb +48 -0
  40. data/test/config/test_runlist.rb +15 -23
  41. data/test/framework_apis/test_framework_api.rb +74 -0
  42. metadata +74 -27
  43. data/actors/main_interface/main_interface_bot.rb +0 -163
  44. data/actors/main_interface/public/index.html +0 -51
  45. data/actors/main_interface/views/index.erb +0 -45
  46. data/lib/config/current_project.rb +0 -58
  47. data/lib/core/command.rb +0 -12
  48. data/lib/core/commands/compile.rb +0 -21
  49. data/lib/core/commands/dependencies.rb +0 -21
  50. data/lib/core/commands/help.rb +0 -28
  51. data/lib/core/commands/new.rb +0 -60
  52. data/lib/core/commands/runs.rb +0 -52
  53. data/lib/core/commands/start.rb +0 -271
  54. data/lib/core/commands/stop.rb +0 -100
  55. data/lib/core/run_command.rb +0 -106
  56. data/lib/core/tmux.rb +0 -38
  57. data/test/config/test_config.rb +0 -48
  58. data/test/config/test_project.rb +0 -34
  59. data/test/test_run_command.rb +0 -54
  60. /data/{actors → framework_components}/main_interface/startup +0 -0
  61. /data/{actors → framework_components}/main_interface/views/not_found_404.erb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 74e4ed28b0dc3798dd7c0d2316d4cc1b7b4b00dc
4
- data.tar.gz: 8b1bd9b75e807c5e061720bdf21a2a367c969d6b
3
+ metadata.gz: 98a1d74bc599d78623959deb2d80d7ef4b5527b0
4
+ data.tar.gz: 229db1d35c9f3000f6510fa44e075878e21b7f07
5
5
  SHA512:
6
- metadata.gz: b7416f84abc2fcde32f84d728d41c9f229e194aadf07be54f77e54231b33f3359f932d1742259064a3e29987072836811cdd485b921fd59f4bff3cf22b34e7bd
7
- data.tar.gz: 9e03507f6f0a018ad06c64ac5b29b02d6989b5fbebb323ff1edc588e464ddb51aa3351c21bf26fa0c7d5407edef08a77df1529ea2b9a59d3533f8aa919b60bae
6
+ metadata.gz: 0673b2e12cd08dd77e2359b3aa05f7d0d9d6b36e415de55f0df13ef201887fd5c1e0303e695bef502cc2b877df6b72a4aa405d358375ff0498635a4178337322
7
+ data.tar.gz: 274b0ea11c7671bb8cb42f1d1179026f5a6cfb04d3af52a60d91b3e3a8d97d804457b248203733b821cc2b75bd7ff390c2e1089822627a5525bbea7a8640ae74
data/Gemfile CHANGED
@@ -5,8 +5,10 @@ gem 'semantic', '~> 1.3', '>=1.3'
5
5
  gem 'logging', '~> 1.8', '>=1.8.2'
6
6
  gem 'git', '~> 1.2', '>=1.2.8'
7
7
  gem 'sinatra', '~>1.4.5', '>=1.4.5'
8
+ gem 'thin', '~>1.6.3', '>=1.6.3'
8
9
  gem 'nokogiri', '~>1.6.3', '>=1.6.3'
9
10
  gem 'slop', '~>4.0.0', '>=4.0.0'
11
+ gem 'nutella_lib','~>0.4.0', '>=0.4.0'
10
12
 
11
13
 
12
14
  group :development do
@@ -20,4 +22,5 @@ end
20
22
 
21
23
  group :test do
22
24
  gem 'rake'
25
+ gem 'fakefs', '~> 0.6.7', '>= 0.6'
23
26
  end
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
 
2
2
  [![Gem Version](https://badge.fury.io/rb/nutella_framework.svg)](http://badge.fury.io/rb/nutella_framework)
3
- [![Build Status](https://travis-ci.org/nutella-framework/nutella_framework.svg?branch=master)](https://travis-ci.org/nutella-framework/nutella_framework)
4
- [![Dependency Status](https://gemnasium.com/nutella-framework/nutella_framework.svg)](https://gemnasium.com/nutella-framework/nutella_framework)
3
+ [![Build Status](https://travis-ci.org/nutella-framework/nutella_framework.svg?branch=master)](https://travis-ci.org/nutella-framework/nutella_framework)
5
4
  [![Code Climate](https://codeclimate.com/github/nutella-framework/nutella_framework/badges/gpa.svg)](https://codeclimate.com/github/nutella-framework/nutella_framework)
6
5
 
7
6
  # Nutella
@@ -34,9 +33,9 @@ Congratulations! Nutella is ready to use!
34
33
 
35
34
 
36
35
  # Where next?
37
- If you already have a projects you want to tinker with (like [RoomQuake](https://github.com/ltg-uic/roomquake)) simply checkout the project to a local folder, `cd /to/my/local/folder` and start tinkering away. Not sure what to do? Check out our [nutella Command Line Tool man page](https://github.com/nutella-framework/nutella_framework/wiki/Nutella-Command-Line-Interface).
36
+ If you already have an application you want to tinker with (like [RoomQuake](https://github.com/ltg-uic/roomquake)) simply checkout the application to a local folder, `cd /to/my/local/folder` and start tinkering away. Not sure what to do? Check out our [nutella Command Line Tool man page](https://github.com/nutella-framework/nutella_framework/wiki/Nutella-Command-Line-Interface).
38
37
 
39
- If you want to create your own project, check out the [new project tutorial](https://github.com/nutella-framework/nutella_framework/wiki/New-project-tutorial).
38
+ If you want to create your own application, check out the [new app tutorial](https://github.com/nutella-framework/nutella_framework/wiki/New-application-tutorial).
40
39
 
41
40
 
42
41
  # Contributing
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4.0
data/data/startup CHANGED
@@ -6,8 +6,8 @@
6
6
  BASEDIR=$(dirname $0)
7
7
 
8
8
 
9
- # Remember that nutella passes the run_id and the broker name as
10
- # command line parameters that you can access via $1 and $2 respectively.
9
+ # Remember: nutella passes the `broker address`, the `app_id` and the `run_id`
10
+ # as command line parameters that you can access via $1, $2 and $3 respectively.
11
11
 
12
12
  # Start your bot here with something like (example in ruby):
13
- # ruby $BASEDIR/my_bot.rb $1 $2
13
+ # ruby $BASEDIR/my_bot.rb $1 $2 $3
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head lang="en">
4
+ <meta charset="UTF-8">
5
+ <title>Example framework interface</title>
6
+ <!-- The description of this interfaces here -->
7
+ <meta name="description" content="This is an example framework interface">
8
+ </head>
9
+ <body>
10
+ <h1>Example framework interface</h1>
11
+ <p>This is an example of a framework interface. It really doesn't belong here but for now this
12
+ is ok. Once we'll have real framework interfaces this is going to be be moved to a template.
13
+ </p>
14
+ <p>And just to make sure we are loading not just the index, here is a picture of dandelions</p>
15
+ <img src="dandelion-flowers-card.jpg" width="500">
16
+
17
+ </body>
18
+ </html>
@@ -0,0 +1,183 @@
1
+ require 'json'
2
+ require 'sinatra'
3
+ require 'nokogiri'
4
+
5
+ # Configuration file and runlist (runlist as global)
6
+ config_file = ARGV[0]
7
+ $runlist_file = ARGV[1]
8
+
9
+ # Try to parse the both config file and runlist and terminate if we can't
10
+ begin
11
+ config_h = JSON.parse(IO.read(config_file))
12
+ JSON.parse(IO.read($runlist_file))
13
+ rescue
14
+ # something went wrong
15
+ abort 'Impossible to parse configuration and/or runlist files!'
16
+ end
17
+
18
+ # Set Sinatra to run in production mode
19
+ set :environment, :production
20
+
21
+ # Set Sinatra's port to nutella's main_interface_port
22
+ set :port, config_h['main_interface_port']
23
+
24
+
25
+
26
+
27
+ # Display the form to input the app_id and run_id
28
+ get '/' do
29
+ send_file 'public/index.html'
30
+ end
31
+
32
+ # Redirect if there is no slash after the run_id
33
+ get '/:app_id/:run_id' do
34
+ redirect "#{request.url}/"
35
+ end
36
+
37
+
38
+ # Renders the interfaces summary page for the run
39
+ get '/:app_id/:run_id/' do
40
+ # Parse the app_id and run_id from URL and extract the run path from runlist.json
41
+ @app_id = params[:app_id]
42
+ @run_id = params[:run_id]
43
+ @app_path = get_app_path @app_id
44
+ # If there is no app with this name, render error page
45
+ return erb( :not_found_404, :locals => {:not_found_type => 'run'} ) if @app_path.nil?
46
+ # To generate the 'index.erb' we need to load a bunch of details
47
+ # (folder, title/name, description) for each interface
48
+ @interfaces = load_interfaces_details @app_path
49
+ @framework_interfaces = load_framework_interfaces
50
+ # Render the interfaces summary page
51
+ erb :index
52
+ end
53
+
54
+ # Redirect if there is a slash after the interface
55
+ get '/:app_id/:run_id/:interface/' do
56
+ redirect "#{request.url[0..-2]}"
57
+ end
58
+
59
+
60
+ # Serves the index.html file for each individual interface augmented with nutella query string parameters
61
+ get '/:app_id/:run_id/runs/:interface' do
62
+ # Parse the app_id and run_id from URL and extract the run path from runlist.json
63
+ app_id = params[:app_id]
64
+ run_id = params[:run_id]
65
+ interface = params[:interface]
66
+ app_path = get_app_path app_id
67
+ # Compose the path of interface index file passing the nutella parameters
68
+ index_file_path = "#{app_path}/interfaces/#{interface}/index.html"
69
+ # If the index file doesn't exist, render error page
70
+ return erb( :not_found_404, :locals => {:not_found_type => 'idx'} ) unless File.exist? index_file_path
71
+ # If the index file exists, compose query string and redirect
72
+ index_with_query_url = "#{request.path}/index.html?broker=#{config_h['broker']}&app_id=#{app_id}&run_id=#{run_id}"
73
+ redirect index_with_query_url
74
+ end
75
+
76
+ # Serves the files contained in each interface folder
77
+ get '/:app_id/:run_id/runs/:interface/*' do
78
+ # Parse the run_id, the interface name and the file_path from URL
79
+ app_id = params[:app_id]
80
+ interface = params[:interface]
81
+ relative_file_path = params[:splat][0]
82
+ app_path = get_app_path app_id
83
+ # Compose the path of the file we are trying to serve
84
+ file_path = "#{app_path}/interfaces/#{interface}/#{relative_file_path}"
85
+ # If the file we are trying to serve doesn't exist, render error page
86
+ return erb( :not_found_404, :locals => {:not_found_type => 'file'} ) unless File.exist? file_path
87
+ # If the file exists, render it
88
+ send_file file_path
89
+ end
90
+
91
+
92
+ # Serve the index file for a framework interface passing the nutella parameters
93
+ get '/:app_id/:run_id/framework/:interface' do
94
+ app_id = params[:app_id]
95
+ run_id = params[:run_id]
96
+ # Filesystem path to the index file
97
+ index_file_path = "#{File.dirname(__FILE__)}/../#{params[:interface]}/index.html"
98
+ # If the index file doesn't exist, render error page
99
+ return erb( :not_found_404, :locals => {:not_found_type => 'idx'} ) unless File.exist? index_file_path
100
+ # If the index file exists, compose query string and redirect
101
+ index_with_query_url = "#{request.path}/index.html?broker=#{config_h['broker']}&app_id=#{app_id}&run_id=#{run_id}"
102
+ redirect index_with_query_url
103
+ end
104
+
105
+ # Serves the files contained in each framework interface folder
106
+ get '/:app_id/:run_id/framework/:interface/*' do
107
+ # Fetch the relative file path
108
+ relative_file_path = params[:splat][0]
109
+ # Compose the path of the file we are trying to serve
110
+ file_path = "#{File.dirname(__FILE__)}/../#{params[:interface]}/#{relative_file_path}"
111
+ # If the file we are trying to serve doesn't exist, render error page
112
+ return erb( :not_found_404, :locals => {:not_found_type => 'file'} ) unless File.exist? file_path
113
+ # If the file exists, render it
114
+ send_file file_path
115
+ end
116
+
117
+
118
+ # Utility functions -------------------------------------------------------------------------
119
+
120
+ # Utility function:
121
+ # Gets the path associated with a certain application
122
+ def get_app_path( app_id )
123
+ begin
124
+ runs_h = JSON.parse(IO.read($runlist_file))
125
+ runs_h[app_id]['path']
126
+ rescue
127
+ nil
128
+ end
129
+ end
130
+
131
+ # Utility function:
132
+ # Loads all the details for all interfaces and stores them into an array of hashes
133
+ def load_interfaces_details( app_path )
134
+ interfaces = Array.new
135
+ interfaces_path = "#{app_path}/interfaces/"
136
+ Dir.entries(interfaces_path).select {|entry| File.directory?(File.join(interfaces_path, entry)) && !(entry =='.' || entry == '..') }.each do |iface_dir|
137
+ interfaces.push extract_interface_info( interfaces_path, iface_dir )
138
+ end
139
+ interfaces
140
+ end
141
+
142
+
143
+ def load_framework_interfaces
144
+ interfaces = Array.new
145
+ components_directory = "#{File.dirname(__FILE__)}/../"
146
+ Dir.entries(components_directory).select {|entry| File.directory?(File.join(components_directory, entry)) && !(entry =='.' || entry == '..') }.each do |iface_dir|
147
+ interfaces.push(extract_interface_info( components_directory, iface_dir)) if File.exist?("#{components_directory}#{iface_dir}/index.html")
148
+ end
149
+ interfaces
150
+ end
151
+
152
+
153
+ # Utility function:
154
+ # Extracts name, description and folder for a single interface from it's index.html
155
+ def extract_interface_info( interfaces_path, iface_dir )
156
+ iface_properties = Hash.new
157
+ index_path = "#{interfaces_path}#{iface_dir}/index.html"
158
+ unless File.exist? index_path
159
+ iface_properties[:name] = iface_dir
160
+ iface_properties[:description] = 'My designer was a bit lazy and didn\'t include an index.html file in the main interface directory :('
161
+ return iface_properties
162
+ end
163
+
164
+ # If file exists, parse it and extract info
165
+ f = File.open index_path
166
+ doc = Nokogiri::HTML f
167
+ f.close
168
+ # Extract interface name from title
169
+ iface_properties[:name] = (doc.css('title').empty? || doc.css('title').text.empty? ) ? iface_dir : doc.css('title').text
170
+ # Extract description from meta description tag
171
+ if doc.css("meta[name='description']").empty?
172
+ iface_properties[:description] = 'My designer was a bit lazy and didn\'t include a &lt;meta name="description" content="Description of this interface"&gt; tag in the index.html file :('
173
+ else
174
+ if doc.css("meta[name='description']").attribute('content').nil?
175
+ iface_properties[:description] = 'There was no attribute content in &lt;meta name="description" content="Description of this interface"&gt; tag in the index.html file :('
176
+ else
177
+ iface_properties[:description] = doc.css("meta[name='description']").attribute('content').text
178
+ end
179
+ end
180
+ # Extract URL from interface dir
181
+ iface_properties[:url] = iface_dir
182
+ iface_properties
183
+ end
@@ -0,0 +1,54 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <title>Welcome to nutella</title>
8
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
9
+
10
+ <style type="text/css">
11
+ div {
12
+ margin-top: 4em;
13
+ text-align: center;
14
+ font-size: 3em;
15
+ }
16
+ .form-control {
17
+ height: 50px;
18
+ width: 20%;
19
+ text-align: center;
20
+ font-size: .7em;
21
+ display: inline-block;
22
+ }
23
+ .center form {
24
+ display:inline-block;
25
+ }
26
+ </style>
27
+ </head>
28
+ <body>
29
+
30
+ <!-- Content -->
31
+ <div>
32
+ <p>What is your app id?
33
+ <input id="app_id_input" type="text" value="" class="form-control" autofocus>
34
+ </p>
35
+ <br />
36
+ <p>What is your run id?
37
+ <input id="run_id_input" type="text" value="" class="form-control" >
38
+ </p>
39
+ </div>
40
+
41
+ <!-- Scripts -->
42
+ <script>
43
+ app_id_el = document.getElementById('app_id_input');
44
+ run_id_el = document.getElementById('run_id_input');
45
+ run_id_el.addEventListener('change', function() {
46
+ var url = location.href
47
+ if (url.substr(url.length - 1)=="/")
48
+ window.location = url + app_id_el.value + '/' + this.value + '/';
49
+ else
50
+ window.location = url + '/' + app_id_el.value + '/'+ this.value + '/';
51
+ });
52
+ </script>
53
+ </body>
54
+ </html>
@@ -0,0 +1,63 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <title><%= @app_id %> interfaces</title>
8
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
9
+
10
+ <style type="text/css">
11
+ .row {
12
+ margin-bottom: 20px;
13
+ }
14
+ </style>
15
+ </head>
16
+ <body>
17
+
18
+ <!-- Content -->
19
+ <div class="container">
20
+
21
+ <!-- Title and prompt -->
22
+ <div class="page-header">
23
+ <% if @run_id == 'default' %>
24
+ <h1>Welcome to <em><%= @app_id %></em></h1>
25
+ <% else %>
26
+ <h1>Welcome to <em><%= @app_id %></em>, run <em><%= @run_id %></em></h1>
27
+ <% end %>
28
+ <p class="lead">Use the buttons below to launch a specific interface</p>
29
+ </div>
30
+
31
+ <!-- Run level interfaces -->
32
+ <% @interfaces.each do |i| %>
33
+ <div class="row">
34
+ <div class="col-xs-1 col-sm-1 col-lg-1"><a href="runs/<%= i[:url] %>" target="_blank" type="button" class="btn btn-danger">Launch!</a></div>
35
+ <div class="col-xs-2 col-sm-2 col-lg-2 text-center"><strong><%= i[:name] %></strong></div>
36
+ <div class="col-xs-9 col-sm-9 col-lg-9"><%= i[:description] %></div>
37
+ </div>
38
+ <% end %>
39
+
40
+ <!-- Framework level interfaces -->
41
+
42
+ <hr>
43
+ <div class="row">
44
+ <h2>Framework level interfaces</h2>
45
+ </div>
46
+
47
+ <% @framework_interfaces.each do |i| %>
48
+ <div class="row">
49
+ <div class="col-xs-1 col-sm-1 col-lg-1"><a href="framework/<%= i[:url] %>" target="_blank" type="button" class="btn btn-danger">Launch!</a></div>
50
+ <div class="col-xs-2 col-sm-2 col-lg-2 text-center"><strong><%= i[:name] %></strong></div>
51
+ <div class="col-xs-9 col-sm-9 col-lg-9"><%= i[:description] %></div>
52
+ </div>
53
+ <% end %>
54
+
55
+
56
+ </div>
57
+
58
+ <!-- Scripts -->
59
+ <script>
60
+
61
+ </script>
62
+ </body>
63
+ </html>
@@ -0,0 +1,6 @@
1
+ // The file order.json contains an array of components name.
2
+ // If this file exists, nutella will start the framework components in that order
3
+ [
4
+ "runs_list_bot",
5
+ "main_interface"
6
+ ]
@@ -0,0 +1,15 @@
1
+ require 'nutella_lib'
2
+
3
+ # This needs to be initialized as framework component like so:
4
+ # nutella.init_as_app_component('localhost', 'app_runs_list_bot')
5
+ nutella.init('localhost', 'my_app_id', 'no_run_id', 'app_runs_list_bot')
6
+
7
+ # Listen for runs_list requests (done by app components when they connect)
8
+ nutella.net.app.handle_requests('app_runs_list', lambda do |req, from|
9
+ from['app_id'] # Use this info to fetch the appropriate runs
10
+ ['run_1', 'run_2', 'run_3'] # Return an array of names!
11
+ end)
12
+
13
+ # Whenever the list is updated, fire an update to the right app
14
+
15
+ nutella.net.listen
@@ -1,4 +1,4 @@
1
- require 'core/command'
1
+ require 'commands/meta/command'
2
2
  require 'socket'
3
3
 
4
4
  module Nutella
@@ -36,7 +36,7 @@ module Nutella
36
36
  def change_broker( new_broker )
37
37
  # Check that there are no runs hinging on this broker
38
38
  unless Nutella.runlist.empty?
39
- console.warn 'You are currently running some projects on this broker. You can\'t change the broker while running.'
39
+ console.warn 'You are currently running some nutella applications on this broker. You can\'t change the broker while running.'
40
40
  return
41
41
  end
42
42
  # Try to parse the hostname and switch to the new broker
@@ -1,9 +1,9 @@
1
- require 'core/command'
1
+ require 'commands/meta/command'
2
2
  require 'semantic'
3
3
 
4
4
  module Nutella
5
5
  class Checkup < Command
6
- @description = 'Checks that all the dependencies are installed and prepares nutella to run'
6
+ @description = 'Checks that all the framework dependencies are installed'
7
7
 
8
8
  def run( args=nil )
9
9
 
@@ -0,0 +1,13 @@
1
+ require 'commands/meta/run_command'
2
+ require 'tmux/tmux'
3
+
4
+ module Nutella
5
+ class Compile < RunCommand
6
+ @description = 'Compiles all the components that need compilation in the application'
7
+
8
+ def run(args=nil)
9
+ compile_and_dependencies 'compile', 'Compiling', 'components compiled'
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'commands/meta/command'
2
+ require 'tmux/tmux'
3
+
4
+ module Nutella
5
+ class Dependencies < RunCommand
6
+ @description = 'Installs the dependencies for all components in the application'
7
+
8
+ def run(args=nil)
9
+ compile_and_dependencies 'dependencies', 'Installing dependencies for', 'dependencies installed'
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,35 @@
1
+ require 'commands/meta/command'
2
+
3
+ module Nutella
4
+
5
+ class Help < Command
6
+ @description = 'Displays what every command does and how to use it'
7
+
8
+ def run(args=nil)
9
+ message=''
10
+ Dir["#{File.dirname(__FILE__)}/*.rb"].each do |file|
11
+ message += add_cmd_help(file)
12
+ end
13
+ console.info message
14
+ console.success 'For more details on individual commands, see https://github.com/nutella-framework/nutella_framework/wiki/Nutella-Command-Line-Interface'
15
+ end
16
+
17
+ private
18
+
19
+ def add_cmd_help(file)
20
+ command = File.basename(file, File.extname(file))
21
+ if command.length > 7
22
+ message = "#{command}\t"
23
+ else
24
+ message = "#{command}\t\t"
25
+ end
26
+ message += Object::const_get("Nutella::#{command.capitalize}").description
27
+ message += "\n"
28
+ message
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+
@@ -1,15 +1,19 @@
1
- require 'core/template_command'
1
+ require 'commands/meta/template_command'
2
2
  require 'git'
3
3
  require 'net/http'
4
4
 
5
5
  module Nutella
6
6
 
7
7
  class Install < TemplateCommand
8
- @description = 'Copies an arbitrary template (from central DB, directory or URL) into the current project'
8
+ @description = 'Copies an arbitrary template (from central DB, directory or URL) into the current application'
9
9
 
10
10
  def run(args=nil)
11
- # Is current directory a nutella prj?
12
- return unless Nutella.current_project.exist?
11
+
12
+ # If the current directory is not a nutella application, return
13
+ unless Nutella.current_app.exist?
14
+ console.warn 'The current directory is not a nutella application'
15
+ return
16
+ end
13
17
 
14
18
  # Check args
15
19
  if args.empty?
@@ -19,16 +23,16 @@ module Nutella
19
23
  template = args[0]
20
24
  destination_dir = args.length==2 ? args[1] : nil
21
25
 
22
- # Extract project directory
23
- prj_dir = Nutella.current_project.dir
26
+ # Extract application directory
27
+ app_path =Dir.pwd
24
28
 
25
29
  # What kind of template are we handling?
26
30
  if is_template_a_local_dir? template
27
- add_local_template( template, template, prj_dir, destination_dir )
31
+ add_local_template( template, template, app_path, destination_dir )
28
32
  elsif is_template_a_git_repo? template
29
- add_remote_template( template, prj_dir, destination_dir)
33
+ add_remote_template( template, app_path, destination_dir)
30
34
  elsif is_template_in_db? template
31
- add_central_template( template, prj_dir, destination_dir)
35
+ add_central_template( template, app_path, destination_dir)
32
36
  else
33
37
  console.warn 'The specified template is not a valid nutella template'
34
38
  end
@@ -55,7 +59,7 @@ module Nutella
55
59
  tmp_dest_dir = template_git_url[template_git_url.rindex('/')+1 .. template_git_url.length]
56
60
  end
57
61
  clone_template_from_repo_to( template_git_url, tmp_dest_dir )
58
- return validate_template "#{Nutella.config['tmp_dir']}/#{tmp_dest_dir}"
62
+ return validate_template "#{Nutella::NUTELLA_TMP}/#{tmp_dest_dir}"
59
63
  rescue
60
64
  return false
61
65
  end
@@ -106,21 +110,21 @@ module Nutella
106
110
 
107
111
  def add_remote_template ( template, prj_dir, dest_dir)
108
112
  template_name = template[template.rindex('/')+1 .. template.length-5]
109
- template_dir = "#{Nutella.config['tmp_dir']}/#{template_name}"
113
+ template_dir = "#{Nutella::NUTELLA_TMP}/#{template_name}"
110
114
  add_local_template( template, template_dir, prj_dir, dest_dir )
111
115
  end
112
116
 
113
117
 
114
118
  def add_central_template( template_name, prj_dir, dest_dir)
115
- template_dir = "#{Nutella.config['tmp_dir']}/#{template_name}"
119
+ template_dir = "#{Nutella::NUTELLA_TMP}/#{template_name}"
116
120
  add_local_template( template_name, template_dir, prj_dir, dest_dir )
117
121
  end
118
122
 
119
123
 
120
124
  def clone_template_from_repo_to(template, dest_dir)
121
125
  clean_tmp_dir
122
- Dir.mkdir Nutella.config['tmp_dir'] unless Dir.exists? Nutella.config['tmp_dir']
123
- Git.clone(template, dest_dir, :path => Nutella.config['tmp_dir'])
126
+ Dir.mkdir Nutella::NUTELLA_TMP unless Dir.exists? Nutella::NUTELLA_TMP
127
+ Git.clone(template, dest_dir, :path => Nutella::NUTELLA_TMP)
124
128
  end
125
129
 
126
130
 
@@ -132,7 +136,7 @@ module Nutella
132
136
 
133
137
 
134
138
  def clean_tmp_dir
135
- FileUtils.rm_rf "#{Nutella.config['tmp_dir']}"
139
+ FileUtils.rm_rf "#{Nutella::NUTELLA_TMP}"
136
140
  end
137
141
 
138
142
  end
@@ -0,0 +1,19 @@
1
+
2
+
3
+ module Nutella
4
+
5
+ # Nutella command
6
+ class Command
7
+
8
+ class << self;
9
+ attr_accessor :description
10
+ end
11
+
12
+ # Commands overload this method to execute
13
+ def run( args=nil )
14
+ console.error 'Running the generic command!!! WAT? https://www.destroyallsoftware.com/talks/wat'
15
+ end
16
+
17
+ end
18
+
19
+ end