activesupport 5.0.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (268) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +343 -590
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -4
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +11 -5
  8. data/lib/active_support/backtrace_cleaner.rb +33 -5
  9. data/lib/active_support/benchmarkable.rb +5 -3
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +45 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +81 -79
  13. data/lib/active_support/cache/memory_store.rb +69 -41
  14. data/lib/active_support/cache/null_store.rb +11 -4
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +74 -37
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +332 -161
  19. data/lib/active_support/callbacks.rb +657 -586
  20. data/lib/active_support/concern.rb +79 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +59 -19
  23. data/lib/active_support/configurable.rb +15 -17
  24. data/lib/active_support/configuration_file.rb +46 -0
  25. data/lib/active_support/core_ext/array/access.rb +21 -7
  26. data/lib/active_support/core_ext/array/conversions.rb +20 -18
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +3 -1
  30. data/lib/active_support/core_ext/array/inquiry.rb +3 -1
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/array.rb +9 -7
  33. data/lib/active_support/core_ext/benchmark.rb +5 -3
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -26
  39. data/lib/active_support/core_ext/class.rb +4 -2
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +3 -1
  42. data/lib/active_support/core_ext/date/calculations.rb +16 -13
  43. data/lib/active_support/core_ext/date/conversions.rb +23 -21
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +7 -5
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +3 -1
  51. data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
  53. data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +165 -29
  58. data/lib/active_support/core_ext/file/atomic.rb +7 -5
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/conversions.rb +40 -39
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +4 -2
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
  65. data/lib/active_support/core_ext/hash/keys.rb +9 -36
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  68. data/lib/active_support/core_ext/hash.rb +10 -9
  69. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  70. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  71. data/lib/active_support/core_ext/integer/time.rb +11 -18
  72. data/lib/active_support/core_ext/integer.rb +5 -3
  73. data/lib/active_support/core_ext/kernel/concern.rb +3 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +5 -4
  77. data/lib/active_support/core_ext/load_error.rb +2 -23
  78. data/lib/active_support/core_ext/marshal.rb +6 -2
  79. data/lib/active_support/core_ext/module/aliasing.rb +5 -48
  80. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  81. data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
  84. data/lib/active_support/core_ext/module/concerning.rb +16 -11
  85. data/lib/active_support/core_ext/module/delegation.rb +159 -44
  86. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  87. data/lib/active_support/core_ext/module/introspection.rb +23 -26
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +13 -12
  91. data/lib/active_support/core_ext/name_error.rb +36 -2
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
  94. data/lib/active_support/core_ext/numeric/time.rb +18 -26
  95. data/lib/active_support/core_ext/numeric.rb +5 -4
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +14 -2
  98. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  99. data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
  100. data/lib/active_support/core_ext/object/duplicable.rb +13 -62
  101. data/lib/active_support/core_ext/object/inclusion.rb +3 -1
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +42 -15
  104. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  105. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  106. data/lib/active_support/core_ext/object/try.rb +20 -8
  107. data/lib/active_support/core_ext/object/with_options.rb +15 -2
  108. data/lib/active_support/core_ext/object.rb +14 -12
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  111. data/lib/active_support/core_ext/range/each.rb +5 -2
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +7 -4
  115. data/lib/active_support/core_ext/regexp.rb +10 -1
  116. data/lib/active_support/core_ext/securerandom.rb +28 -6
  117. data/lib/active_support/core_ext/string/access.rb +9 -18
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +47 -4
  122. data/lib/active_support/core_ext/string/indent.rb +6 -4
  123. data/lib/active_support/core_ext/string/inflections.rb +78 -29
  124. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  125. data/lib/active_support/core_ext/string/multibyte.rb +10 -5
  126. data/lib/active_support/core_ext/string/output_safety.rb +86 -31
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +5 -1
  129. data/lib/active_support/core_ext/string/zones.rb +4 -2
  130. data/lib/active_support/core_ext/string.rb +15 -13
  131. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  132. data/lib/active_support/core_ext/symbol.rb +3 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  134. data/lib/active_support/core_ext/time/calculations.rb +117 -45
  135. data/lib/active_support/core_ext/time/compatibility.rb +13 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +18 -12
  137. data/lib/active_support/core_ext/time/zones.rb +9 -7
  138. data/lib/active_support/core_ext/time.rb +7 -5
  139. data/lib/active_support/core_ext/uri.rb +12 -7
  140. data/lib/active_support/core_ext.rb +3 -2
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +208 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +7 -1
  145. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  146. data/lib/active_support/dependencies.rb +172 -98
  147. data/lib/active_support/deprecation/behaviors.rb +45 -13
  148. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  149. data/lib/active_support/deprecation/disallowed.rb +56 -0
  150. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  151. data/lib/active_support/deprecation/method_wrappers.rb +32 -17
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
  153. data/lib/active_support/deprecation/reporting.rb +61 -16
  154. data/lib/active_support/deprecation.rb +17 -9
  155. data/lib/active_support/descendants_tracker.rb +61 -9
  156. data/lib/active_support/digest.rb +20 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +67 -66
  158. data/lib/active_support/duration/iso8601_serializer.rb +25 -17
  159. data/lib/active_support/duration.rb +349 -46
  160. data/lib/active_support/encrypted_configuration.rb +45 -0
  161. data/lib/active_support/encrypted_file.rb +117 -0
  162. data/lib/active_support/environment_inquirer.rb +20 -0
  163. data/lib/active_support/evented_file_update_checker.rb +88 -112
  164. data/lib/active_support/execution_wrapper.rb +25 -13
  165. data/lib/active_support/executor.rb +3 -1
  166. data/lib/active_support/file_update_checker.rb +56 -51
  167. data/lib/active_support/fork_tracker.rb +62 -0
  168. data/lib/active_support/gem_version.rb +4 -2
  169. data/lib/active_support/gzip.rb +7 -5
  170. data/lib/active_support/hash_with_indifferent_access.rb +153 -49
  171. data/lib/active_support/i18n.rb +9 -6
  172. data/lib/active_support/i18n_railtie.rb +30 -20
  173. data/lib/active_support/inflections.rb +13 -11
  174. data/lib/active_support/inflector/inflections.rb +28 -15
  175. data/lib/active_support/inflector/methods.rb +120 -109
  176. data/lib/active_support/inflector/transliterate.rb +60 -25
  177. data/lib/active_support/inflector.rb +7 -5
  178. data/lib/active_support/json/decoding.rb +30 -29
  179. data/lib/active_support/json/encoding.rb +22 -11
  180. data/lib/active_support/json.rb +4 -2
  181. data/lib/active_support/key_generator.rb +6 -36
  182. data/lib/active_support/lazy_load_hooks.rb +53 -20
  183. data/lib/active_support/locale/en.rb +33 -0
  184. data/lib/active_support/locale/en.yml +7 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +11 -9
  186. data/lib/active_support/log_subscriber.rb +51 -18
  187. data/lib/active_support/logger.rb +9 -22
  188. data/lib/active_support/logger_silence.rb +14 -21
  189. data/lib/active_support/logger_thread_safe_level.rb +55 -8
  190. data/lib/active_support/message_encryptor.rb +170 -53
  191. data/lib/active_support/message_verifier.rb +91 -20
  192. data/lib/active_support/messages/metadata.rb +80 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  194. data/lib/active_support/messages/rotator.rb +57 -0
  195. data/lib/active_support/multibyte/chars.rb +24 -78
  196. data/lib/active_support/multibyte/unicode.rb +21 -352
  197. data/lib/active_support/multibyte.rb +4 -2
  198. data/lib/active_support/notifications/fanout.rb +121 -19
  199. data/lib/active_support/notifications/instrumenter.rb +78 -14
  200. data/lib/active_support/notifications.rb +80 -12
  201. data/lib/active_support/number_helper/number_converter.rb +17 -16
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
  206. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  207. data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -4
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
  209. data/lib/active_support/number_helper/rounding_helper.rb +50 -0
  210. data/lib/active_support/number_helper.rb +45 -16
  211. data/lib/active_support/option_merger.rb +25 -4
  212. data/lib/active_support/ordered_hash.rb +6 -4
  213. data/lib/active_support/ordered_options.rb +23 -9
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +7 -5
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +8 -9
  218. data/lib/active_support/railtie.rb +62 -11
  219. data/lib/active_support/reloader.rb +12 -11
  220. data/lib/active_support/rescuable.rb +20 -11
  221. data/lib/active_support/secure_compare_rotator.rb +51 -0
  222. data/lib/active_support/security_utils.rb +26 -15
  223. data/lib/active_support/string_inquirer.rb +12 -3
  224. data/lib/active_support/subscriber.rb +77 -23
  225. data/lib/active_support/tagged_logging.rb +52 -17
  226. data/lib/active_support/test_case.rb +106 -29
  227. data/lib/active_support/testing/assertions.rb +144 -8
  228. data/lib/active_support/testing/autorun.rb +5 -10
  229. data/lib/active_support/testing/constant_lookup.rb +2 -1
  230. data/lib/active_support/testing/declarative.rb +3 -1
  231. data/lib/active_support/testing/deprecation.rb +4 -2
  232. data/lib/active_support/testing/file_fixtures.rb +4 -0
  233. data/lib/active_support/testing/isolation.rb +19 -24
  234. data/lib/active_support/testing/method_call_assertions.rb +31 -2
  235. data/lib/active_support/testing/parallelization/server.rb +78 -0
  236. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  237. data/lib/active_support/testing/parallelization.rb +51 -0
  238. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  239. data/lib/active_support/testing/stream.rb +30 -29
  240. data/lib/active_support/testing/tagged_logging.rb +3 -1
  241. data/lib/active_support/testing/time_helpers.rb +125 -24
  242. data/lib/active_support/time.rb +14 -12
  243. data/lib/active_support/time_with_zone.rb +142 -55
  244. data/lib/active_support/values/time_zone.rb +160 -53
  245. data/lib/active_support/version.rb +3 -1
  246. data/lib/active_support/xml_mini/jdom.rb +115 -114
  247. data/lib/active_support/xml_mini/libxml.rb +15 -14
  248. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  249. data/lib/active_support/xml_mini/nokogiri.rb +13 -13
  250. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  251. data/lib/active_support/xml_mini/rexml.rb +18 -9
  252. data/lib/active_support/xml_mini.rb +44 -42
  253. data/lib/active_support.rb +19 -10
  254. metadata +79 -37
  255. data/lib/active_support/concurrency/latch.rb +0 -19
  256. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  257. data/lib/active_support/core_ext/hash/compact.rb +0 -20
  258. data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
  259. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  260. data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
  261. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
  262. data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
  263. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  264. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  265. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  266. data/lib/active_support/core_ext/struct.rb +0 -3
  267. data/lib/active_support/core_ext/time/marshal.rb +0 -3
  268. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,6 +1,10 @@
