spring 2.0.0 → 3.1.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.
@@ -32,7 +32,7 @@ module Spring
32
32
  # then we need to be under bundler.
33
33
  require "bundler/setup"
34
34
 
35
- # Auto-require any spring extensions which are in the Gemfile
35
+ # Auto-require any Spring extensions which are in the Gemfile
36
36
  Gem::Specification.map(&:name).grep(/^spring-/).each do |command|
37
37
  begin
38
38
  require command
@@ -5,7 +5,22 @@ module Spring
5
5
  attr_accessor :application_root, :quiet
6
6
 
7
7
  def gemfile
8
- ENV['BUNDLE_GEMFILE'] || "Gemfile"
8
+ require "bundler"
9
+
10
+ if /\s1.9.[0-9]/ === Bundler.ruby_scope.gsub(/[\/\s]+/,'')
11
+ Pathname.new(ENV["BUNDLE_GEMFILE"] || "Gemfile").expand_path
12
+ else
13
+ Bundler.default_gemfile
14
+ end
15
+ end
16
+
17
+ def gemfile_lock
18
+ case gemfile.to_s
19
+ when /\bgems\.rb\z/
20
+ gemfile.sub_ext('.locked')
21
+ else
22
+ gemfile.sub_ext('.lock')
23
+ end
9
24
  end
10
25
 
11
26
  def after_fork_callbacks
data/lib/spring/env.rb CHANGED
@@ -1,10 +1,7 @@
1
1
  require "pathname"
2
- require "fileutils"
3
2
  require "digest/md5"
4
- require "tmpdir"
5
3
 
6
4
  require "spring/version"
7
- require "spring/sid"
8
5
  require "spring/configuration"
9
6
 
10
7
  module Spring
@@ -33,10 +30,12 @@ module Spring
33
30
  end
34
31
 
35
32
  def tmp_path
33
+ require "tmpdir"
36
34
  path = Pathname.new(
37
35
  ENV["SPRING_TMP_PATH"] ||
38
36
  File.join(ENV['XDG_RUNTIME_DIR'] || Dir.tmpdir, "spring-#{Process.uid}")
39
37
  )
38
+ require "fileutils"
40
39
  FileUtils.mkdir_p(path) unless path.exist?
41
40
  path
42
41
  end
data/lib/spring/errors.rb CHANGED
@@ -24,7 +24,7 @@ module Spring
24
24
 
25
25
  def message
26
26
  "Spring was unable to find your config/application.rb file. " \
27
- "Your project root was detected at #{project_root}, so spring " \
27
+ "Your project root was detected at #{project_root}, so Spring " \
28
28
  "looked for #{project_root}/config/application.rb but it doesn't exist. You can " \
29
29
  "configure the root of your application by setting Spring.application_root in " \
30
30
  "config/spring.rb."
data/lib/spring/json.rb CHANGED
@@ -46,11 +46,9 @@ end
46
46
 
47
47
  # See https://github.com/kr/okjson for updates.
48
48
 
49
- require 'stringio'
50
-
51
49
  # Some parts adapted from
52
- # http://golang.org/src/pkg/json/decode.go and
53
- # http://golang.org/src/pkg/utf8/utf8.go
50
+ # https://golang.org/src/pkg/json/decode.go and
51
+ # https://golang.org/src/pkg/utf8/utf8.go
54
52
  module Spring
55
53
  module OkJson
56
54
  Upstream = '43'
@@ -468,19 +466,18 @@ private
468
466
 
469
467
 
470
468
  def strenc(s)
