aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/vendor/rack-1.0/rack/reloader.rb
blob: b17d8c09262b6be6c28264cd72989d6c248e5693 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
require 'thread'

module Rack
  # Rack::Reloader checks on every request, but at most every +secs+
  # seconds, if a file loaded changed, and reloads it, logging to
  # rack.errors.
  #
  # It is recommended you use ShowExceptions to catch SyntaxErrors etc.

  class Reloader
    def initialize(app, secs=10)
      @app = app
      @secs = secs              # reload every @secs seconds max
      @last = Time.now
    end

    def call(env)
      if Time.now > @last + @secs
        Thread.exclusive {
          reload!(env['rack.errors'])
          @last = Time.now
        }
      end

      @app.call(env)
    end

    def reload!(stderr=$stderr)
      need_reload = $LOADED_FEATURES.find_all { |loaded|
        begin
          if loaded =~ /\A[.\/]/  # absolute filename or 1.9
            abs = loaded
          else
            abs = $LOAD_PATH.map { |path| ::File.join(path, loaded) }.
                             find { |file| ::File.exist? file }
          end

          if abs
            ::File.mtime(abs) > @last - @secs  rescue false
          else
            false
          end
        end
      }

      need_reload.each { |l|
        $LOADED_FEATURES.delete l
      }

      need_reload.each { |to_load|
        begin
          if require to_load
            stderr.puts "#{self.class}: reloaded `#{to_load}'"
          end
        rescue LoadError, SyntaxError => e
          raise e                 # Possibly ShowExceptions
        end
      }

      stderr.flush
      need_reload
    end
  end
end