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

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.
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