471
- t = StringIO.new
472
- t.putc(?")
469
+ t = '"'.b
473
470
  r = 0
474
471
 
475
472
  while r < s.length
476
473
  case s[r]
477
- when ?" then t.print('\\"')
478
- when ?\\ then t.print('\\\\')
479
- when ?\b then t.print('\\b')
480
- when ?\f then t.print('\\f')
481
- when ?\n then t.print('\\n')
482
- when ?\r then t.print('\\r')
483
- when ?\t then t.print('\\t')
474
+ when ?" then t << '\\"'
475
+ when ?\\ then t << '\\\\'
476
+ when ?\b then t << '\\b'
477
+ when ?\f then t << '\\f'
478
+ when ?\n then t << '\\n'
479
+ when ?\r then t << '\\r'
480
+ when ?\t then t << '\\t'
484
481
  else
485
482
  c = s[r]
486
483
  # In ruby >= 1.9, s[r] is a codepoint, not a byte.
@@ -490,14 +487,14 @@ private
490
487
  if c.ord < Spc.ord
491
488
  c = "\\u%04x" % [c.ord]
492
489
  end
493
- t.write(c)
490
+ t << c
494
491
  rescue
495
- t.write(Ustrerr)
492
+ t << Ustrerr
496
493
  end
497
494
  elsif c < Spc
498
- t.write("\\u%04x" % c)
495
+ t << "\\u%04x" % c
499
496
  elsif Spc <= c && c <= ?~
500
- t.putc(c)
497
+ t << c
501
498
  else
502
499
  n = ucharcopy(t, s, r) # ensure valid UTF-8 output
503
500
  r += n - 1 # r is incremented below
@@ -505,8 +502,8 @@ private
505
502
  end
506
503
  r += 1
507
504
  end
508
- t.putc(?")
509
- t.string
505
+ t << '"'
506
+ t
510
507
  end
511
508
 
512
509
 
@@ -531,7 +528,7 @@ private
531
528
 
532
529
  # 1-byte, 7-bit sequence?
533
530
  if c0 < Utagx
534
- t.putc(c0)
531
+ t << c0
535
532
  return 1
536
533
  end
537
534
 
@@ -544,8 +541,8 @@ private
544
541
  # 2-byte, 11-bit sequence?
545
542
  if c0 < Utag3
546
543
  raise Utf8Error if ((c0&Umask2)<<6 | (c1&Umaskx)) <= Uchar1max
547
- t.putc(c0)
548
- t.putc(c1)
544
+ t << c0
545
+ t << c1
549
546
  return 2
550
547
  end
551
548
 
@@ -559,9 +556,9 @@ private
559
556
  if c0 < Utag4
560
557
  u = (c0&Umask3)<<12 | (c1&Umaskx)<<6 | (c2&Umaskx)
561
558
  raise Utf8Error if u <= Uchar2max
562
- t.putc(c0)
563
- t.putc(c1)
564
- t.putc(c2)
559
+ t << c0
560
+ t << c1
561
+ t << c2
565
562
  return 3
566
563
  end
567
564
 
@@ -574,16 +571,16 @@ private
574
571
  if c0 < Utag5
575
572
  u = (c0&Umask4)<<18 | (c1&Umaskx)<<12 | (c2&Umaskx)<<6 | (c3&Umaskx)
576
573
  raise Utf8Error if u <= Uchar3max
577
- t.putc(c0)
578
- t.putc(c1)
579
- t.putc(c2)
580
- t.putc(c3)
574
+ t << c0
575
+ t << c1
576
+ t << c2
577
+ t << c3
581
578
  return 4
582
579
  end
583
580
 
584
581
  raise Utf8Error
585
582
  rescue Utf8Error
586
- t.write(Ustrerr)
583
+ t << Ustrerr
587
584
  return 1
588
585
  end
589
586
 
@@ -1,6 +1,6 @@
1
1
  module Spring
2
2
  # Yes, I know this reimplements a bunch of stuff in Active Support, but
3
- # I don't want the spring client to depend on AS, in order to keep its
3
+ # I don't want the Spring client to depend on AS, in order to keep its
4
4
  # load time down.
5
5
  class ProcessTitleUpdater
6
6
  SECOND = 1
data/lib/spring/server.rb CHANGED
@@ -81,7 +81,8 @@ module Spring
81
81
  # This will cause it to be automatically killed once the session
82
82
  # ends (i.e. when the user closes their terminal).
83
83
  def set_pgid
84
- Process.setpgid(0, SID.pgid)
84
+ pgid = Process.getpgid(Process.getsid)
85
+ Process.setpgid(0, pgid)
85
86
  end
86
87
 
87
88
  # Ignore SIGINT and SIGQUIT otherwise the user typing ^C or ^\ on the command line
@@ -1,3 +1,3 @@
1
1
  module Spring
2
- VERSION = "2.0.0"
2
+ VERSION = "3.1.1"
3
3
  end
@@ -23,9 +23,21 @@ module Spring
23
23
  @directories = Set.new
24
24
  @stale = false
25
25
  @listeners = []
26
+
27
+ @on_debug = nil
28
+ end
29
+
30
+ def on_debug(&block)
31
+ @on_debug = block
32
+ end
33
+
34
+ def debug
35
+ @on_debug.call(yield) if @on_debug
26
36
  end
27
37
 
28
38
  def add(*items)
39
+ debug { "watcher: add: #{items.inspect}" }
40
+
29
41
  items = items.flatten.map do |item|
30
42
  item = Pathname.new(item)
31
43
 
@@ -36,14 +48,30 @@ module Spring
36
48
  end
37
49
  end
38
50
 
39
- items = items.select(&:exist?)
51
+ items = items.select do |item|
52
+ if item.symlink?
53
+ item.readlink.exist?.tap do |exists|
54
+ if !exists
55
+ debug { "add: ignoring dangling symlink: #{item.inspect} -> #{item.readlink.inspect}" }
56
+ end
57
+ end
58
+ else
59
+ item.exist?
60
+ end
61
+ end
40
62
 
41
63
  synchronize {
42
64
  items.each do |item|
43
65
  if item.directory?
44
66
  directories << item.realpath.to_s
45
67
  else
46
- files << item.realpath.to_s
68
+ begin
69
+ files << item.realpath.to_s
70
+ rescue Errno::ENOENT
71
+ # Race condition. Ignore symlinks whose target was removed
72
+ # since the check above, or are deeply chained.
73
+ debug { "add: ignoring now-dangling symlink: #{item.inspect} -> #{item.readlink.inspect}" }
74
+ end
47
75
  end
48
76
  end
49
77
 
@@ -56,16 +84,19 @@ module Spring
56
84
  end
57
85
 
58
86
  def on_stale(&block)
87
+ debug { "added listener: #{block.inspect}" }
59
88
  @listeners << block
60
89
  end
61
90
 
62
91
  def mark_stale
63
92
  return if stale?
64
93
  @stale = true
94
+ debug { "marked stale, calling listeners: listeners=#{@listeners.inspect}" }
65
95
  @listeners.each(&:call)
66
96
  end
67
97
 
68
98
  def restart
99
+ debug { "restarting" }
69
100
  stop
70
101
  start
71
102
  end
@@ -12,7 +12,13 @@ module Spring
12
12
  end
13
13
 
14
14
  def check_stale
15
- synchronize { mark_stale if mtime < compute_mtime }
15
+ synchronize do
16
+ computed = compute_mtime
17
+ if mtime < computed
18
+ debug { "check_stale: mtime=#{mtime.inspect} < computed=#{computed.inspect}" }
19
+ mark_stale
20
+ end
21
+ end
16
22
  end
17
23
 
18
24
  def add(*)
@@ -21,36 +27,67 @@ module Spring
21
27
  end
22
28
 
23
29
  def start
30
+ debug { "start: poller=#{@poller.inspect}" }
24
31
  unless @poller
25
32
  @poller = Thread.new {
26
33
  Thread.current.abort_on_exception = true
27
34
 
28
- loop do
29
- Kernel.sleep latency
30
- check_stale
35
+ begin
36
+ until stale?
37
+ Kernel.sleep latency
38
+ check_stale
39
+ end
40
+ rescue Exception => e
41
+ debug do
42
+ "poller: aborted: #{e.class}: #{e}\n #{e.backtrace.join("\n ")}"
43
+ end
44
+ raise
45
+ ensure
46
+ @poller = nil
31
47
  end
32
48
  }
33
49
  end
34
50
  end
35
51
 
36
52
  def stop
53
+ debug { "stopping poller: #{@poller.inspect}" }
37
54
  if @poller
38
55
  @poller.kill
39
56
  @poller = nil
40
57
  end
41
58
  end
42
59
 
60
+ def running?
61
+ @poller && @poller.alive?
62
+ end
63
+
43
64
  def subjects_changed
44
- @mtime = compute_mtime
65
+ computed = compute_mtime
66
+ debug { "subjects_changed: mtime #{@mtime} -> #{computed}" }
67
+ @mtime = computed
45
68
  end
46
69
 
47
70
  private
48
71
 
49
72
  def compute_mtime
50
- expanded_files.map { |f| File.mtime(f).to_f }.max || 0
51
- rescue Errno::ENOENT
52
- # if a file does no longer exist, the watcher is always stale.
53
- Float::MAX
73
+ expanded_files.map do |f|
74
+ # Get the mtime of symlink targets. Ignore dangling symlinks.
75
+ if File.symlink?(f)
76
+ begin
77
+ File.mtime(f)
78
+ rescue Errno::ENOENT
79
+ 0
80
+ end
81
+ # If a file no longer exists, treat it as changed.
82
+ else
83
+ begin
84
+ File.mtime(f)
85
+ rescue Errno::ENOENT
86
+ debug { "compute_mtime: no longer exists: #{f}" }
87
+ Float::MAX
88
+ end
89
+ end.to_f
90
+ end.max || 0
54
91
  end
55
92
 
56
93
  def expanded_files
metadata CHANGED
@@ -1,31 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spring
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Leighton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-01 00:00:00.000000000 Z
11
+ date: 2021-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
20
- type: :runtime
19
+ version: '0'
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '4.2'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: bump
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: bump
42
+ name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -90,13 +90,6 @@ files:
90
90
  - lib/spring/json.rb
91
91
  - lib/spring/process_title_updater.rb
92
92
  - lib/spring/server.rb
93
- - lib/spring/sid.rb
94
- - lib/spring/test.rb
95
- - lib/spring/test/acceptance_test.rb
96
- - lib/spring/test/application.rb
97
- - lib/spring/test/application_generator.rb
98
- - lib/spring/test/rails_version.rb
99
- - lib/spring/test/watcher_test.rb
100
93
  - lib/spring/version.rb
101
94
  - lib/spring/watcher.rb
102
95
  - lib/spring/watcher/abstract.rb
@@ -113,15 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
106
  requirements:
114
107
  - - ">="
115
108
  - !ruby/object:Gem::Version
116
- version: '0'
109
+ version: 2.5.0
117
110
  required_rubygems_version: !ruby/object:Gem::Requirement
118
111
  requirements:
119
112
  - - ">="
120
113
  - !ruby/object:Gem::Version
121
114
  version: '0'
122
115
  requirements: []
123
- rubyforge_project:
124
- rubygems_version: 2.5.1
116
+ rubygems_version: 3.2.22
125
117
  signing_key:
126
118
  specification_version: 4
127
119
  summary: Rails application preloader
data/lib/spring/sid.rb DELETED
@@ -1,42 +0,0 @@
1
- begin
2
- # If rubygems is present, keep it out of the way when loading fiddle,
3
- # otherwise if fiddle is not installed then rubygems will load all
4
- # gemspecs in its (futile) search for fiddle, which is slow.
5
- if respond_to?(:gem_original_require, true)
6
- gem_original_require 'fiddle'
7
- else
8
- require 'fiddle'
9
- end
10
- rescue LoadError
11
- end
12
-
13
- module Spring
14
- module SID
15
- def self.fiddle_func
16
- @fiddle_func ||= Fiddle::Function.new(
17
- DL::Handle::DEFAULT['getsid'],
18
- [Fiddle::TYPE_INT],
19
- Fiddle::TYPE_INT
20
- )
21
- end
22
-
23
- def self.sid
24
- @sid ||= begin
25
- if Process.respond_to?(:getsid)
26
- # Ruby 2
27
- Process.getsid
28
- elsif defined?(Fiddle) and defined?(DL)
29
- # Ruby 1.9.3 compiled with libffi support
30
- fiddle_func.call(0)
31
- else
32
- # last resort: shell out
33
- `ps -p #{Process.pid} -o sess=`.to_i
34
- end
35
- end
36
- end
37
-
38
- def self.pgid
39
- Process.getpgid(sid)
40
- end
41
- end
42
- end