nyara 0.1.pre.0 → 0.1.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nyara +2 -14
  3. data/changes +3 -0
  4. data/example/factorial.rb +19 -0
  5. data/example/hello.rb +5 -0
  6. data/example/project.rb +11 -0
  7. data/example/stream.rb +14 -0
  8. data/ext/extconf.rb +19 -0
  9. data/ext/hashes.c +160 -57
  10. data/ext/inc/ary_intern.h +36 -0
  11. data/ext/route.cc +2 -1
  12. data/ext/url_encoded.c +1 -0
  13. data/lib/nyara.rb +1 -0
  14. data/lib/nyara/command.rb +60 -79
  15. data/lib/nyara/config.rb +19 -1
  16. data/lib/nyara/controller.rb +64 -7
  17. data/lib/nyara/hashes/config_hash.rb +3 -20
  18. data/lib/nyara/hashes/header_hash.rb +2 -2
  19. data/lib/nyara/hashes/param_hash.rb +1 -0
  20. data/lib/nyara/nyara.rb +45 -37
  21. data/lib/nyara/part.rb +2 -2
  22. data/lib/nyara/reload.rb +63 -64
  23. data/lib/nyara/route.rb +7 -6
  24. data/lib/nyara/session.rb +4 -0
  25. data/lib/nyara/templates/{Gemfile → Gemfile.tt} +4 -0
  26. data/lib/nyara/templates/Linnerfile +28 -0
  27. data/lib/nyara/templates/Rakefile +16 -2
  28. data/lib/nyara/templates/app/assets/files/favicon.ico +1 -0
  29. data/lib/nyara/templates/app/assets/files/robots.txt +5 -0
  30. data/lib/nyara/templates/app/assets/scripts/app.coffee +4 -0
  31. data/lib/nyara/templates/app/assets/scripts/module-example.coffee +4 -0
  32. data/lib/nyara/templates/app/assets/styles/app.scss +2 -0
  33. data/lib/nyara/templates/app/controllers/application_controller.rb +8 -0
  34. data/lib/nyara/templates/app/views/layouts/application.erb.tt +12 -0
  35. data/lib/nyara/templates/config/application.rb +4 -0
  36. data/lib/nyara/templates/config/{database.yml → database.yml.tt} +3 -3
  37. data/lib/nyara/templates/config/production.rb +2 -0
  38. data/lib/nyara/view.rb +6 -2
  39. data/nyara.gemspec +3 -1
  40. data/rakefile +7 -26
  41. data/spec/apps/reload.rb +35 -0
  42. data/spec/command_spec.rb +24 -10
  43. data/spec/config_spec.rb +19 -8
  44. data/spec/controller_spec.rb +14 -0
  45. data/spec/evented_io_spec.rb +3 -1
  46. data/spec/ext_route_spec.rb +25 -3
  47. data/spec/hashes_spec.rb +45 -21
  48. data/spec/integration_spec.rb +28 -2
  49. data/spec/path_helper_spec.rb +7 -0
  50. data/spec/performance_spec.rb +1 -1
  51. data/spec/public/test.css +1 -0
  52. data/{lib/nyara/templates/public/robot.txt → spec/public/test.jpg} +0 -0
  53. data/spec/public/test.js +1 -0
  54. data/spec/reload_spec.rb +50 -0
  55. data/spec/route_spec.rb +4 -4
  56. data/spec/spec_helper.rb +15 -9
  57. data/spec/url_encoded_spec.rb +5 -0
  58. data/spec/view_spec.rb +7 -0
  59. data/spec/views/_partial.slim +1 -1
  60. data/tools/bug.rb +53 -0
  61. data/tools/hello.rb +49 -0
  62. data/tools/memcheck.rb +33 -0
  63. metadata +73 -41
  64. data/ext/inc/status_codes.inc +0 -64
  65. data/lib/nyara/templates/app/views/layouts/application.erb +0 -12
  66. data/lib/nyara/templates/public/css/app.css +0 -1
  67. data/lib/nyara/templates/public/js/app.js +0 -1
