activesupport 4.2.11.1 → 6.0.3.1

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 (263) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -411
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -7
  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 +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +34 -6
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +58 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +95 -91
  13. data/lib/active_support/cache/memory_store.rb +39 -36
  14. data/lib/active_support/cache/null_store.rb +11 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +75 -42
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +331 -217
  19. data/lib/active_support/callbacks.rb +650 -592
  20. data/lib/active_support/concern.rb +35 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +226 -0
  23. data/lib/active_support/configurable.rb +13 -14
  24. data/lib/active_support/core_ext/array/access.rb +41 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +24 -20
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  29. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
  31. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  32. data/lib/active_support/core_ext/array.rb +9 -6
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +45 -31
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  39. data/lib/active_support/core_ext/class.rb +4 -3
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +14 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  43. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +6 -4
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
  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 +14 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  53. data/lib/active_support/core_ext/date_time/conversions.rb +16 -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 +114 -22
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/compact.rb +4 -23
  61. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  64. data/lib/active_support/core_ext/hash/except.rb +12 -9
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  66. data/lib/active_support/core_ext/hash/keys.rb +19 -42
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  68. data/lib/active_support/core_ext/hash/slice.rb +5 -27
  69. data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
  70. data/lib/active_support/core_ext/hash.rb +10 -9
  71. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  72. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  73. data/lib/active_support/core_ext/integer/time.rb +11 -18
  74. data/lib/active_support/core_ext/integer.rb +5 -3
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/kernel.rb +5 -5
  79. data/lib/active_support/core_ext/load_error.rb +3 -22
  80. data/lib/active_support/core_ext/marshal.rb +8 -8
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -46
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +133 -30
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +44 -19
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -7
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -11
  94. data/lib/active_support/core_ext/name_error.rb +22 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  99. data/lib/active_support/core_ext/numeric.rb +5 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +27 -3
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +13 -93
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +51 -20
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  110. data/lib/active_support/core_ext/object/try.rb +81 -23
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/object.rb +14 -13
  113. data/lib/active_support/core_ext/range/compare_range.rb +76 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  115. data/lib/active_support/core_ext/range/each.rb +18 -17
  116. data/lib/active_support/core_ext/range/include_range.rb +7 -21
  117. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  119. data/lib/active_support/core_ext/range.rb +7 -4
  120. data/lib/active_support/core_ext/regexp.rb +2 -0
  121. data/lib/active_support/core_ext/securerandom.rb +45 -0
  122. data/lib/active_support/core_ext/string/access.rb +16 -6
  123. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  124. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  125. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  126. data/lib/active_support/core_ext/string/filters.rb +48 -6
  127. data/lib/active_support/core_ext/string/indent.rb +6 -4
  128. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  129. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  130. data/lib/active_support/core_ext/string/multibyte.rb +16 -7
  131. data/lib/active_support/core_ext/string/output_safety.rb +93 -40
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  133. data/lib/active_support/core_ext/string/strip.rb +6 -5
  134. data/lib/active_support/core_ext/string/zones.rb +4 -2
  135. data/lib/active_support/core_ext/string.rb +15 -13
  136. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  137. data/lib/active_support/core_ext/time/calculations.rb +115 -52
  138. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  139. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  140. data/lib/active_support/core_ext/time/zones.rb +41 -7
  141. data/lib/active_support/core_ext/time.rb +7 -6
  142. data/lib/active_support/core_ext/uri.rb +6 -7
  143. data/lib/active_support/core_ext.rb +3 -1
  144. data/lib/active_support/current_attributes.rb +203 -0
  145. data/lib/active_support/dependencies/autoload.rb +2 -0
  146. data/lib/active_support/dependencies/interlock.rb +57 -0
  147. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  148. data/lib/active_support/dependencies.rb +208 -166
  149. data/lib/active_support/deprecation/behaviors.rb +44 -11
  150. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  151. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  152. data/lib/active_support/deprecation/method_wrappers.rb +61 -21
  153. data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
  154. data/lib/active_support/deprecation/reporting.rb +32 -12
  155. data/lib/active_support/deprecation.rb +12 -9
  156. data/lib/active_support/descendants_tracker.rb +57 -9
  157. data/lib/active_support/digest.rb +20 -0
  158. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  159. data/lib/active_support/duration/iso8601_serializer.rb +53 -0
  160. data/lib/active_support/duration.rb +315 -40
  161. data/lib/active_support/encrypted_configuration.rb +45 -0
  162. data/lib/active_support/encrypted_file.rb +100 -0
  163. data/lib/active_support/evented_file_update_checker.rb +234 -0
  164. data/lib/active_support/execution_wrapper.rb +129 -0
  165. data/lib/active_support/executor.rb +8 -0
  166. data/lib/active_support/file_update_checker.rb +62 -37
  167. data/lib/active_support/gem_version.rb +6 -4
  168. data/lib/active_support/gzip.rb +7 -5
  169. data/lib/active_support/hash_with_indifferent_access.rb +129 -30
  170. data/lib/active_support/i18n.rb +9 -6
  171. data/lib/active_support/i18n_railtie.rb +50 -14
  172. data/lib/active_support/inflections.rb +13 -11
  173. data/lib/active_support/inflector/inflections.rb +58 -13
  174. data/lib/active_support/inflector/methods.rb +159 -145
  175. data/lib/active_support/inflector/transliterate.rb +84 -34
  176. data/lib/active_support/inflector.rb +7 -5
  177. data/lib/active_support/json/decoding.rb +32 -30
  178. data/lib/active_support/json/encoding.rb +17 -60
  179. data/lib/active_support/json.rb +4 -2
  180. data/lib/active_support/key_generator.rb +11 -43
  181. data/lib/active_support/lazy_load_hooks.rb +53 -20
  182. data/lib/active_support/locale/en.rb +33 -0
  183. data/lib/active_support/locale/en.yml +2 -0
  184. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  185. data/lib/active_support/log_subscriber.rb +44 -19
  186. data/lib/active_support/logger.rb +9 -23
  187. data/lib/active_support/logger_silence.rb +32 -14
  188. data/lib/active_support/logger_thread_safe_level.rb +32 -8
  189. data/lib/active_support/message_encryptor.rb +166 -53
  190. data/lib/active_support/message_verifier.rb +149 -16
  191. data/lib/active_support/messages/metadata.rb +72 -0
  192. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  193. data/lib/active_support/messages/rotator.rb +56 -0
  194. data/lib/active_support/multibyte/chars.rb +56 -63
  195. data/lib/active_support/multibyte/unicode.rb +56 -290
  196. data/lib/active_support/multibyte.rb +4 -2
  197. data/lib/active_support/notifications/fanout.rb +109 -22
  198. data/lib/active_support/notifications/instrumenter.rb +107 -16
  199. data/lib/active_support/notifications.rb +51 -10
  200. data/lib/active_support/number_helper/number_converter.rb +16 -15
  201. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
  202. data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
  203. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
  204. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
  205. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  206. data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
  207. data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
  208. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  209. data/lib/active_support/number_helper.rb +105 -68
  210. data/lib/active_support/option_merger.rb +24 -4
  211. data/lib/active_support/ordered_hash.rb +7 -5
  212. data/lib/active_support/ordered_options.rb +27 -5
  213. data/lib/active_support/parameter_filter.rb +128 -0
  214. data/lib/active_support/per_thread_registry.rb +9 -4
  215. data/lib/active_support/proxy_object.rb +2 -0
  216. data/lib/active_support/rails.rb +10 -8
  217. data/lib/active_support/railtie.rb +43 -9
  218. data/lib/active_support/reloader.rb +130 -0
  219. data/lib/active_support/rescuable.rb +108 -53
  220. data/lib/active_support/security_utils.rb +15 -11
  221. data/lib/active_support/string_inquirer.rb +11 -4
  222. data/lib/active_support/subscriber.rb +74 -30
  223. data/lib/active_support/tagged_logging.rb +25 -13
  224. data/lib/active_support/test_case.rb +107 -44
  225. data/lib/active_support/testing/assertions.rb +151 -20
  226. data/lib/active_support/testing/autorun.rb +4 -2
  227. data/lib/active_support/testing/constant_lookup.rb +2 -1
  228. data/lib/active_support/testing/declarative.rb +3 -1
  229. data/lib/active_support/testing/deprecation.rb +13 -10
  230. data/lib/active_support/testing/file_fixtures.rb +38 -0
  231. data/lib/active_support/testing/isolation.rb +35 -26
  232. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  233. data/lib/active_support/testing/parallelization.rb +134 -0
  234. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  235. data/lib/active_support/testing/stream.rb +43 -0
  236. data/lib/active_support/testing/tagged_logging.rb +3 -1
  237. data/lib/active_support/testing/time_helpers.rb +84 -20
  238. data/lib/active_support/time.rb +14 -12
  239. data/lib/active_support/time_with_zone.rb +179 -39
  240. data/lib/active_support/values/time_zone.rb +203 -63
  241. data/lib/active_support/version.rb +3 -1
  242. data/lib/active_support/xml_mini/jdom.rb +116 -115
  243. data/lib/active_support/xml_mini/libxml.rb +16 -13
  244. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  245. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  246. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  247. data/lib/active_support/xml_mini/rexml.rb +11 -9
  248. data/lib/active_support/xml_mini.rb +38 -46
  249. data/lib/active_support.rb +13 -11
  250. metadata +84 -26
  251. data/lib/active_support/concurrency/latch.rb +0 -27
  252. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  253. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  254. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  255. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  256. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  257. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  258. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  259. data/lib/active_support/core_ext/object/itself.rb +0 -15
  260. data/lib/active_support/core_ext/struct.rb +0 -6
  261. data/lib/active_support/core_ext/thread.rb +0 -86
  262. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  263. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "pathname"