1
- require 'set'
2
- require 'pathname'
3
- require 'concurrent/atomic/atomic_boolean'
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "pathname"
5
+ require "concurrent/atomic/atomic_boolean"
6
+ require "listen"
7
+ require "active_support/fork_tracker"
4
8
 
5
9
  module ActiveSupport
6
10
  # Allows you to "listen" to changes in a file system.
@@ -17,7 +21,7 @@ module ActiveSupport
17
21
  #
18
22
  # Example:
19
23
  #
20
- # checker = EventedFileUpdateChecker.new(["/tmp/foo"], -> { puts "changed" })
24
+ # checker = ActiveSupport::EventedFileUpdateChecker.new(["/tmp/foo"]) { puts "changed" }
21
25
  # checker.updated?
22
26
  # # => false
23
27
  # checker.execute_if_updated
@@ -32,48 +36,26 @@ module ActiveSupport
32
36
  #
33
37
  class EventedFileUpdateChecker #:nodoc: all
34
38
  def initialize(files, dirs = {}, &block)
35
- @ph = PathHelper.new
36
- @files = files.map { |f| @ph.xpath(f) }.to_set
37
-
38
- @dirs = {}
39
- dirs.each do |dir, exts|
40
- @dirs[@ph.xpath(dir)] = Array(exts).map { |ext| @ph.normalize_extension(ext) }
39
+ unless block
40
+ raise ArgumentError, "A block is required to initialize an EventedFileUpdateChecker"
41
41
  end