@@ -8,14 +8,14 @@ module Nyara
8
8
  CONTENT_TYPE = 'Content-Type'.freeze
9
9
 
10
10
  def aref_content_type
11
- self._aref CONTENT_TYPE
11
+ _aref CONTENT_TYPE
12
12
  end
13
13
 
14
14
  def aset_content_type value
15
15
  unless value.index 'charset'
16
16
  value = "#{value}; charset=UTF-8"
17
17
  end
18
- self._aset CONTENT_TYPE, value
18
+ _aset CONTENT_TYPE, value
19
19
  end
20
20
  end
21
21
  end
@@ -3,5 +3,6 @@ module Nyara
3
3
  # All keys are stored in String form.
4
4
  class ParamHash
5
5
  alias has_key? key?
6
+ private :nested_aset, :nested_aref
6
7
  end
7
8
  end
data/lib/nyara/nyara.rb CHANGED
@@ -26,7 +26,6 @@ require_relative "route"
26
26
  require_relative "view"
27
27
  require_relative "cpu_counter"
28
28
  require_relative "part"
29
- require_relative "command"
30
29
 
31
30
  module Nyara
32
31
  HTTP_STATUS_FIRST_LINES = Hash[HTTP_STATUS_CODES.map{|k,v|[k, "HTTP/1.1 #{k} #{v}\r\n".freeze]}].freeze
@@ -61,7 +60,7 @@ module Nyara
61
60
  Config
62
61
  end
63
62
 
64
- %w[logger env production? test? development? project_path views_path public_path].each do |m|
63
+ %w[logger env production? test? development? project_path assets_path views_path public_path].each do |m|
65
64
  eval <<-RUBY
66
65
  def #{m} *xs
67
66
  Config.#{m} *xs
@@ -77,42 +76,49 @@ module Nyara
77
76
  View.init
78
77
  end
79
78
 
79
+ # load with Config['app_files']
80
80
  def load_app
81
+ app_files = Config['app_files']
82
+ return unless app_files
83
+
81
84
  Dir.chdir Config.root do
85
+ # NOTE app_files can be an array
86
+ Dir.glob Config['app_files'] do |file|
87
+ require Config.project_path file
88
+ end
82
89
  if Config.development?
83
90
  require_relative "reload"
84
- Reload.init do
85
- # NOTE app_files can be an array
86
- Dir.glob(Config['app_files']).uniq.each do |file|
87
- Reload.load_file Config.project_path file
88
- end
89
- end
90
- else
91
- Dir.glob Config['app_files'] do |file|
92
- require Config.project_path file
93
- end
91
+ Reload.listen
92
+ @reload = Reload
94
93
  end
95
94
  end
96
95
  end
97
96
 
98
97
  def start_server
99
- port = Config[:port]
98
+ port = Config['port']
99
+ env = Config['env']
100
100
 
101
101
  if l = logger
102
- l.info "starting #{Config[:env]} server at 0.0.0.0:#{port}"
102
+ l.info "starting #{env} server at 0.0.0.0:#{port}"
103
103
  end
104
- case Config[:env].to_s
104
+ case env.to_s
105
105
  when 'production'
106
- patch_tcp_socket
107
106
  start_production_server port
108
107
  when 'test'
109
108
  # don't
110
109
  else
111
- patch_tcp_socket
110
+ start_watch_assets
112
111
  start_development_server port
113
112
  end
114
113
  end
115
114
 
115
+ def start_watch_assets
116
+ return if Config[:assets].blank?
117
+ Process.fork do
118
+ exec 'bundle exec linner watch'
119
+ end
120
+ end
121
+
116
122
  def patch_tcp_socket
117
123
  if l = logger
118
124
  l.info "patching TCPSocket"