5
+ require "concurrent/atomic/atomic_boolean"
6
+
7
+ module ActiveSupport
8
+ # Allows you to "listen" to changes in a file system.
9
+ # The evented file updater does not hit disk when checking for updates
10
+ # instead it uses platform specific file system events to trigger a change
11
+ # in state.
12
+ #
13
+ # The file checker takes an array of files to watch or a hash specifying directories
14
+ # and file extensions to watch. It also takes a block that is called when
15
+ # EventedFileUpdateChecker#execute is run or when EventedFileUpdateChecker#execute_if_updated
16
+ # is run and there have been changes to the file system.
17
+ #
18
+ # Note: Forking will cause the first call to `updated?` to return `true`.
19
+ #
20
+ # Example:
21
+ #
22
+ # checker = ActiveSupport::EventedFileUpdateChecker.new(["/tmp/foo"]) { puts "changed" }
23
+ # checker.updated?
24
+ # # => false
25
+ # checker.execute_if_updated
26
+ # # => nil
27
+ #
28
+ # FileUtils.touch("/tmp/foo")
29
+ #
30
+ # checker.updated?
31
+ # # => true
32
+ # checker.execute_if_updated
33
+ # # => "changed"
34
+ #
35
+ class EventedFileUpdateChecker #:nodoc: all
36
+ def initialize(files, dirs = {}, &block)
37
+ unless block
38
+ raise ArgumentError, "A block is required to initialize an EventedFileUpdateChecker"
39
+ end
40
+
41
+ @ph = PathHelper.new
42
+ @files = files.map { |f| @ph.xpath(f) }.to_set
43
+
44
+ @dirs = {}
45
+ dirs.each do |dir, exts|
46
+ @dirs[@ph.xpath(dir)] = Array(exts).map { |ext| @ph.normalize_extension(ext) }
47
+ end
48
+
49
+ @block = block
50
+ @updated = Concurrent::AtomicBoolean.new(false)
51
+ @lcsp = @ph.longest_common_subpath(@dirs.keys)
52
+ @pid = Process.pid
53
+ @boot_mutex = Mutex.new
54
+
55
+ dtw = directories_to_watch
56
+ @dtw, @missing = dtw.partition(&:exist?)
57
+
58
+ if @dtw.any?
59
+ # Loading listen triggers warnings. These are originated by a legit
60
+ # usage of attr_* macros for private attributes, but adds a lot of noise
61
+ # to our test suite. Thus, we lazy load it and disable warnings locally.
62
+ silence_warnings do
63
+ require "listen"
64
+ rescue LoadError => e
65
+ raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
66
+ end
67
+ end
68
+ boot!
69
+ end
70
+
71
+ def updated?
72
+ @boot_mutex.synchronize do
73
+ if @pid != Process.pid
74
+ boot!
75
+ @pid = Process.pid
76
+ @updated.make_true
77
+ end
78
+ end
79
+
80
+ if @missing.any?(&:exist?)
81
+ @boot_mutex.synchronize do
82
+ appeared, @missing = @missing.partition(&:exist?)
83
+ shutdown!
84
+
85
+ @dtw += appeared
86
+ boot!
87
+
88
+ @updated.make_true
89
+ end
90
+ end
91
+
92
+ @updated.true?
93
+ end
94
+
95
+ def execute
96
+ @updated.make_false
97
+ @block.call
98
+ end
99
+
100
+ def execute_if_updated
101
+ if updated?
102
+ yield if block_given?
103
+ execute
104
+ true
105
+ end
106
+ end
107
+
108
+ private
109
+ def boot!
110
+ normalize_dirs!
111
+
112
+ unless @dtw.empty?
113
+ Listen.to(*@dtw, &method(:changed)).start
114
+ end
115
+ end
116
+
117
+ def shutdown!
118
+ Listen.stop
119
+ end
120
+
121
+ def normalize_dirs!
122
+ @dirs.transform_keys! do |dir|
123
+ dir.exist? ? dir.realpath : dir
124
+ end
125
+ end
126
+
127
+ def changed(modified, added, removed)
128
+ unless updated?
129
+ @updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
130
+ end
131
+ end
132
+
133
+ def watching?(file)
134
+ file = @ph.xpath(file)
135
+
136
+ if @files.member?(file)
137
+ true
138
+ elsif file.directory?
139
+ false
140
+ else
141
+ ext = @ph.normalize_extension(file.extname)
142
+
143
+ file.dirname.ascend do |dir|
144
+ matching = @dirs[dir]
145
+
146
+ if matching && (matching.empty? || matching.include?(ext))
147
+ break true
148
+ elsif dir == @lcsp || dir.root?
149
+ break false
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ def directories_to_watch
156
+ dtw = @files.map(&:dirname) + @dirs.keys
157
+ dtw.compact!
158
+ dtw.uniq!
159
+
160
+ normalized_gem_paths = Gem.path.map { |path| File.join path, "" }
161
+ dtw = dtw.reject do |path|
162
+ normalized_gem_paths.any? { |gem_path| path.to_s.start_with?(gem_path) }
163
+ end
164
+
165
+ @ph.filter_out_descendants(dtw)
166
+ end
167
+
168
+ class PathHelper
169
+ def xpath(path)
170
+ Pathname.new(path).expand_path
171
+ end
172
+
173
+ def normalize_extension(ext)
174
+ ext.to_s.sub(/\A\./, "")
175
+ end
176
+
177
+ # Given a collection of Pathname objects returns the longest subpath
178
+ # common to all of them, or +nil+ if there is none.
179
+ def longest_common_subpath(paths)
180
+ return if paths.empty?
181
+
182
+ lcsp = Pathname.new(paths[0])
183
+
184
+ paths[1..-1].each do |path|
185
+ until ascendant_of?(lcsp, path)
186
+ if lcsp.root?
187
+ # If we get here a root directory is not an ascendant of path.
188
+ # This may happen if there are paths in different drives on
189
+ # Windows.
190
+ return
191
+ else
192
+ lcsp = lcsp.parent
193
+ end
194
+ end
195
+ end
196
+
197
+ lcsp
198
+ end
199
+
200
+ # Returns the deepest existing ascendant, which could be the argument itself.
201
+ def existing_parent(dir)
202
+ dir.ascend do |ascendant|
203
+ break ascendant if ascendant.directory?
204
+ end
205
+ end
206
+
207
+ # Filters out directories which are descendants of others in the collection (stable).
208
+ def filter_out_descendants(dirs)
209
+ return dirs if dirs.length < 2
210
+
211
+ dirs_sorted_by_nparts = dirs.sort_by { |dir| dir.each_filename.to_a.length }
212
+ descendants = []
213
+
214
+ until dirs_sorted_by_nparts.empty?
215
+ dir = dirs_sorted_by_nparts.shift
216
+
217
+ dirs_sorted_by_nparts.reject! do |possible_descendant|
218
+ ascendant_of?(dir, possible_descendant) && descendants << possible_descendant
219
+ end
220
+ end
221
+
222
+ # Array#- preserves order.
223
+ dirs - descendants
224
+ end
225
+
226
+ private
227
+ def ascendant_of?(base, other)
228
+ base != other && other.ascend do |ascendant|
229
+ break true if base == ascendant
230
+ end
231
+ end
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/callbacks"
4
+ require "concurrent/hash"
5
+
6
+ module ActiveSupport
7
+ class ExecutionWrapper
8
+ include ActiveSupport::Callbacks
9
+
10
+ Null = Object.new # :nodoc:
11
+ def Null.complete! # :nodoc:
12
+ end
13
+
14
+ define_callbacks :run
15
+ define_callbacks :complete
16
+
17
+ def self.to_run(*args, &block)
18
+ set_callback(:run, *args, &block)
19
+ end
20
+
21
+ def self.to_complete(*args, &block)
22
+ set_callback(:complete, *args, &block)
23
+ end
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
+
42
+ # Register an object to be invoked during both the +run+ and
43
+ # +complete+ steps.
44
+ #
45
+ # +hook.complete+ will be passed the value returned from +hook.run+,
46
+ # and will only be invoked if +run+ has previously been called.
47
+ # (Mostly, this means it won't be invoked if an exception occurs in
48
+ # a preceding +to_run+ block; all ordinary +to_complete+ blocks are
49
+ # invoked in that situation.)
50
+ def self.register_hook(hook, outer: false)
51
+ if outer
52
+ to_run RunHook.new(hook), prepend: true
53
+ to_complete :after, CompleteHook.new(hook)
54
+ else
55
+ to_run RunHook.new(hook)
56
+ to_complete CompleteHook.new(hook)
57
+ end
58
+ end
59
+
60
+ # Run this execution.
61
+ #
62
+ # Returns an instance, whose +complete!+ method *must* be invoked
63
+ # after the work has been performed.
64
+ #
65
+ # Where possible, prefer +wrap+.
66
+ def self.run!
67
+ if active?
68
+ Null
69
+ else
70
+ new.tap do |instance|
71
+ success = nil
72
+ begin
73
+ instance.run!
74
+ success = true
75
+ ensure
76
+ instance.complete! unless success
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ # Perform the work in the supplied block as an execution.
83
+ def self.wrap
84
+ return yield if active?
85
+
86
+ instance = run!
87
+ begin
88
+ yield
89
+ ensure
90
+ instance.complete!
91
+ end
92
+ end
93
+
94
+ class << self # :nodoc:
95
+ attr_accessor :active
96
+ end
97
+
98
+ def self.inherited(other) # :nodoc:
99
+ super
100
+ other.active = Concurrent::Hash.new
101
+ end
102
+
103
+ self.active = Concurrent::Hash.new
104
+
105
+ def self.active? # :nodoc:
106
+ @active[Thread.current]
107
+ end
108
+
109
+ def run! # :nodoc:
110
+ self.class.active[Thread.current] = true
111
+ run_callbacks(:run)
112
+ end
113
+
114
+ # Complete this in-flight execution. This method *must* be called
115
+ # exactly once on the result of any call to +run!+.
116
+ #
117
+ # Where possible, prefer +wrap+.
118
+ def complete!
119
+ run_callbacks(:complete)
120
+ ensure
121
+ self.class.active.delete Thread.current
122
+ end
123
+
124
+ private
125
+ def hook_state
126
+ @_hook_state ||= {}
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/execution_wrapper"
4
+
5
+ module ActiveSupport
6
+ class Executor < ExecutionWrapper
7
+ end
8
+ end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/time/calculations"
4
+
1
5
  module ActiveSupport