42
42
 
43
- @block = block
44
- @updated = Concurrent::AtomicBoolean.new(false)
45
- @lcsp = @ph.longest_common_subpath(@dirs.keys)
46
- @pid = Process.pid
47
- @boot_mutex = Mutex.new
48
-
49
- if (@dtw = directories_to_watch).any?
50
- # Loading listen triggers warnings. These are originated by a legit
51
- # usage of attr_* macros for private attributes, but adds a lot of noise
52
- # to our test suite. Thus, we lazy load it and disable warnings locally.
53
- silence_warnings do
54
- begin
55
- require 'listen'
56
- rescue LoadError => e
57
- raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
58
- end
59
- end
60
- end
61
- boot!
43
+ @block = block
44
+ @core = Core.new(files, dirs)
45
+ ObjectSpace.define_finalizer(self, @core.finalizer)
62
46
  end
63
47
 
64
48
  def updated?
65
- @boot_mutex.synchronize do
66
- if @pid != Process.pid
67
- boot!
68
- @pid = Process.pid
69
- @updated.make_true
70
- end
49
+ if @core.restart?
50
+ @core.thread_safely(&:restart)
51
+ @core.updated.make_true
71
52
  end
72
- @updated.true?
53
+
54
+ @core.updated.true?
73
55
  end
