activesupport 5.0.7.2 → 5.1.7
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +464 -694
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_support.rb +8 -4
- data/lib/active_support/all.rb +3 -3
- data/lib/active_support/array_inquirer.rb +7 -5
- data/lib/active_support/backtrace_cleaner.rb +4 -4
- data/lib/active_support/benchmarkable.rb +3 -3
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache.rb +41 -48
- data/lib/active_support/cache/file_store.rb +11 -20
- data/lib/active_support/cache/mem_cache_store.rb +30 -40
- data/lib/active_support/cache/memory_store.rb +13 -13
- data/lib/active_support/cache/null_store.rb +4 -4
- data/lib/active_support/cache/strategy/local_cache.rb +13 -22
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +4 -5
- data/lib/active_support/callbacks.rb +649 -584
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
- data/lib/active_support/concurrency/share_lock.rb +20 -21
- data/lib/active_support/configurable.rb +5 -5
- data/lib/active_support/core_ext.rb +1 -2
- data/lib/active_support/core_ext/array.rb +7 -7
- data/lib/active_support/core_ext/array/access.rb +1 -1
- data/lib/active_support/core_ext/array/conversions.rb +15 -15
- data/lib/active_support/core_ext/array/grouping.rb +1 -1
- data/lib/active_support/core_ext/array/inquiry.rb +1 -1
- data/lib/active_support/core_ext/array/prepend_and_append.rb +1 -1
- data/lib/active_support/core_ext/benchmark.rb +1 -1
- data/lib/active_support/core_ext/big_decimal.rb +1 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +4 -6
- data/lib/active_support/core_ext/class.rb +2 -2
- data/lib/active_support/core_ext/class/attribute.rb +5 -5
- data/lib/active_support/core_ext/class/attribute_accessors.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -4
- data/lib/active_support/core_ext/date.rb +5 -5
- data/lib/active_support/core_ext/date/acts_like.rb +1 -1
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +8 -8
- data/lib/active_support/core_ext/date/conversions.rb +12 -12
- data/lib/active_support/core_ext/date/zones.rb +2 -2
- data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -22
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +7 -8
- data/lib/active_support/core_ext/date_time.rb +5 -5
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -2
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +20 -10
- data/lib/active_support/core_ext/date_time/compatibility.rb +2 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +12 -12
- data/lib/active_support/core_ext/digest/uuid.rb +4 -4
- data/lib/active_support/core_ext/enumerable.rb +23 -12
- data/lib/active_support/core_ext/file.rb +1 -1
- data/lib/active_support/core_ext/file/atomic.rb +4 -4
- data/lib/active_support/core_ext/hash.rb +9 -9
- data/lib/active_support/core_ext/hash/compact.rb +12 -9
- data/lib/active_support/core_ext/hash/conversions.rb +36 -37
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -2
- data/lib/active_support/core_ext/hash/keys.rb +6 -6
- data/lib/active_support/core_ext/hash/reverse_merge.rb +1 -1
- data/lib/active_support/core_ext/hash/slice.rb +4 -4
- data/lib/active_support/core_ext/hash/transform_values.rb +1 -0
- data/lib/active_support/core_ext/integer.rb +3 -3
- data/lib/active_support/core_ext/integer/inflections.rb +1 -1
- data/lib/active_support/core_ext/integer/time.rb +2 -2
- data/lib/active_support/core_ext/kernel.rb +4 -4
- data/lib/active_support/core_ext/kernel/concern.rb +1 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +1 -1
- data/lib/active_support/core_ext/load_error.rb +1 -18
- data/lib/active_support/core_ext/module.rb +11 -12
- data/lib/active_support/core_ext/module/aliasing.rb +3 -48
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -4
- data/lib/active_support/core_ext/module/attribute_accessors.rb +11 -5
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +20 -13
- data/lib/active_support/core_ext/module/concerning.rb +1 -1
- data/lib/active_support/core_ext/module/delegation.rb +85 -16
- data/lib/active_support/core_ext/module/introspection.rb +3 -11
- data/lib/active_support/core_ext/module/reachable.rb +2 -2
- data/lib/active_support/core_ext/numeric.rb +4 -4
- data/lib/active_support/core_ext/numeric/conversions.rb +3 -9
- data/lib/active_support/core_ext/numeric/inquiry.rb +21 -21
- data/lib/active_support/core_ext/numeric/time.rb +5 -5
- data/lib/active_support/core_ext/object.rb +12 -12
- data/lib/active_support/core_ext/object/blank.rb +3 -1
- data/lib/active_support/core_ext/object/conversions.rb +4 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +34 -4
- data/lib/active_support/core_ext/object/inclusion.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +26 -12
- data/lib/active_support/core_ext/object/to_param.rb +1 -1
- data/lib/active_support/core_ext/object/to_query.rb +8 -5
- data/lib/active_support/core_ext/object/try.rb +1 -1
- data/lib/active_support/core_ext/object/with_options.rb +12 -1
- data/lib/active_support/core_ext/range.rb +4 -4
- data/lib/active_support/core_ext/range/conversions.rb +1 -1
- data/lib/active_support/core_ext/regexp.rb +4 -0
- data/lib/active_support/core_ext/securerandom.rb +3 -3
- data/lib/active_support/core_ext/string.rb +13 -13
- data/lib/active_support/core_ext/string/access.rb +6 -6
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/indent.rb +4 -4
- data/lib/active_support/core_ext/string/inflections.rb +10 -14
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +19 -20
- data/lib/active_support/core_ext/string/strip.rb +1 -1
- data/lib/active_support/core_ext/string/zones.rb +2 -2
- data/lib/active_support/core_ext/time.rb +5 -5
- data/lib/active_support/core_ext/time/acts_like.rb +1 -1
- data/lib/active_support/core_ext/time/calculations.rb +46 -29
- data/lib/active_support/core_ext/time/conversions.rb +15 -12
- data/lib/active_support/core_ext/time/zones.rb +3 -3
- data/lib/active_support/core_ext/uri.rb +2 -2
- data/lib/active_support/dependencies.rb +45 -46
- data/lib/active_support/dependencies/interlock.rb +1 -1
- data/lib/active_support/deprecation.rb +9 -8
- data/lib/active_support/deprecation/behaviors.rb +3 -3
- data/lib/active_support/deprecation/constant_accessor.rb +50 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -2
- data/lib/active_support/deprecation/method_wrappers.rb +10 -3
- data/lib/active_support/deprecation/proxy_wrappers.rb +6 -4
- data/lib/active_support/deprecation/reporting.rb +7 -7
- data/lib/active_support/duration.rb +221 -28
- data/lib/active_support/duration/iso8601_parser.rb +66 -65
- data/lib/active_support/duration/iso8601_serializer.rb +11 -9
- data/lib/active_support/evented_file_update_checker.rb +59 -55
- data/lib/active_support/execution_wrapper.rb +3 -3
- data/lib/active_support/executor.rb +1 -1
- data/lib/active_support/file_update_checker.rb +54 -50
- data/lib/active_support/gem_version.rb +2 -2
- data/lib/active_support/gzip.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +40 -28
- data/lib/active_support/i18n.rb +5 -5
- data/lib/active_support/i18n_railtie.rb +14 -9
- data/lib/active_support/inflections.rb +11 -11
- data/lib/active_support/inflector.rb +5 -5
- data/lib/active_support/inflector/inflections.rb +11 -9
- data/lib/active_support/inflector/methods.rb +52 -51
- data/lib/active_support/inflector/transliterate.rb +8 -11
- data/lib/active_support/json.rb +2 -2
- data/lib/active_support/json/decoding.rb +3 -3
- data/lib/active_support/json/encoding.rb +8 -7
- data/lib/active_support/key_generator.rb +17 -17
- data/lib/active_support/lazy_load_hooks.rb +2 -2
- data/lib/active_support/log_subscriber.rb +9 -7
- data/lib/active_support/log_subscriber/test_helper.rb +9 -9
- data/lib/active_support/logger.rb +3 -3
- data/lib/active_support/logger_silence.rb +3 -3
- data/lib/active_support/logger_thread_safe_level.rb +1 -1
- data/lib/active_support/message_encryptor.rb +77 -35
- data/lib/active_support/message_verifier.rb +7 -7
- data/lib/active_support/multibyte.rb +2 -2
- data/lib/active_support/multibyte/chars.rb +23 -21
- data/lib/active_support/multibyte/unicode.rb +68 -89
- data/lib/active_support/notifications.rb +7 -5
- data/lib/active_support/notifications/fanout.rb +3 -3
- data/lib/active_support/notifications/instrumenter.rb +5 -5
- data/lib/active_support/number_helper.rb +5 -4
- data/lib/active_support/number_helper/number_converter.rb +11 -11
- data/lib/active_support/number_helper/number_to_currency_converter.rb +3 -3
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +8 -10
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -11
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -3
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -32
- data/lib/active_support/number_helper/rounding_helper.rb +64 -0
- data/lib/active_support/option_merger.rb +1 -1
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +6 -4
- data/lib/active_support/per_thread_registry.rb +5 -5
- data/lib/active_support/rails.rb +12 -6
- data/lib/active_support/railtie.rb +3 -3
- data/lib/active_support/reloader.rb +1 -1
- data/lib/active_support/rescuable.rb +6 -6
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/string_inquirer.rb +8 -2
- data/lib/active_support/subscriber.rb +9 -5
- data/lib/active_support/tagged_logging.rb +4 -4
- data/lib/active_support/test_case.rb +12 -29
- data/lib/active_support/testing/assertions.rb +100 -2
- data/lib/active_support/testing/autorun.rb +2 -2
- data/lib/active_support/testing/constant_lookup.rb +0 -1
- data/lib/active_support/testing/declarative.rb +1 -1
- data/lib/active_support/testing/deprecation.rb +3 -2
- data/lib/active_support/testing/isolation.rb +15 -22
- data/lib/active_support/testing/method_call_assertions.rb +1 -1
- data/lib/active_support/testing/setup_and_teardown.rb +2 -2
- data/lib/active_support/testing/stream.rb +28 -28
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +45 -11
- data/lib/active_support/time.rb +12 -12
- data/lib/active_support/time_with_zone.rb +16 -14
- data/lib/active_support/values/time_zone.rb +100 -31
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini.rb +34 -36
- data/lib/active_support/xml_mini/jdom.rb +112 -112
- data/lib/active_support/xml_mini/libxml.rb +12 -11
- data/lib/active_support/xml_mini/libxmlsax.rb +13 -14
- data/lib/active_support/xml_mini/nokogiri.rb +10 -10
- data/lib/active_support/xml_mini/nokogirisax.rb +12 -13
- data/lib/active_support/xml_mini/rexml.rb +9 -9
- metadata +8 -9
- data/lib/active_support/concurrency/latch.rb +0 -26
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
- data/lib/active_support/core_ext/struct.rb +0 -3
- data/lib/active_support/core_ext/time/marshal.rb +0 -3
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require "strscan"
|
2
|
+
require "active_support/core_ext/regexp"
|
2
3
|
|
3
4
|
module ActiveSupport
|
4
5
|
class Duration
|
@@ -11,8 +12,8 @@ module ActiveSupport
|
|
11
12
|
class ParsingError < ::ArgumentError; end
|
12
13
|
|
13
14
|
PERIOD_OR_COMMA = /\.|,/
|
14
|
-
PERIOD =
|
15
|
-
COMMA =
|
15
|
+
PERIOD = ".".freeze
|
16
|
+
COMMA = ",".freeze
|
16
17
|
|
17
18
|
SIGN_MARKER = /\A\-|\+|/
|
18
19
|
DATE_MARKER = /P/
|
@@ -20,8 +21,8 @@ module ActiveSupport
|
|
20
21
|
DATE_COMPONENT = /(\-?\d+(?:[.,]\d+)?)(Y|M|D|W)/
|
21
22
|
TIME_COMPONENT = /(\-?\d+(?:[.,]\d+)?)(H|M|S)/
|
22
23
|
|
23
|
-
DATE_TO_PART = {
|
24
|
-
TIME_TO_PART = {
|
24
|
+
DATE_TO_PART = { "Y" => :years, "M" => :months, "W" => :weeks, "D" => :days }
|
25
|
+
TIME_TO_PART = { "H" => :hours, "M" => :minutes, "S" => :seconds }
|
25
26
|
|
26
27
|
DATE_COMPONENTS = [:years, :months, :days]
|
27
28
|
TIME_COMPONENTS = [:hours, :minutes, :seconds]
|
@@ -39,36 +40,36 @@ module ActiveSupport
|
|
39
40
|
def parse!
|
40
41
|
while !finished?
|
41
42
|
case mode
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
43
|
+
when :start
|
44
|
+
if scan(SIGN_MARKER)
|
45
|
+
self.sign = (scanner.matched == "-") ? -1 : 1
|
46
|
+
self.mode = :sign
|
47
|
+
else
|
48
|
+
raise_parsing_error
|
49
|
+
end
|
50
|
+
|
51
|
+
when :sign
|
52
|
+
if scan(DATE_MARKER)
|
53
|
+
self.mode = :date
|
54
|
+
else
|
55
|
+
raise_parsing_error
|
56
|
+
end
|
57
|
+
|
58
|
+
when :date
|
59
|
+
if scan(TIME_MARKER)
|
60
|
+
self.mode = :time
|
61
|
+
elsif scan(DATE_COMPONENT)
|
62
|
+
parts[DATE_TO_PART[scanner[2]]] = number * sign
|
63
|
+
else
|
64
|
+
raise_parsing_error
|
65
|
+
end
|
66
|
+
|
67
|
+
when :time
|
68
|
+
if scan(TIME_COMPONENT)
|
69
|
+
parts[TIME_TO_PART[scanner[2]]] = number * sign
|
70
|
+
else
|
71
|
+
raise_parsing_error
|
72
|
+
end
|
72
73
|
|
73
74
|
end
|
74
75
|
end
|
@@ -79,44 +80,44 @@ module ActiveSupport
|
|
79
80
|
|
80
81
|
private
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
83
|
+
def finished?
|
84
|
+
scanner.eos?
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
# Parses number which can be a float with either comma or period.
|
88
|
+
def number
|
89
|
+
PERIOD_OR_COMMA.match?(scanner[1]) ? scanner[1].tr(COMMA, PERIOD).to_f : scanner[1].to_i
|
90
|
+
end
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
92
|
+
def scan(pattern)
|
93
|
+
scanner.scan(pattern)
|
94
|
+
end
|
94
95
|
|
95
|
-
|
96
|
-
|
97
|
-
|
96
|
+
def raise_parsing_error(reason = nil)
|
97
|
+
raise ParsingError, "Invalid ISO 8601 duration: #{scanner.string.inspect} #{reason}".strip
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
100
|
+
# Checks for various semantic errors as stated in ISO 8601 standard.
|
101
|
+
def validate!
|
102
|
+
raise_parsing_error("is empty duration") if parts.empty?
|
102
103
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
104
|
+
# Mixing any of Y, M, D with W is invalid.
|
105
|
+
if parts.key?(:weeks) && (parts.keys & DATE_COMPONENTS).any?
|
106
|
+
raise_parsing_error("mixing weeks with other date parts not allowed")
|
107
|
+
end
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
109
|
+
# Specifying an empty T part is invalid.
|
110
|
+
if mode == :time && (parts.keys & TIME_COMPONENTS).empty?
|
111
|
+
raise_parsing_error("time part marker is present but time part is empty")
|
112
|
+
end
|
112
113
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
114
|
+
fractions = parts.values.reject(&:zero?).select { |a| (a % 1) != 0 }
|
115
|
+
unless fractions.empty? || (fractions.size == 1 && fractions.last == @parts.values.reject(&:zero?).last)
|
116
|
+
raise_parsing_error "(only last part can be fractional)"
|
117
|
+
end
|
117
118
|
|
118
|
-
|
119
|
-
|
119
|
+
return true
|
120
|
+
end
|
120
121
|
end
|
121
122
|
end
|
122
123
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_support/core_ext/object/blank"
|
2
|
+
require "active_support/core_ext/hash/transform_values"
|
3
3
|
|
4
4
|
module ActiveSupport
|
5
5
|
class Duration
|
6
6
|
# Serializes duration to string according to ISO 8601 Duration format.
|
7
|
-
class ISO8601Serializer
|
7
|
+
class ISO8601Serializer # :nodoc:
|
8
8
|
def initialize(duration, precision: nil)
|
9
9
|
@duration = duration
|
10
10
|
@precision = precision
|
@@ -12,19 +12,21 @@ module ActiveSupport
|
|
12
12
|
|
13
13
|
# Builds and returns output string.
|
14
14
|
def serialize
|
15
|
-
output = 'P'
|
16
15
|
parts, sign = normalize
|
16
|
+
return "PT0S".freeze if parts.empty?
|
17
|
+
|
18
|
+
output = "P"
|
17
19
|
output << "#{parts[:years]}Y" if parts.key?(:years)
|
18
20
|
output << "#{parts[:months]}M" if parts.key?(:months)
|
19
21
|
output << "#{parts[:weeks]}W" if parts.key?(:weeks)
|
20
22
|
output << "#{parts[:days]}D" if parts.key?(:days)
|
21
|
-
time =
|
23
|
+
time = ""
|
22
24
|
time << "#{parts[:hours]}H" if parts.key?(:hours)
|
23
25
|
time << "#{parts[:minutes]}M" if parts.key?(:minutes)
|
24
26
|
if parts.key?(:seconds)
|
25
27
|
time << "#{sprintf(@precision ? "%0.0#{@precision}f" : '%g', parts[:seconds])}S"
|
26
28
|
end
|
27
|
-
output << "T#{time}"
|
29
|
+
output << "T#{time}" unless time.empty?
|
28
30
|
"#{sign}#{output}"
|
29
31
|
end
|
30
32
|
|
@@ -35,13 +37,13 @@ module ActiveSupport
|
|
35
37
|
# Zero parts are removed as not significant.
|
36
38
|
# If all parts are negative it will negate all of them and return minus as a sign.
|
37
39
|
def normalize
|
38
|
-
parts = @duration.parts.each_with_object(Hash.new(0)) do |(k,v),p|
|
40
|
+
parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p|
|
39
41
|
p[k] += v unless v.zero?
|
40
42
|
end
|
41
43
|
# If all parts are negative - let's make a negative duration
|
42
|
-
sign =
|
44
|
+
sign = ""
|
43
45
|
if parts.values.all? { |v| v < 0 }
|
44
|
-
sign =
|
46
|
+
sign = "-"
|
45
47
|
parts.transform_values!(&:-@)
|
46
48
|
end
|
47
49
|
[parts, sign]
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "set"
|
2
|
+
require "pathname"
|
3
|
+
require "concurrent/atomic/atomic_boolean"
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
# Allows you to "listen" to changes in a file system.
|
@@ -17,7 +17,7 @@ module ActiveSupport
|
|
17
17
|
#
|
18
18
|
# Example:
|
19
19
|
#
|
20
|
-
# checker = EventedFileUpdateChecker.new(["/tmp/foo"]
|
20
|
+
# checker = ActiveSupport::EventedFileUpdateChecker.new(["/tmp/foo"]) { puts "changed" }
|
21
21
|
# checker.updated?
|
22
22
|
# # => false
|
23
23
|
# checker.execute_if_updated
|
@@ -32,6 +32,10 @@ module ActiveSupport
|
|
32
32
|
#
|
33
33
|
class EventedFileUpdateChecker #:nodoc: all
|
34
34
|
def initialize(files, dirs = {}, &block)
|
35
|
+
unless block
|
36
|
+
raise ArgumentError, "A block is required to initialize an EventedFileUpdateChecker"
|
37
|
+
end
|
38
|
+
|
35
39
|
@ph = PathHelper.new
|
36
40
|
@files = files.map { |f| @ph.xpath(f) }.to_set
|
37
41
|
|
@@ -52,7 +56,7 @@ module ActiveSupport
|
|
52
56
|
# to our test suite. Thus, we lazy load it and disable warnings locally.
|
53
57
|
silence_warnings do
|
54
58
|
begin
|
55
|
-
require
|
59
|
+
require "listen"
|
56
60
|
rescue LoadError => e
|
57
61
|
raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
|
58
62
|
end
|
@@ -129,71 +133,71 @@ module ActiveSupport
|
|
129
133
|
@ph.filter_out_descendants(dtw)
|
130
134
|
end
|
131
135
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
+
class PathHelper
|
137
|
+
def xpath(path)
|
138
|
+
Pathname.new(path).expand_path
|
139
|
+
end
|
136
140
|
|
137
|
-
|
138
|
-
|
139
|
-
|
141
|
+
def normalize_extension(ext)
|
142
|
+
ext.to_s.sub(/\A\./, "")
|
143
|
+
end
|
140
144
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
145
|
+
# Given a collection of Pathname objects returns the longest subpath
|
146
|
+
# common to all of them, or +nil+ if there is none.
|
147
|
+
def longest_common_subpath(paths)
|
148
|
+
return if paths.empty?
|
149
|
+
|
150
|
+
lcsp = Pathname.new(paths[0])
|
151
|
+
|
152
|
+
paths[1..-1].each do |path|
|
153
|
+
until ascendant_of?(lcsp, path)
|
154
|
+
if lcsp.root?
|
155
|
+
# If we get here a root directory is not an ascendant of path.
|
156
|
+
# This may happen if there are paths in different drives on
|
157
|
+
# Windows.
|
158
|
+
return
|
159
|
+
else
|
160
|
+
lcsp = lcsp.parent
|
161
|
+
end
|
157
162
|
end
|
158
163
|
end
|
159
|
-
end
|
160
164
|
|
161
|
-
|
162
|
-
|
165
|
+
lcsp
|
166
|
+
end
|
163
167
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
+
# Returns the deepest existing ascendant, which could be the argument itself.
|
169
|
+
def existing_parent(dir)
|
170
|
+
dir.ascend do |ascendant|
|
171
|
+
break ascendant if ascendant.directory?
|
172
|
+
end
|
168
173
|
end
|
169
|
-
end
|
170
174
|
|
171
|
-
|
172
|
-
|
173
|
-
|
175
|
+
# Filters out directories which are descendants of others in the collection (stable).
|
176
|
+
def filter_out_descendants(dirs)
|
177
|
+
return dirs if dirs.length < 2
|
174
178
|
|
175
|
-
|
176
|
-
|
179
|
+
dirs_sorted_by_nparts = dirs.sort_by { |dir| dir.each_filename.to_a.length }
|
180
|
+
descendants = []
|
177
181
|
|
178
|
-
|
179
|
-
|
182
|
+
until dirs_sorted_by_nparts.empty?
|
183
|
+
dir = dirs_sorted_by_nparts.shift
|
180
184
|
|
181
|
-
|
182
|
-
|
185
|
+
dirs_sorted_by_nparts.reject! do |possible_descendant|
|
186
|
+
ascendant_of?(dir, possible_descendant) && descendants << possible_descendant
|
187
|
+
end
|
183
188
|
end
|
184
|
-
end
|
185
189
|
|
186
|
-
|
187
|
-
|
188
|
-
|
190
|
+
# Array#- preserves order.
|
191
|
+
dirs - descendants
|
192
|
+
end
|
189
193
|
|
190
|
-
|
194
|
+
private
|
191
195
|
|
192
|
-
|
193
|
-
|
194
|
-
|
196
|
+
def ascendant_of?(base, other)
|
197
|
+
base != other && other.ascend do |ascendant|
|
198
|
+
break true if base == ascendant
|
199
|
+
end
|
195
200
|
end
|
196
|
-
|
197
|
-
end
|
201
|
+
end
|
198
202
|
end
|
199
203
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/callbacks"
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
4
|
class ExecutionWrapper
|
@@ -19,14 +19,14 @@ module ActiveSupport
|
|
19
19
|
set_callback(:complete, *args, &block)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
RunHook = Struct.new(:hook) do # :nodoc:
|
23
23
|
def before(target)
|
24
24
|
hook_state = target.send(:hook_state)
|
25
25
|
hook_state[hook] = hook.run
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
29
|
+
CompleteHook = Struct.new(:hook) do # :nodoc:
|
30
30
|
def before(target)
|
31
31
|
hook_state = target.send(:hook_state)
|
32
32
|
if hook_state.key?(hook)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/core_ext/time/calculations"
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
4
|
# FileUpdateChecker specifies the API used by Rails to watch files
|
@@ -38,6 +38,10 @@ module ActiveSupport
|
|
38
38
|
# changes. The array of files and list of directories cannot be changed
|
39
39
|
# after FileUpdateChecker has been initialized.
|
40
40
|
def initialize(files, dirs = {}, &block)
|
41
|
+
unless block
|
42
|
+
raise ArgumentError, "A block is required to initialize a FileUpdateChecker"
|
43
|
+
end
|
44
|
+
|
41
45
|
@files = files.freeze
|
42
46
|
@glob = compile_glob(dirs)
|
43
47
|
@block = block
|
@@ -93,65 +97,65 @@ module ActiveSupport
|
|
93
97
|
|
94
98
|
private
|
95
99
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
100
|
+
def watched
|
101
|
+
@watched || begin
|
102
|
+
all = @files.select { |f| File.exist?(f) }
|
103
|
+
all.concat(Dir[@glob]) if @glob
|
104
|
+
all
|
105
|
+
end
|
101
106
|
end
|
102
|
-
end
|
103
107
|
|
104
|
-
|
105
|
-
|
106
|
-
|
108
|
+
def updated_at(paths)
|
109
|
+
@updated_at || max_mtime(paths) || Time.at(0)
|
110
|
+
end
|
107
111
|
|
108
|
-
|
109
|
-
|
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.
|
112
|
+
# This method returns the maximum mtime of the files in +paths+, or +nil+
|
113
|
+
# if the array is empty.
|
122
114
|
#
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
115
|
+
# Files with a mtime in the future are ignored. Such abnormal situation
|
116
|
+
# can happen for example if the user changes the clock by hand. It is
|
117
|
+
# healthy to consider this edge case because with mtimes in the future
|
118
|
+
# reloading is not triggered.
|
119
|
+
def max_mtime(paths)
|
120
|
+
time_now = Time.now
|
121
|
+
max_mtime = nil
|
122
|
+
|
123
|
+
# Time comparisons are performed with #compare_without_coercion because
|
124
|
+
# AS redefines these operators in a way that is much slower and does not
|
125
|
+
# bring any benefit in this particular code.
|
126
|
+
#
|
127
|
+
# Read t1.compare_without_coercion(t2) < 0 as t1 < t2.
|
128
|
+
paths.each do |path|
|
129
|
+
mtime = File.mtime(path)
|
130
|
+
|
131
|
+
next if time_now.compare_without_coercion(mtime) < 0
|
132
|
+
|
133
|
+
if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
|
134
|
+
max_mtime = mtime
|
135
|
+
end
|
131
136
|
end
|
132
|
-
end
|
133
137
|
|
134
|
-
|
135
|
-
|
138
|
+
max_mtime
|
139
|
+
end
|
136
140
|
|
137
|
-
|
138
|
-
|
139
|
-
|
141
|
+
def compile_glob(hash)
|
142
|
+
hash.freeze # Freeze so changes aren't accidentally pushed
|
143
|
+
return if hash.empty?
|
140
144
|
|
141
|
-
|
142
|
-
|
145
|
+
globs = hash.map do |key, value|
|
146
|
+
"#{escape(key)}/**/*#{compile_ext(value)}"
|
147
|
+
end
|
148
|
+
"{#{globs.join(",")}}"
|
143
149
|
end
|
144
|
-
"{#{globs.join(",")}}"
|
145
|
-
end
|
146
150
|
|
147
|
-
|
148
|
-
|
149
|
-
|
151
|
+
def escape(key)
|
152
|
+
key.gsub(",", '\,')
|
153
|
+
end
|
150
154
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
155
|
+
def compile_ext(array)
|
156
|
+
array = Array(array)
|
157
|
+
return if array.empty?
|
158
|
+
".{#{array.join(",")}}"
|
159
|
+
end
|
156
160
|
end
|
157
161
|
end
|