2
6
  # FileUpdateChecker specifies the API used by Rails to watch files
3
7
  # and control reloading. The API depends on four methods:
@@ -23,7 +27,7 @@ module ActiveSupport
23
27
  # I18n.reload!
24
28
  # end
25
29
  #
26
- # ActionDispatch::Reloader.to_prepare do
30
+ # ActiveSupport::Reloader.to_prepare do
27
31
  # i18n_reloader.execute_if_updated
28
32
  # end
29
33
  class FileUpdateChecker
@@ -35,7 +39,11 @@ module ActiveSupport
35
39
  # This method must also receive a block that will be called once a path
36
40
  # changes. The array of files and list of directories cannot be changed
37
41
  # after FileUpdateChecker has been initialized.
38
- def initialize(files, dirs={}, &block)
42
+ def initialize(files, dirs = {}, &block)
43
+ unless block
44
+ raise ArgumentError, "A block is required to initialize a FileUpdateChecker"
45
+ end
46
+
39
47
  @files = files.freeze
40
48
  @glob = compile_glob(dirs)
41
49
  @block = block
@@ -81,6 +89,7 @@ module ActiveSupport
81
89
  # Execute the block given if updated.
82
90
  def execute_if_updated
83
91
  if updated?
92
+ yield if block_given?
84
93
  execute