74
56
 
75
57
  def execute
76
- @updated.make_false
58
+ @core.updated.make_false
77
59
  @block.call
78
60
  end
79
61
 
@@ -85,110 +67,104 @@ module ActiveSupport
85
67
  end
86
68
  end
87
69
 
88
- private
89
- def boot!
90
- Listen.to(*@dtw, &method(:changed)).start
91
- end
70
+ class Core
71
+ attr_reader :updated
92
72
 
93
- def changed(modified, added, removed)
94
- unless updated?
95
- @updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
73
+ def initialize(files, dirs)
74
+ @files = files.map { |file| Pathname(file).expand_path }.to_set
75
+
76
+ @dirs = dirs.each_with_object({}) do |(dir, exts), hash|
77
+ hash[Pathname(dir).expand_path] = Array(exts).map { |ext| ext.to_s.sub(/\A\.?/, ".") }.to_set
96
78
  end
97
- end
98
79
 
99
- def watching?(file)
100
- file = @ph.xpath(file)
80
+ @common_path = common_path(@dirs.keys)
101
81
 
102
- if @files.member?(file)
103
- true
104
- elsif file.directory?
105
- false
106
- else
107
- ext = @ph.normalize_extension(file.extname)
82
+ @dtw = directories_to_watch
83
+ @missing = []
108
84
 
109
- file.dirname.ascend do |dir|
110
- if @dirs.fetch(dir, []).include?(ext)
111
- break true
112
- elsif dir == @lcsp || dir.root?
113
- break false
114
- end
115
- end
85
+ @updated = Concurrent::AtomicBoolean.new(false)
86
+ @mutex = Mutex.new
87
+
88
+ start
89
+ @after_fork = ActiveSupport::ForkTracker.after_fork { start }
90
+ end
91
+
92
+ def finalizer
93
+ proc do
94
+ stop
95
+ ActiveSupport::ForkTracker.unregister(@after_fork)
116
96
  end
117
97
  end
118
98
 
119
- def directories_to_watch
120
- dtw = (@files + @dirs.keys).map { |f| @ph.existing_parent(f) }
121
- dtw.compact!
122
- dtw.uniq!
99
+ def thread_safely
100
+ @mutex.synchronize do
101
+ yield self
102
+ end
103
+ end
123
104
 
124
- @ph.filter_out_descendants(dtw)
105
+ def start
106
+ normalize_dirs!
107
+ @dtw, @missing = [*@dtw, *@missing].partition(&:exist?)
108
+ @listener = @dtw.any? ? Listen.to(*@dtw, &method(:changed)) : nil
109
+ @listener&.start
125
110
  end
126
111
 
127
- class PathHelper
128
- def xpath(path)
129
- Pathname.new(path).expand_path
112
+ def stop
113
+ @listener&.stop
130
114
  end
131
115
 
132
- def normalize_extension(ext)
133
- ext.to_s.sub(/\A\./, '')
116
+ def restart
117
+ stop
118
+ start
134
119
  end
135
120
 
136
- # Given a collection of Pathname objects returns the longest subpath
137
- # common to all of them, or +nil+ if there is none.
138
- def longest_common_subpath(paths)
139
- return if paths.empty?
140
-
141
- lcsp = Pathname.new(paths[0])
142
-
143
- paths[1..-1].each do |path|
144
- until ascendant_of?(lcsp, path)
145
- if lcsp.root?
146
- # If we get here a root directory is not an ascendant of path.
147
- # This may happen if there are paths in different drives on
148
- # Windows.
149
- return
150
- else
151
- lcsp = lcsp.parent
152
- end
153
- end
154
- end
121
+ def restart?
122
+ @missing.any?(&:exist?)
123
+ end
155
124
 
