autoreload 0.0.1 → 0.2.0

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/HISTORY ADDED
@@ -0,0 +1,14 @@
1
+ = RELEASE HISTORY
2
+
3
+ == 0.2.0 2010-05-10
4
+
5
+ * Completely reworked API.
6
+
7
+ == 0.1.0 2010-05-01
8
+
9
+ * Same as original, but now a RubyWorks project.
10
+
11
+ == 0.0.1 2007-07-01
12
+
13
+ * Initial release
14
+
File without changes
data/PROFILE ADDED
@@ -0,0 +1,20 @@
1
+ ---
2
+ title : Autoreload
3
+ summary: Automatically reload library files
4
+ license: MIT
5
+ contact: rubyworks-mailinglist@googlegroups.com
6
+ suite : rubyworks
7
+ created: 2007-07-01
8
+
9
+ authors:
10
+ - Kouichirou Eto
11
+ - Thomas Sawyer
12
+
13
+ description:
14
+ Autoreload automatically reloads library files when they have been
15
+ updated. It is especailly useful when testing stateless services
16
+ such as web applications.
17
+
18
+ resources:
19
+ homepage : http://rubyworks.github.com/autoreload
20
+ repository: http://github.com/rubyworks/autoreload
@@ -0,0 +1,42 @@
1
+ = Autoreload
2
+
3
+ * home: http://rubyworks.github.com/autoreload
4
+ * work: http://github.com/rubyworks/autoreload
5
+
6
+
7
+ == DESCRIPTION
8
+
9
+ Autoreload automatically reloads library files when they have been
10
+ updated. It is especailly useful when testing stateless services
11
+ such as web applications.
12
+
13
+
14
+ == HOW TO USE
15
+
16
+ Say we have a library <tt>foo.rb</tt> in our load path:
17
+
18
+ def foo
19
+ 1
20
+ end
21
+
22
+ We can then run the following script, <tt>example.rb</tt>:
23
+
24
+ require 'autoreload'
25
+ require 'foo'
26
+
27
+ autoreload('foo.rb', :interval=>2, :verbose=>true)
28
+
29
+ loop {
30
+ puts foo
31
+ sleep 2
32
+ }
33
+
34
+ With that running we can change <tt>foo.rb</tt> and the change will take
35
+ effect in <tt>example.rb</tt> within two seconds of being made.
36
+
37
+
38
+ == COPYRIGHT
39
+
40
+ Copyright (c) 2007 Kouichirou Eto
41
+
42
+ Copyright (c) 2010 Thomas Sawyer
data/VERSION ADDED
@@ -0,0 +1,5 @@
1
+ name : autoreload
2
+ major: 0
3
+ minor: 2
4
+ patch: 0
5
+ date : 2010-05-10
@@ -1,100 +1,9 @@
1
- # Copyright (C) 2003-2007 Kouichirou Eto, All rights reserved.
2
- # License: Ruby License
3
-
4
- require 'thread'
5
-
6
- module AutoReload #:nodoc:
7
- module VERSION #:nodoc:
8
- MAJOR = 0
9
- MINOR = 0
10
- TINY = 1
11
- STRING = [MAJOR, MINOR, TINY].join('.')
12
- end
13
-
14
- class Reloader
15
- def self.start(*a)
16
- self.new(*a).start
17
- end
18
-
19
- DEFAULT_INTERVAL = 1
20
-
21
- def initialize(interval = DEFAULT_INTERVAL,
22
- verbose = false, name = nil) #:nodoc:
23
- @interval = interval
24
- @verbose = verbose
25
- @name = name
26
- @status = {}
27
- @thread = nil
28
- end
29
-
30
- def start #:nodoc:
31
- @thread = Thread.new {
32
- loop {
33
- begin
34
- update
35
- rescue Exception
36
- warn 'update failed: ' + $!
37
- end
38
- sleep @interval
39
- }
40
- }
41
- @thread.abort_on_exception = true
42
- end
43
-
44
- private
45
-
46
- def warn(msg, out = $stderr)
47
- msg = "#{@name}: #{msg}" if @name
48
- out << msg + "\n"
49
- # $stderr.puts()
50
- end
51
-
52
- def update
53
- libs = [$0] + $"
54
- libs.each {|lib|
55
- check_lib(lib)
56
- }
57
- end
58
-
59
- def check_lib(lib)
60
- if @status[lib]
61
- file, mtime = @status[lib]
62
- return if ! FileTest.exist?(file) # file is disappered.
63
- curtime = File.mtime(file).to_i
64
- if mtime < curtime
65
- if @verbose
66
- warn "reload: '#{file}'"
67
- end
68
- load file # Load it.
69
- @status[lib] = [file, curtime]
70
- end
71
- return
72
- end
73
-
74
- check_path = [''] + $LOAD_PATH
75
- #check_path = ['']
76
- check_path.each {|path|
77
- file = File.join(path, lib)
78
- file = lib if path.empty? # Check if the lib is a filename.
79
- if FileTest.exist?(file)
80
- @status[lib] = [file, File.mtime(file).to_i]
81
- return
82
- end
83
- }
84
-
85
- #raise "The library '#{lib}' is not found."
86
- # $stdout.puts(message("The library '#{lib}' is not found.")) if @verbose
87
- end
88
-
89
- def get_status(file)
90
- if FileTest.exist?(file)
91
- return [file, File.mtime(file).to_i]
92
- end
93
- return nil
94
- end
95
- end
96
- end
97
-
98
- def autoreload(*a)
99
- AutoReload::Reloader.start(*a)
1
+ require 'autoreload/reloader'
2
+
3
+ module AutoReload
4
+ # TODO: version constant
5
+ end
6
+
7
+ def autoreload(*files)
8
+ AutoReload::Reloader.start(*files)
100
9
  end