85
94
  true
86
95
  else
@@ -89,49 +98,65 @@ module ActiveSupport
89
98
  end
90
99
 
91
100
  private
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
107
+ end
92
108
 
93
- def watched
94
- @watched || begin
95
- all = @files.select { |f| File.exist?(f) }
96
- all.concat(Dir[@glob]) if @glob
97
- all
109
+ def updated_at(paths)
110
+ @updated_at || max_mtime(paths) || Time.at(0)
98
111
  end
99
- end
100
112
 
101
- def updated_at(paths)
102
- @updated_at || max_mtime(paths) || Time.at(0)
103
- end
113
+ # This method returns the maximum mtime of the files in +paths+, or +nil+
114
+ # if the array is empty.
115
+ #
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
104
123
 
105
- # This method returns the maximum mtime of the files in +paths+, or +nil+
106
- # if the array is empty.
107
- #
108
- # Files with a mtime in the future are ignored. Such abnormal situation
109
- # can happen for example if the user changes the clock by hand. It is
110
- # healthy to consider this edge case because with mtimes in the future
111
- # reloading is not triggered.
112
- def max_mtime(paths)
113
- time_now = Time.now
114
- paths.map {|path| File.mtime(path)}.reject {|mtime| time_now < mtime}.max
115
- end
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)
116
131
 