156
- lcsp
125
+ def normalize_dirs!
126
+ @dirs.transform_keys! do |dir|
127
+ dir.exist? ? dir.realpath : dir
128
+ end
157
129
  end
158
130
 
159
- # Returns the deepest existing ascendant, which could be the argument itself.
160
- def existing_parent(dir)
161
- dir.ascend do |ascendant|
162
- break ascendant if ascendant.directory?
131
+ def changed(modified, added, removed)
132
+ unless @updated.true?
133
+ @updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
163
134
  end
164
135
  end
165
136
 
166
- # Filters out directories which are descendants of others in the collection (stable).
167
- def filter_out_descendants(dirs)
168
- return dirs if dirs.length < 2
137
+ def watching?(file)
138
+ file = Pathname(file)
169
139
 
170
- dirs_sorted_by_nparts = dirs.sort_by { |dir| dir.each_filename.to_a.length }
171
- descendants = []
140
+ if @files.member?(file)
141
+ true
142
+ elsif file.directory?
143
+ false
144
+ else
145
+ ext = file.extname
172
146
 
173
- until dirs_sorted_by_nparts.empty?
174
- dir = dirs_sorted_by_nparts.shift
147
+ file.dirname.ascend do |dir|
148
+ matching = @dirs[dir]
175
149
 
176
- dirs_sorted_by_nparts.reject! do |possible_descendant|
177
- ascendant_of?(dir, possible_descendant) && descendants << possible_descendant
150
+ if matching && (matching.empty? || matching.include?(ext))
151
+ break true
152
+ elsif dir == @common_path || dir.root?
153
+ break false
154
+ end
178
155
  end
179
156
  end
180
-
181
- # Array#- preserves order.
182
- dirs - descendants
183
157
  end
184
158
 
185
- private
159
+ def directories_to_watch
160
+ dtw = @dirs.keys | @files.map(&:dirname)
161
+ accounted_for = dtw.to_set + Gem.path.map { |path| Pathname(path) }
162
+ dtw.reject { |dir| dir.ascend.drop(1).any? { |parent| accounted_for.include?(parent) } }
163
+ end
186
164
 
187
- def ascendant_of?(base, other)
188
- base != other && other.ascend do |ascendant|
189
- break true if base == ascendant
190
- end
191
- end
165
+ def common_path(paths)
166
+ paths.map { |path| path.ascend.to_a }.reduce(&:&)&.first
167
+ end
192
168
  end
193
169
  end
194
170
  end
@@ -1,4 +1,7 @@
1
- require 'active_support/callbacks'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/callbacks"
4
+ require "concurrent/hash"
2
5
 
3
6
  module ActiveSupport
4
7
  class ExecutionWrapper
@@ -19,6 +22,23 @@ module ActiveSupport
19
22
  set_callback(:complete, *args, &block)
20
23
  end
21
24
 
25
+ RunHook = Struct.new(:hook) do # :nodoc:
26
+ def before(target)
27
+ hook_state = target.send(:hook_state)
28
+ hook_state[hook] = hook.run
29
+ end
30
+ end
31
+
32
+ CompleteHook = Struct.new(:hook) do # :nodoc:
33
+ def before(target)
34
+ hook_state = target.send(:hook_state)
35
+ if hook_state.key?(hook)
36
+ hook.complete hook_state[hook]
37
+ end
38
+ end
39
+ alias after before
40
+ end
41
+
22
42
  # Register an object to be invoked during both the +run+ and
23
43
  # +complete+ steps.
24
44
  #
@@ -29,19 +49,11 @@ module ActiveSupport
29
49
  # invoked in that situation.)
30
50
  def self.register_hook(hook, outer: false)
31
51
  if outer
32
- run_args = [prepend: true]
33
- complete_args = [:after]
52
+ to_run RunHook.new(hook), prepend: true
53
+ to_complete :after, CompleteHook.new(hook)
34
54
  else