@@ -0,0 +1,90 @@
1
+ module AutoReload
2
+
3
+ # = Library Lookup
4
+ #
5
+ # This library is a slightly modified copy of the +plugin+ library.
6
+ #
7
+ module Lookup
8
+
9
+ extend self
10
+
11
+ # Find plugins, searching through standard $LOAD_PATH,
12
+ # Roll Libraries and RubyGems.
13
+ #
14
+ # Provide a +match+ file glob to find plugins.
15
+ #
16
+ # Lookup.find('syckle/*')
17
+ #
18
+ def find(match, options={})
19
+ plugins = []
20
+ plugins.concat find_roll(match, options)
21
+ plugins.concat find_loadpath(match, options)
22
+ plugins.concat find_gems(match, options)
23
+ plugins.uniq
24
+ end
25
+
26
+ # Shortcut for #find.
27
+ #
28
+ # Lookup['syckle/*']
29
+ #
30
+ alias_method :[], :find
31
+
32
+ # Search roll for current or latest libraries.
33
+ def find_roll(match, options={})
34
+ plugins = []
35
+ #directory = options[:directory] || DIRECTORY
36
+ if defined?(::Roll)
37
+ ::Roll::Library.ledger.each do |name, lib|
38
+ lib = lib.sort.first if Array===lib
39
+ lib.loadpath.each do |path|
40
+ #find = File.join(lib.location, path, directory, match)
41
+ find = File.join(lib.location, path, match)
42
+ list = Dir.glob(find)
43
+ list = list.map{ |d| d.chomp('/') }
44
+ plugins.concat(list)
45
+ end
46
+ end
47
+ end
48
+ plugins
49
+ end
50
+
51
+ # Search standard $LOAD_PATH.
52
+ #
53
+ # Activated gem versions are in here too.
54
+
55
+ def find_loadpath(match, options={})
56
+ plugins = []
57
+ #directory = options[:directory] || DIRECTORY
58
+ $LOAD_PATH.uniq.each do |path|
59
+ path = File.expand_path(path)
60
+ #list = Dir.glob(File.join(path, directory, match))
61
+ list = Dir.glob(File.join(path, match))
62
+ list = list.map{ |d| d.chomp('/') }
63
+ plugins.concat(list)
64
+ end
65
+ plugins
66
+ end
67
+
68
+ # Search latest gem versions.
69
+ #
70
+ # TODO: Is there anyway to skip active gems?
71
+
72
+ def find_gems(match, options={})
73
+ plugins = []
74
+ #directory = options[:directory] || DIRECTORY
75
+ if defined?(::Gem)
76
+ ::Gem.latest_load_paths do |path|
77
+ #list = Dir.glob(File.join(path, directory, match))
78
+ list = Dir.glob(File.join(path, match))
79
+ list = list.map{ |d| d.chomp('/') }
80
+ plugins.concat(list)
81
+ end
82
+ end
83
+ plugins
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ # Copyright (C) 2010 Thomas Sawyer
@@ -0,0 +1,140 @@
1
+ require 'thread'
2
+ require 'autoreload/lookup'
3
+
4
+ module AutoReload
5
+
6
+ # Reload class does all the heavy lifting
7
+ # for AutoReload library.
8
+ #
9
+ class Reloader
10
+
11
+ # Shortcut for Reloader.new(*args).start.
12
+ def self.start(*args)
13
+ self.new(*args).start
14
+ end
15
+
16
+ # Default interval is one second.
17
+ DEFAULT_INTERVAL = 1
18
+
19
+ # New Reloader.
20
+ #
21
+ # === Options
22
+ #
23
+ # :interval - seconds betwee updates
24
+ # :verbose - true provides reload warning
25
+ # :reprime - include $0 in reload list
26
+ #
27
+ def initialize(*files)
28
+ options = Hash===files.last ? files.pop : {}
29
+
30
+ @files = files.map{ |file| file.to_s } #Dir.glob(file) }.flatten.compact
31
+
32
+ @interval = options[:interval] || DEFAULT_INTERVAL
33
+ @verbose = options[:verbose]
34
+ @reprime = options[:reprime]
35
+
36
+ @status = {}
37
+ end
38
+
39
+ # Start the reload thread.
40
+ def start
41
+ update # primate the path loads
42
+ @thread = Thread.new do
43
+ loop do
44
+ begin
45
+ update
46
+ rescue Exception
47
+ warn 'update failed: ' + $!
48
+ end
49
+ sleep @interval
50
+ end
51
+ end
52
+ @thread.abort_on_exception = true
53
+ end
54
+
55
+ # Kills the autoreload thread.
56
+ def stop
57
+ @thread.kill if @thread
58
+ end
59
+
60
+ #
61
+ attr :thread
62
+
63
+ # List of files provided to autoreload.
64
+ attr :files
65
+
66
+ # Status hash, used to track reloads.
67
+ attr :status
68
+
69
+ # The periodic interval of reload.
70
+ attr :interval
71
+
72
+ # Provide warning on reload.
73
+ def verbose?
74
+ @verbose || $VERBOSE
75
+ end
76
+
77
+ # Is $0 in the reload list?
78
+ def reprime?
79
+ @reprime
80
+ end
81
+
82
+ private
83
+
84
+ # List of library files to autoreload.
85
+ #--
86
+ # ISSUE: Why include $0 ?
87
+ #--
88
+ def libraries
89
+ if @files.empty?
90
+ @reprime ? [$0] + $" : $"
91
+ else
92
+ @files
93
+ end
94
+ end
95
+
96
+ # Iterate through all selection library files and reload if needed.
97
+ def update
98
+ libraries.each{ |lib| check(lib) }
99
+ end
100
+
101
+ # Check status and reload if out-of-date.
102
+ def check(lib)
103
+ if @status.key?(lib)
104
+ file, mtime = @status[lib]
105
+
106
+ return unless file # file never was
107
+ return unless FileTest.exist?(file) # file has disappered
108
+
109
+ curtime = File.mtime(file).to_i
110
+
111
+ if mtime < curtime
112
+ warn "reload: '#{file}'" if verbose?
113
+ load file
114
+ @status[lib] = [file, curtime]
115
+ end
116
+ else
117
+ @status[lib] = get_status(lib)
118
+ end
119
+ end
120
+
121
+ # Get library file status.
122
+ def get_status(lib)
123
+ file = Lookup.find(lib).first
124
+ if file #FileTest.exist?(file)
125
+ [file, File.mtime(file).to_i]
126
+ else
127
+ warn "reload fail: library '#{lib}' not found" if verbose?
128
+ #raise "The library '#{lib}' is not found."
129
+ #$stdout.puts(message("The library '#{lib}' is not found.")) if @verbose
130
+ [nil, nil]
131
+ end
132
+ end
133
+
134
+ end
135
+
136
+ end
137
+
138
+ # Copyright (C) 2003,2007 Kouichirou Eto
139
+ # Copyright (C) 2010 Thomas Sawyer
140
+
@@ -17,43 +17,43 @@ module AutoReload
17
17
  end