@@ -121,17 +127,14 @@ module Nyara
121
127
  end
122
128
 
123
129
  def start_development_server port
124
- trap :INT do
125
- exit!
126
- end
130
+ create_tcp_server port
131
+ @workers = []
132
+ incr_workers nil
127
133
 
128
- t = Thread.new do
129
- server = TCPServer.new '0.0.0.0', port
130
- server.listen 1000
131
- Ext.init_queue
132
- Ext.run_queue server.fileno
133
- end
134
- t.join
134
+ trap :INT, &method(:kill_all)
135
+ trap :QUIT, &method(:kill_all)
136
+ trap :TERM, &method(:kill_all)
137
+ Process.waitall
135
138
  end
136
139
 
137
140
  # Signals:
@@ -161,16 +164,7 @@ module Nyara
161
164
  workers = Config[:workers]
162
165
 
163
166
  puts "workers: #{workers}"
164
-
165
- if (server_fd = ENV['NYARA_FD'].to_i) > 0
166
- puts "inheriting server fd #{server_fd}"
167
- @server = TCPServer.for_fd server_fd
168
- end
169
- unless @server
170
- @server = TCPServer.new '0.0.0.0', port
171
- @server.listen 1000
172
- ENV['NYARA_FD'] = @server.fileno.to_s
173
- end
167
+ create_tcp_server port
174
168
 
175
169
  GC.start
176
170
  @workers = []
@@ -198,11 +192,24 @@ module Nyara
198
192
 
199
193
  private
200
194
 
195
+ def create_tcp_server port
196
+ if (server_fd = ENV['NYARA_FD'].to_i) > 0
197
+ puts "inheriting server fd #{server_fd}"
198
+ @server = TCPServer.for_fd server_fd
199
+ end
200
+ unless @server
201
+ @server = TCPServer.new '0.0.0.0', port
202
+ @server.listen 1000
203
+ ENV['NYARA_FD'] = @server.fileno.to_s
204
+ end
205
+ end
206
+
201
207
  # Kill all workers and exit
202
208
  def kill_all sig
203
209
  @workers.each do |w|
204
210
  Process.kill :KILL, w
205
211
  end
212
+ @reload.stop if @reload
206
213
  exit!
207
214
  end
208
215
 
@@ -254,6 +261,7 @@ module Nyara
254
261
  def incr_workers sig
255
262
  Config['before_fork'].call if Config['before_fork']