35
- run_args = complete_args = []
36
- end
37
-
38
- to_run(*run_args) do
39
- hook_state[hook] = hook.run
40
- end
41
- to_complete(*complete_args) do
42
- if hook_state.key?(hook)
43
- hook.complete hook_state[hook]
44
- end
55
+ to_run RunHook.new(hook)
56
+ to_complete CompleteHook.new(hook)
45
57
  end
46
58
  end
47
59
 
@@ -1,4 +1,6 @@
1
- require 'active_support/execution_wrapper'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/execution_wrapper"
2
4
 
3
5
  module ActiveSupport
4
6
  class Executor < ExecutionWrapper
@@ -1,4 +1,6 @@
1
- require 'active_support/core_ext/time/calculations'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/time/calculations"
2
4
 
3
5
  module ActiveSupport
4
6
  # FileUpdateChecker specifies the API used by Rails to watch files
@@ -38,6 +40,10 @@ module ActiveSupport
38
40
  # changes. The array of files and list of directories cannot be changed
39
41
  # after FileUpdateChecker has been initialized.
40
42
  def initialize(files, dirs = {}, &block)
43
+ unless block
44
+ raise ArgumentError, "A block is required to initialize a FileUpdateChecker"
45
+ end
46
+
41
47
  @files = files.freeze
42
48
  @glob = compile_glob(dirs)
43
49
  @block = block
@@ -92,66 +98,65 @@ module ActiveSupport
92
98
  end
93
99
 
94
100
  private
95
-
96
- def watched
97
- @watched || begin
98
- all = @files.select { |f| File.exist?(f) }
99
- all.concat(Dir[@glob]) if @glob
100
- all
101
+ def watched
102
+ @watched || begin
103
+ all = @files.select { |f| File.exist?(f) }
104
+ all.concat(Dir[@glob]) if @glob
105
+ all
106
+ end
101
107
  end
102
- end
103
108
 
104
- def updated_at(paths)
105
- @updated_at || max_mtime(paths) || Time.at(0)
106
- end
109
+ def updated_at(paths)
110
+ @updated_at || max_mtime(paths) || Time.at(0)
111
+ end
107
112
 
108
- # This method returns the maximum mtime of the files in +paths+, or +nil+
109
- # if the array is empty.
110
- #
111
- # Files with a mtime in the future are ignored. Such abnormal situation
112
- # can happen for example if the user changes the clock by hand. It is
113
- # healthy to consider this edge case because with mtimes in the future
114
- # reloading is not triggered.
115
- def max_mtime(paths)
116
- time_now = Time.now
117
- max_mtime = nil
118
-
119
- # Time comparisons are performed with #compare_without_coercion because
120
- # AS redefines these operators in a way that is much slower and does not
121
- # bring any benefit in this particular code.
113
+ # This method returns the maximum mtime of the files in +paths+, or +nil+
114
+ # if the array is empty.
122
115
  #
123
- # Read t1.compare_without_coercion(t2) < 0 as t1 < t2.
124
- paths.each do |path|
125
- mtime = File.mtime(path)
126
-
127
- next if time_now.compare_without_coercion(mtime) < 0
128
-
129
- if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
130
- max_mtime = mtime
116
+ # Files with a mtime in the future are ignored. Such abnormal situation
117
+ # can happen for example if the user changes the clock by hand. It is
118
+ # healthy to consider this edge case because with mtimes in the future
119
+ # reloading is not triggered.
120
+ def max_mtime(paths)
121
+ time_now = Time.now
122
+ max_mtime = nil
123
+
124
+ # Time comparisons are performed with #compare_without_coercion because
125
+ # AS redefines these operators in a way that is much slower and does not
126
+ # bring any benefit in this particular code.
127
+ #
128
+ # Read t1.compare_without_coercion(t2) < 0 as t1 < t2.
129
+ paths.each do |path|
130
+ mtime = File.mtime(path)
131
+
132
+ next if time_now.compare_without_coercion(mtime) < 0
133
+
134
+ if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
135
+ max_mtime = mtime
136
+ end
131
137
  end
132
- end
133
138
 
134
- max_mtime
135
- end
139
+ max_mtime
140
+ end
136
141
 
137
- def compile_glob(hash)
138
- hash.freeze # Freeze so changes aren't accidentally pushed
139
- return if hash.empty?
142
+ def compile_glob(hash)
143
+ hash.freeze # Freeze so changes aren't accidentally pushed
144
+ return if hash.empty?
140
145
 