18
18
  end
19
19
 
20
- class TestAutoReload < Test::Unit::TestCase
21
- def test_autoreload
22
- #autoreload(1, true, 'test_autoreload')
23
- autoreload(1)
20
+ class TestAutoReload < Test::Unit::TestCase
24
21
 
22
+ def test_autoreload
25
23
  # create a library
26
24
  dir = Pathname.new(__FILE__).dirname
27
25
  library = dir + 'tmp_library.rb'
28
26
  library.write 'def foo; 1; end'
27
+
28
+ autoreload(library, :interval => 1) #, :verbose=>true)
29
29
 
30
30
  # require it
31
- require library
32
- assert_equal 1, foo
31
+ require library
32
+
33
+ assert_equal(1, foo)
33
34
 
34
- sleep 2 # wait is necessary.
35
- # If not, the time stamp will be same with the next file.
35
+ sleep 2 # wait is needed for time stamp to not be same with the next file.
36
36
 
37
37
  # recreate the file
38
38
  library.write 'def foo; 2; end'
39
39
 
40
- sleep 2 # wait again. wait for the autoreload will be started.
40
+ sleep 2 # wait again for the autoreload loop to repeat.
41
41
 
42
42
  # check the number again.
43
- assert_equal 2, foo
43
+ assert_equal(2, foo)
44
44
 
45
- # clean it
45
+ # clean up
46
46
  library.unlink
47
- assert_equal false, library.exist?
47
+ assert_equal(false, library.exist?)
48
48
  end
49
49
 
50
- # ruby -w -Ilib test/test_autoreload.rb -n test_all
51
- def test_all
52
- rel = AutoReload::Reloader.new
53
-
54
- # test_warn
55
- str = ''
56
- rel.warn("a", str)
57
- assert_equal "a\n", str
58
- end
50
+ ## ruby -w -Ilib test/test_autoreload.rb -n test_all
51
+ #def test_all
52
+ # rel = AutoReload::Reloader.new
53
+ #
54
+ # # test_warn
55
+ # str = ''
56
+ # rel.warn("a", str)
57
+ # assert_equal "a\n", str
58
+ #end
59
59
  end