256
263
  pid = fork {
264
+ patch_tcp_socket
257
265
  $0 = "(nyara:worker) ruby #{$0}"
258
266
  Config['after_fork'].call if Config['after_fork']
259
267
 
data/lib/nyara/part.rb CHANGED
@@ -103,11 +103,11 @@ module Nyara
103
103
  keys = ParamHash.split_name(name)
104
104
 
105
105
  if self['filename']
106
- params.nested_aset keys, self
106
+ params.send :nested_aset, keys, self
107
107
  elsif self['type']
108
108
  warn "looks like bad part: #{self['header'].inspect}"
109
109
  else
110
- params.nested_aset keys, CGI.unescape(self['data'])
110
+ params.send :nested_aset, keys, CGI.unescape(self['data'])
111
111
  end
112
112
  end
113
113
 
data/lib/nyara/reload.rb CHANGED
@@ -2,84 +2,83 @@ require "listen"
2
2
 
3
3
  module Nyara
4
4
  # listen to fs events and reload code / views
5
- # todo add to development env: require 'nyara/reload'; Reload.listen
6
5
  module Reload
7
- # init, should require all files that needs to be reloaded in the given block
8
- def self.init
9
- @new_classes = []
10
- @trace_point = TracePoint.new :class do |tp|
11
- @new_classes << tp.self.to_s.to_sym
12
- end
13
- @file_list = {}
14
- @first_load = true
15
- yield
16
- @first_load = false
17
- end
18
6
 
19
- # NOTE file should end with '.rb'
20
- def self.load_file file
21
- if consts = @file_list[file]
22
- consts.reverse_each do |const|
23
- Object.send :remove_const, const
24
- end
25
- end
7
+ extend self
26
8
 
27
- @trace_point.enable
28
- old_consts = Object.send :constants
29
- if @first_load
30
- require file
31
- else
32
- if l = Nyara.logger
33
- l.info "reloading: #{file}"
34
- end
35
- begin
36
- load file
37
- @last_error = nil
38
- rescue Exception
39
- @last_error = $!
9
+ # NOTE file should end with '.rb'<br>
10
+ # returns last error
11
+ def load_file file
12
+ verbose = $VERBOSE
13
+ $VERBOSE = nil
14
+ begin
15
+ load file
16
+ @last_error = nil
17
+ rescue Exception
18
+ @last_error = $!
19
+ ensure
20
+ $VERBOSE = verbose
21
+ end
22
+ if l = Nyara.logger
23
+ if @last_error
24
+ l.error @last_error
40
25
  end
41
26
  end
42
- @trace_point.disable
43
- added_consts = Object.send(:constants) - old_consts
44
-
45
- added_consts.concat @new_classes
46
- @new_classes.clear
47
- added_consts.uniq!
48
- added_consts.sort!
49
-
50
- @file_list[file] = added_consts
51
- @last_error
52
27
  end
28
+ attr_reader :last_error
53
29
 
54
30
  # start listening
55
- def self.listen
56
- views_path = Config.views_path('/')
57
- if views_path
58
- if l = Nyara.logger
59
- l.info "watching views change under #{views_path}"
60
- end
61
- Listen.to Config.views_path('/'), relative_paths: true do |modified, added, removed|
62
- modified.each do |file|
63
- View.on_modified file
64
- end
65
- removed.each do |file|
66
- View.on_removed file
67
- end
31
+ def listen
32
+ @port = Config['port']
33
+ app_path = Config['root']
34
+ views_path = Config.views_path('/', false)
35
+ if l = Nyara.logger
36
+ l.info "watching app and view changes under #{app_path}"
37
+ unless views_path.start_with?(app_path)
38
+ l.warn "views not under project dir, changes not watched"
68
39
  end
69
40
  end
41
+ @app_listener = hook_app_reload app_path
42
+ @views_listener = hook_views_reload views_path
43
+ end
70
44
 
71
- return unless Config.development?
72
- if l = Nyara.logger
73
- l.info "watching app change under #{Config['root']}"
45
+ # cleanup workers
46
+ def stop
47
+ if @app_listener.adapter.worker
48
+ @app_listener.adapter.worker.stop
74
49
  end
75
- Listen.to Config['root'], filter: /\.rb$/, relative_paths: false do |modified, added, removed|
76
- (added + modified).uniq.each do |file|
77
- load_file file
78
- end
79
- # (1.0) todo send notification on bad files
50
+ if @views_listener.adapter.worker
51
+ @views_listener.adapter.worker.stop
80
52
  end
81
53
  end
82
54
 
83
- # todo (don't forget wiki doc!)
55
+ # ---
56
+ # private
57
+ # +++
58
+
59
+ def hook_app_reload app_path
60
+ l = Listen.to(app_path).relative_paths(false).filter(/\.rb$/).change do |modified, added, removed|
61
+ notify 'app-modified', (added + modified).uniq
62
+ end
63
+ l.start
64
+ l
65
+ end
66
+
67
+ def hook_views_reload views_path
68
+ l = Listen.to(views_path).relative_paths(true).change do |modified, added, removed|
69
+ notify 'views-modified', (added + modified).uniq
70
+ notify 'views-removed', removed
71
+ end
72
+ l.start
73
+ l
74
+ end
75
+
76
+ def notify leader, files
77
+ return if files.empty?
78
+ data = files.to_query('files')
79
+ s = TCPSocket.new 'localhost', @port
80
+ s << "POST /reload:#{leader}\r\nContent-Length: #{data.bytesize}\r\n\r\n" << data
81
+ s.close
82
+ end
84
83
  end
85
84
  end
data/lib/nyara/route.rb CHANGED
@@ -158,8 +158,6 @@ module Nyara
158
158
  def analyse_path path
159
159
  raise 'path must contain no new line' if path.index "\n"
160
160
  raise 'path must start with /' unless path.start_with? '/'
161
- path = path.sub(/\/$/, '') if path != '/'
162
-
163
161
  path.split(FORWARD_SPLIT, 2)
164
162
  end
165
163
  end
@@ -240,12 +238,15 @@ module Nyara
240
238
  end
241
239
 
242
240
  def print_routes
243
- puts "all routes:"
241
+ puts "All routes:"
244
242
  Nyara::Route.routes.each do |route|
245
- print (route.id || "").gsub("#", "").rjust(30), " "
243
+ cname = route.controller.to_s
244
+ cname.gsub!("Controller", "")
245
+ cname.downcase!
246
+ print "#{cname}#{route.id}".rjust(30), " "
246
247
  print route.http_method_to_s.ljust(6), " "
247
- print route.path
248
- puts ""
248
+ print route.path_template
249
+ puts
249
250
  end
250
251
  end
251
252
 
data/lib/nyara/session.rb CHANGED
@@ -133,6 +133,10 @@ module Nyara
133
133
  OpenSSL::PKey::DSA.generate 256
134
134
  end
135
135
 
136
+ def generate_cipher_key
137
+ rand(CIPHER_RAND_MAX).to_s(36).ljust CIPHER_BLOCK_SIZE
138
+ end
139
+
136
140
  # private
137
141
 
138
142
  def encode64 s
@@ -4,6 +4,10 @@ gem 'erubis'
4
4
  gem 'nyara', '<%= Nyara::VERSION %>', require: 'nyara/nyara'
5
5
  gem 'mongoid', '3.1.4'
6
6
 
7
+ group :development do
8
+ gem 'linner', github: "SaitoWu/linner"
9
+ end
10
+
7
11
  group :deploy do
8
12
  gem 'rake'
9
13
  end
@@ -0,0 +1,28 @@
1
+ paths:
2
+ app: "app/assets"
3
+ public: "public"
4
+ groups:
5
+ scripts:
6
+ paths:
7
+ - app/assets/scripts
8
+ concat:
9
+ "/assets/app.js": "app/assets/**/*.{js,coffee}"
10
+ order:
11
+ - "..."
12
+ - app/assets/scripts/app.coffee
13
+ styles:
14
+ paths:
15
+ - app/assets/styles
16
+ concat:
17
+ "/assets/app.css": "app/assets/**/[a-z]*.{css,scss,sass}"
18
+ files:
19
+ paths:
20
+ - app/assets/files
21
+ copy:
22
+ "/": "app/assets/**/*.{ico,txt}"
23
+ modules:
24
+ wrapper: "cmd"
25
+ ignored: "{vendor/**/*,app/assets/scripts/app.{js,coffee}}"
26
+ definition: "/assets/app.js"
27
+ revision: true
28
+ notification: true
@@ -1,6 +1,20 @@
1
- desc "display all routes"
1
+ require "rake"
2
+
3
+ desc "print all routes"
2
4
  task :routes do
3
- require_relative 'config/application'
5
+ require_relative "config/application"
4
6
  Nyara.setup
5
7
  Nyara::Route.print_routes
6
8
  end
9
+
10
+ namespace :assets do
11
+ desc "compile assets into public"
12
+ task :build do
13
+ sh 'bundle exec linner build'
14
+ end
15
+
16
+ desc "clean assets in public"
17
+ task :clean do
18
+ sh 'bundle exec linner clean'
19
+ end
20
+ end