141
- globs = hash.map do |key, value|
142
- "#{escape(key)}/**/*#{compile_ext(value)}"
146
+ globs = hash.map do |key, value|
147
+ "#{escape(key)}/**/*#{compile_ext(value)}"
148
+ end
149
+ "{#{globs.join(",")}}"
143
150
  end
144
- "{#{globs.join(",")}}"
145
- end
146
151
 
147
- def escape(key)
148
- key.gsub(',','\,')
149
- end
152
+ def escape(key)
153
+ key.gsub(",", '\,')
154
+ end
150
155
 
151
- def compile_ext(array)
152
- array = Array(array)
153
- return if array.empty?
154
- ".{#{array.join(",")}}"
155
- end
156
+ def compile_ext(array)
157
+ array = Array(array)
158
+ return if array.empty?
159
+ ".{#{array.join(",")}}"
160
+ end
156
161
  end
157
162
  end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module ForkTracker # :nodoc:
5
+ module CoreExt
6
+ def fork(*)
7
+ if block_given?
8
+ super do
9
+ ForkTracker.check!
10
+ yield
11
+ end
12
+ else
13
+ unless pid = super
14
+ ForkTracker.check!
15
+ end
16
+ pid
17
+ end
18
+ end
19
+ end
20
+
21
+ module CoreExtPrivate
22
+ include CoreExt
23
+
24
+ private
25
+ def fork(*)
26
+ super
27
+ end
28
+ end
29
+
30
+ @pid = Process.pid
31
+ @callbacks = []
32
+
33
+ class << self
34
+ def check!
35
+ if @pid != Process.pid
36
+ @callbacks.each(&:call)
37
+ @pid = Process.pid
38
+ end
39
+ end
40
+
41
+ def hook!
42
+ if Process.respond_to?(:fork)
43
+ ::Object.prepend(CoreExtPrivate)
44
+ ::Kernel.prepend(CoreExtPrivate)
45
+ ::Kernel.singleton_class.prepend(CoreExt)
46
+ ::Process.singleton_class.prepend(CoreExt)
47
+ end
48
+ end
49
+
50
+ def after_fork(&block)
51
+ @callbacks << block
52
+ block
53
+ end
54
+
55
+ def unregister(callback)
56
+ @callbacks.delete(callback)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ ActiveSupport::ForkTracker.hook!
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  # Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>.
3
5
  def self.gem_version
@@ -5,8 +7,8 @@ module ActiveSupport
5
7
  end
6
8
 
7
9
  module VERSION
8
- MAJOR = 5
9
- MINOR = 0
10
+ MAJOR = 6
11
+ MINOR = 1
10
12
  TINY = 0
11
13
  PRE = nil
12
14
 
@@ -1,5 +1,7 @@
1
- require 'zlib'
2
- require 'stringio'
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+ require "stringio"
3
5
 
4
6
  module ActiveSupport
5
7
  # A convenient wrapper for the zlib standard library that allows
@@ -9,7 +11,7 @@ module ActiveSupport
9
11
  # # => "\x1F\x8B\b\x00o\x8D\xCDO\x00\x03K\xCE\xCF-(J-.V\xC8MU\x04\x00R>n\x83\f\x00\x00\x00"
10
12
  #
11
13
  # ActiveSupport::Gzip.decompress(gzip)
12
- # # => "compress me!"
14
+ # # => "compress me!"
13
15
  module Gzip
14
16
  class Stream < StringIO
15
17
  def initialize(*)
@@ -21,11 +23,11 @@ module ActiveSupport
21
23
 
22
24
  # Decompresses a gzipped string.
23
25
  def self.decompress(source)
24
- Zlib::GzipReader.new(StringIO.new(source)).read
26
+ Zlib::GzipReader.wrap(StringIO.new(source), &:read)
25
27
  end
26
28
 
27
29
  # Compresses a string using gzip.
28
- def self.compress(source, level=Zlib::DEFAULT_COMPRESSION, strategy=Zlib::DEFAULT_STRATEGY)
30
+ def self.compress(source, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY)
29
31
  output = Stream.new
30
32
  gz = Zlib::GzipWriter.new(output, level, strategy)
31
33
  gz.write(source)