117
- def compile_glob(hash)
118
- hash.freeze # Freeze so changes aren't accidentally pushed
119
- return if hash.empty?
132
+ next if time_now.compare_without_coercion(mtime) < 0
120
133
 
121
- globs = hash.map do |key, value|
122
- "#{escape(key)}/**/*#{compile_ext(value)}"
134
+ if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
135
+ max_mtime = mtime
136
+ end
137
+ end
138
+
139
+ max_mtime
123
140
  end
124
- "{#{globs.join(",")}}"
125
- end
126
141
 
127
- def escape(key)
128
- key.gsub(',','\,')
129
- end
142
+ def compile_glob(hash)
143
+ hash.freeze # Freeze so changes aren't accidentally pushed
144
+ return if hash.empty?
130
145
 
131
- def compile_ext(array)
132
- array = Array(array)
133
- return if array.empty?
134
- ".{#{array.join(",")}}"
135
- end
146
+ globs = hash.map do |key, value|
147
+ "#{escape(key)}/**/*#{compile_ext(value)}"
148
+ end
149
+ "{#{globs.join(",")}}"
150
+ end
151
+
152
+ def escape(key)
153
+ key.gsub(",", '\,')
154
+ end
155
+
156
+ def compile_ext(array)
157
+ array = Array(array)
158
+ return if array.empty?
159
+ ".{#{array.join(",")}}"
160
+ end
136
161
  end
137
162
  end
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
- # Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>
4
+ # Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>.
3
5
  def self.gem_version
4
6
  Gem::Version.new VERSION::STRING
5
7
  end
6
8
 
7
9
  module VERSION
8
- MAJOR = 4
9
- MINOR = 2
10
- TINY = 11
10
+ MAJOR = 6
11
+ MINOR = 0
12
+ TINY = 3
11
13
  PRE = "1"
12
14
 
13
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -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)