csd 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (258) hide show
  1. data/COPYING +1 -2
  2. data/README.rdoc +7 -1
  3. data/Rakefile +7 -2
  4. data/VERSION +1 -1
  5. data/csd.gemspec +18 -216
  6. data/lib/csd.rb +6 -16
  7. data/lib/csd/application.rb +2 -2
  8. data/lib/csd/application/default.rb +15 -14
  9. data/lib/csd/application/default/base.rb +1 -1
  10. data/lib/csd/application/minisip.rb +43 -11
  11. data/lib/csd/application/minisip/about.yml +5 -5
  12. data/lib/csd/application/minisip/base.rb +82 -70
  13. data/lib/csd/application/minisip/error.rb +1 -1
  14. data/lib/csd/application/minisip/options/common.rb +1 -1
  15. data/lib/csd/application/minisip/options/compile.rb +1 -1
  16. data/lib/csd/application/minisip/options/package.rb +1 -1
  17. data/lib/csd/application/minisip/unix.rb +40 -27
  18. data/lib/csd/application/minisip/unix/darwin.rb +12 -0
  19. data/lib/csd/application/minisip/unix/linux.rb +1 -11
  20. data/lib/csd/application/minisip/unix/linux/debian.rb +14 -25
  21. data/lib/csd/application/minisip/unix/linux/debian/ubuntu10.rb +12 -13
  22. data/lib/csd/applications.rb +5 -5
  23. data/lib/csd/commands.rb +164 -89
  24. data/lib/csd/container.rb +61 -0
  25. data/lib/csd/error.rb +10 -1
  26. data/lib/csd/extensions.rb +3 -2
  27. data/lib/csd/extensions/core/array.rb +29 -1
  28. data/lib/csd/extensions/core/dir.rb +15 -24
  29. data/lib/csd/extensions/core/object.rb +10 -2
  30. data/lib/csd/extensions/core/option_parser.rb +22 -3
  31. data/lib/csd/extensions/core/pathname.rb +30 -2
  32. data/lib/csd/extensions/core/string.rb +51 -4
  33. data/lib/csd/extensions/gem/platform.rb +18 -3
  34. data/lib/csd/{options.rb → options_parser.rb} +16 -20
  35. data/lib/csd/path_container.rb +24 -0
  36. data/lib/csd/user_interface.rb +2 -0
  37. data/lib/csd/user_interface/base.rb +26 -0
  38. data/lib/csd/user_interface/cli.rb +37 -0
  39. data/lib/csd/vendor/active_support/MIT-LICENSE +20 -0
  40. data/lib/csd/vendor/active_support/inflector.rb +155 -0
  41. data/lib/csd/vendor/term/GPL2-LICENSE +339 -0
  42. data/lib/csd/vendor/term/ansicolor.rb +113 -0
  43. data/lib/csd/version.rb +13 -4
  44. data/test/application/test_minisip.rb +45 -0
  45. data/test/functional/test_applications.rb +10 -16
  46. data/test/functional/test_commands.rb +260 -23
  47. data/test/unit/test_string.rb +1 -1
  48. metadata +18 -216
  49. data/lib/active_support.rb +0 -75
  50. data/lib/active_support/all.rb +0 -3
  51. data/lib/active_support/backtrace_cleaner.rb +0 -94
  52. data/lib/active_support/base64.rb +0 -42
  53. data/lib/active_support/basic_object.rb +0 -21
  54. data/lib/active_support/benchmarkable.rb +0 -60
  55. data/lib/active_support/buffered_logger.rb +0 -132
  56. data/lib/active_support/builder.rb +0 -6
  57. data/lib/active_support/cache.rb +0 -626
  58. data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
  59. data/lib/active_support/cache/file_store.rb +0 -188
  60. data/lib/active_support/cache/mem_cache_store.rb +0 -191
  61. data/lib/active_support/cache/memory_store.rb +0 -159
  62. data/lib/active_support/cache/strategy/local_cache.rb +0 -164
  63. data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
  64. data/lib/active_support/callbacks.rb +0 -600
  65. data/lib/active_support/concern.rb +0 -29
  66. data/lib/active_support/configurable.rb +0 -36
  67. data/lib/active_support/core_ext.rb +0 -3
  68. data/lib/active_support/core_ext/array.rb +0 -7
  69. data/lib/active_support/core_ext/array/access.rb +0 -46
  70. data/lib/active_support/core_ext/array/conversions.rb +0 -164
  71. data/lib/active_support/core_ext/array/extract_options.rb +0 -29
  72. data/lib/active_support/core_ext/array/grouping.rb +0 -100
  73. data/lib/active_support/core_ext/array/random_access.rb +0 -20
  74. data/lib/active_support/core_ext/array/uniq_by.rb +0 -17
  75. data/lib/active_support/core_ext/array/wrap.rb +0 -22
  76. data/lib/active_support/core_ext/benchmark.rb +0 -7
  77. data/lib/active_support/core_ext/big_decimal.rb +0 -1
  78. data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -27
  79. data/lib/active_support/core_ext/cgi.rb +0 -1
  80. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -19
  81. data/lib/active_support/core_ext/class.rb +0 -4
  82. data/lib/active_support/core_ext/class/attribute.rb +0 -67
  83. data/lib/active_support/core_ext/class/attribute_accessors.rb +0 -63
  84. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -44
  85. data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -232
  86. data/lib/active_support/core_ext/class/subclasses.rb +0 -55
  87. data/lib/active_support/core_ext/date/acts_like.rb +0 -8
  88. data/lib/active_support/core_ext/date/calculations.rb +0 -240
  89. data/lib/active_support/core_ext/date/conversions.rb +0 -99
  90. data/lib/active_support/core_ext/date/freeze.rb +0 -31
  91. data/lib/active_support/core_ext/date_time/acts_like.rb +0 -13
  92. data/lib/active_support/core_ext/date_time/calculations.rb +0 -113
  93. data/lib/active_support/core_ext/date_time/conversions.rb +0 -102
  94. data/lib/active_support/core_ext/date_time/zones.rb +0 -17
  95. data/lib/active_support/core_ext/enumerable.rb +0 -119
  96. data/lib/active_support/core_ext/exception.rb +0 -3
  97. data/lib/active_support/core_ext/file.rb +0 -2
  98. data/lib/active_support/core_ext/file/atomic.rb +0 -41
  99. data/lib/active_support/core_ext/file/path.rb +0 -5
  100. data/lib/active_support/core_ext/float.rb +0 -1
  101. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  102. data/lib/active_support/core_ext/hash.rb +0 -8
  103. data/lib/active_support/core_ext/hash/conversions.rb +0 -150
  104. data/lib/active_support/core_ext/hash/deep_merge.rb +0 -16
  105. data/lib/active_support/core_ext/hash/diff.rb +0 -13
  106. data/lib/active_support/core_ext/hash/except.rb +0 -24
  107. data/lib/active_support/core_ext/hash/indifferent_access.rb +0 -14
  108. data/lib/active_support/core_ext/hash/keys.rb +0 -45
  109. data/lib/active_support/core_ext/hash/reverse_merge.rb +0 -28
  110. data/lib/active_support/core_ext/hash/slice.rb +0 -38
  111. data/lib/active_support/core_ext/integer.rb +0 -3
  112. data/lib/active_support/core_ext/integer/inflections.rb +0 -14
  113. data/lib/active_support/core_ext/integer/multiple.rb +0 -6
  114. data/lib/active_support/core_ext/integer/time.rb +0 -39
  115. data/lib/active_support/core_ext/kernel.rb +0 -5
  116. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  117. data/lib/active_support/core_ext/kernel/debugger.rb +0 -16
  118. data/lib/active_support/core_ext/kernel/reporting.rb +0 -62
  119. data/lib/active_support/core_ext/kernel/requires.rb +0 -26
  120. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -13
  121. data/lib/active_support/core_ext/load_error.rb +0 -23
  122. data/lib/active_support/core_ext/logger.rb +0 -146
  123. data/lib/active_support/core_ext/module.rb +0 -12
  124. data/lib/active_support/core_ext/module/aliasing.rb +0 -70
  125. data/lib/active_support/core_ext/module/anonymous.rb +0 -24
  126. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
  127. data/lib/active_support/core_ext/module/attr_internal.rb +0 -32
  128. data/lib/active_support/core_ext/module/attribute_accessors.rb +0 -66
  129. data/lib/active_support/core_ext/module/delegation.rb +0 -146
  130. data/lib/active_support/core_ext/module/deprecation.rb +0 -9
  131. data/lib/active_support/core_ext/module/introspection.rb +0 -88
  132. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  133. data/lib/active_support/core_ext/module/reachable.rb +0 -10
  134. data/lib/active_support/core_ext/module/remove_method.rb +0 -6
  135. data/lib/active_support/core_ext/module/synchronization.rb +0 -42
  136. data/lib/active_support/core_ext/name_error.rb +0 -18
  137. data/lib/active_support/core_ext/numeric.rb +0 -2
  138. data/lib/active_support/core_ext/numeric/bytes.rb +0 -44
  139. data/lib/active_support/core_ext/numeric/time.rb +0 -77
  140. data/lib/active_support/core_ext/object.rb +0 -14
  141. data/lib/active_support/core_ext/object/acts_like.rb +0 -10
  142. data/lib/active_support/core_ext/object/blank.rb +0 -76
  143. data/lib/active_support/core_ext/object/conversions.rb +0 -4
  144. data/lib/active_support/core_ext/object/duplicable.rb +0 -65
  145. data/lib/active_support/core_ext/object/extending.rb +0 -11
  146. data/lib/active_support/core_ext/object/instance_variables.rb +0 -67
  147. data/lib/active_support/core_ext/object/misc.rb +0 -2
  148. data/lib/active_support/core_ext/object/returning.rb +0 -42
  149. data/lib/active_support/core_ext/object/to_param.rb +0 -49
  150. data/lib/active_support/core_ext/object/to_query.rb +0 -27
  151. data/lib/active_support/core_ext/object/try.rb +0 -36
  152. data/lib/active_support/core_ext/object/with_options.rb +0 -26
  153. data/lib/active_support/core_ext/proc.rb +0 -14
  154. data/lib/active_support/core_ext/process.rb +0 -1
  155. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  156. data/lib/active_support/core_ext/range.rb +0 -4
  157. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  158. data/lib/active_support/core_ext/range/conversions.rb +0 -21
  159. data/lib/active_support/core_ext/range/include_range.rb +0 -21
  160. data/lib/active_support/core_ext/range/overlaps.rb +0 -8
  161. data/lib/active_support/core_ext/regexp.rb +0 -5
  162. data/lib/active_support/core_ext/rexml.rb +0 -46
  163. data/lib/active_support/core_ext/string.rb +0 -12
  164. data/lib/active_support/core_ext/string/access.rb +0 -99
  165. data/lib/active_support/core_ext/string/behavior.rb +0 -7
  166. data/lib/active_support/core_ext/string/conversions.rb +0 -61
  167. data/lib/active_support/core_ext/string/encoding.rb +0 -11
  168. data/lib/active_support/core_ext/string/exclude.rb +0 -6
  169. data/lib/active_support/core_ext/string/filters.rb +0 -49
  170. data/lib/active_support/core_ext/string/inflections.rb +0 -149
  171. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  172. data/lib/active_support/core_ext/string/multibyte.rb +0 -72
  173. data/lib/active_support/core_ext/string/output_safety.rb +0 -109
  174. data/lib/active_support/core_ext/string/starts_ends_with.rb +0 -4
  175. data/lib/active_support/core_ext/string/xchar.rb +0 -18
  176. data/lib/active_support/core_ext/time/acts_like.rb +0 -8
  177. data/lib/active_support/core_ext/time/calculations.rb +0 -282
  178. data/lib/active_support/core_ext/time/conversions.rb +0 -85
  179. data/lib/active_support/core_ext/time/marshal.rb +0 -56
  180. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  181. data/lib/active_support/core_ext/time/zones.rb +0 -78
  182. data/lib/active_support/core_ext/uri.rb +0 -22
  183. data/lib/active_support/dependencies.rb +0 -628
  184. data/lib/active_support/dependencies/autoload.rb +0 -50
  185. data/lib/active_support/deprecation.rb +0 -18
  186. data/lib/active_support/deprecation/behaviors.rb +0 -38
  187. data/lib/active_support/deprecation/method_wrappers.rb +0 -29
  188. data/lib/active_support/deprecation/proxy_wrappers.rb +0 -74
  189. data/lib/active_support/deprecation/reporting.rb +0 -56
  190. data/lib/active_support/duration.rb +0 -105
  191. data/lib/active_support/gzip.rb +0 -25
  192. data/lib/active_support/hash_with_indifferent_access.rb +0 -145
  193. data/lib/active_support/i18n.rb +0 -8
  194. data/lib/active_support/inflections.rb +0 -56
  195. data/lib/active_support/inflector.rb +0 -7
  196. data/lib/active_support/inflector/inflections.rb +0 -211
  197. data/lib/active_support/inflector/methods.rb +0 -141
  198. data/lib/active_support/inflector/transliterate.rb +0 -97
  199. data/lib/active_support/json.rb +0 -2
  200. data/lib/active_support/json/backends/jsongem.rb +0 -43
  201. data/lib/active_support/json/backends/yajl.rb +0 -40
  202. data/lib/active_support/json/backends/yaml.rb +0 -90
  203. data/lib/active_support/json/decoding.rb +0 -51
  204. data/lib/active_support/json/encoding.rb +0 -254
  205. data/lib/active_support/json/variable.rb +0 -11
  206. data/lib/active_support/lazy_load_hooks.rb +0 -27
  207. data/lib/active_support/locale/en.yml +0 -36
  208. data/lib/active_support/memoizable.rb +0 -103
  209. data/lib/active_support/message_encryptor.rb +0 -71
  210. data/lib/active_support/message_verifier.rb +0 -62
  211. data/lib/active_support/multibyte.rb +0 -44
  212. data/lib/active_support/multibyte/chars.rb +0 -480
  213. data/lib/active_support/multibyte/exceptions.rb +0 -8
  214. data/lib/active_support/multibyte/unicode.rb +0 -393
  215. data/lib/active_support/multibyte/utils.rb +0 -60
  216. data/lib/active_support/notifications.rb +0 -81
  217. data/lib/active_support/notifications/fanout.rb +0 -93
  218. data/lib/active_support/notifications/instrumenter.rb +0 -56
  219. data/lib/active_support/option_merger.rb +0 -25
  220. data/lib/active_support/ordered_hash.rb +0 -158
  221. data/lib/active_support/ordered_options.rb +0 -27
  222. data/lib/active_support/railtie.rb +0 -100
  223. data/lib/active_support/rescuable.rb +0 -114
  224. data/lib/active_support/ruby/shim.rb +0 -22
  225. data/lib/active_support/secure_random.rb +0 -199
  226. data/lib/active_support/string_inquirer.rb +0 -21
  227. data/lib/active_support/test_case.rb +0 -42
  228. data/lib/active_support/testing/assertions.rb +0 -82
  229. data/lib/active_support/testing/declarative.rb +0 -40
  230. data/lib/active_support/testing/default.rb +0 -9
  231. data/lib/active_support/testing/deprecation.rb +0 -55
  232. data/lib/active_support/testing/isolation.rb +0 -154
  233. data/lib/active_support/testing/pending.rb +0 -48
  234. data/lib/active_support/testing/performance.rb +0 -455
  235. data/lib/active_support/testing/setup_and_teardown.rb +0 -111
  236. data/lib/active_support/time.rb +0 -34
  237. data/lib/active_support/time/autoload.rb +0 -5
  238. data/lib/active_support/time_with_zone.rb +0 -341
  239. data/lib/active_support/values/time_zone.rb +0 -377
  240. data/lib/active_support/values/unicode_tables.dat +0 -0
  241. data/lib/active_support/version.rb +0 -10
  242. data/lib/active_support/whiny_nil.rb +0 -60
  243. data/lib/active_support/xml_mini.rb +0 -158
  244. data/lib/active_support/xml_mini/jdom.rb +0 -168
  245. data/lib/active_support/xml_mini/libxml.rb +0 -80
  246. data/lib/active_support/xml_mini/libxmlsax.rb +0 -85
  247. data/lib/active_support/xml_mini/nokogiri.rb +0 -78
  248. data/lib/active_support/xml_mini/nokogirisax.rb +0 -83
  249. data/lib/active_support/xml_mini/rexml.rb +0 -129
  250. data/lib/csd/extensions/core/file.rb +0 -14
  251. data/lib/csd/global_open_struct.rb +0 -19
  252. data/lib/csd/path.rb +0 -32
  253. data/lib/csd/ui.rb +0 -2
  254. data/lib/csd/ui/cli.rb +0 -8
  255. data/lib/csd/ui/ui.rb +0 -45
  256. data/lib/term/ansicolor.rb +0 -102
  257. data/lib/term/ansicolor/.keep +0 -0
  258. data/lib/term/ansicolor/version.rb +0 -10
@@ -1,10 +0,0 @@
1
- require 'date'
2
-
3
- class Time
4
- # Ruby 1.8-cvs and early 1.9 series define private Time#to_date
5
- %w(to_date to_datetime).each do |method|
6
- if private_instance_methods.include?(method) || private_instance_methods.include?(method.to_sym)
7
- public method
8
- end
9
- end
10
- end
@@ -1,78 +0,0 @@
1
- require 'active_support/time_with_zone'
2
-
3
- class Time
4
- class << self
5
- attr_accessor :zone_default
6
-
7
- # Returns the TimeZone for the current request, if this has been set (via Time.zone=).
8
- # If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
9
- def zone
10
- Thread.current[:time_zone] || zone_default
11
- end
12
-
13
- # Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
14
- #
15
- # This method accepts any of the following:
16
- #
17
- # * A Rails TimeZone object.
18
- # * An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
19
- # * A TZInfo::Timezone object.
20
- # * An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
21
- #
22
- # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis -- <tt>current_user.time_zone</tt>
23
- # just needs to return a string identifying the user's preferred TimeZone:
24
- #
25
- # class ApplicationController < ActionController::Base
26
- # before_filter :set_time_zone
27
- #
28
- # def set_time_zone
29
- # Time.zone = current_user.time_zone
30
- # end
31
- # end
32
- def zone=(time_zone)
33
- Thread.current[:time_zone] = get_zone(time_zone)
34
- end
35
-
36
- # Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
37
- def use_zone(time_zone)
38
- old_zone, ::Time.zone = ::Time.zone, get_zone(time_zone)
39
- yield
40
- ensure
41
- ::Time.zone = old_zone
42
- end
43
-
44
- # Returns <tt>Time.zone.now</tt> when <tt>config.time_zone</tt> is set, otherwise just returns <tt>Time.now</tt>.
45
- def current
46
- ::Time.zone_default ? ::Time.zone.now : ::Time.now
47
- end
48
-
49
- private
50
- def get_zone(time_zone)
51
- return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
52
- # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
53
- unless time_zone.respond_to?(:period_for_local)
54
- time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone) rescue nil
55
- end
56
- # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
57
- if time_zone
58
- time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
59
- end
60
- end
61
- end
62
-
63
- # Returns the simultaneous time in <tt>Time.zone</tt>.
64
- #
65
- # Time.zone = 'Hawaii' # => 'Hawaii'
66
- # Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
67
- #
68
- # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
69
- # instead of the operating system's time zone.
70
- #
71
- # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
72
- # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
73
- #
74
- # Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
75
- def in_time_zone(zone = ::Time.zone)
76
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
77
- end
78
- end
@@ -1,22 +0,0 @@
1
- # encoding: utf-8
2
-
3
- if RUBY_VERSION >= '1.9'
4
- require 'uri'
5
-
6
- str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
7
-
8
- parser = URI::Parser.new
9
-
10
- unless str == parser.unescape(parser.escape(str))
11
- URI::Parser.class_eval do
12
- remove_method :unescape
13
- def unescape(str, escaped = /%[a-fA-F\d]{2}/)
14
- # TODO: Are we actually sure that ASCII == UTF-8?
15
- # YK: My initial experiments say yes, but let's be sure please
16
- enc = str.encoding
17
- enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
18
- str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(enc)
19
- end
20
- end
21
- end
22
- end
@@ -1,628 +0,0 @@
1
- require 'set'
2
- require 'thread'
3
- require 'pathname'
4
- require 'active_support/core_ext/module/aliasing'
5
- require 'active_support/core_ext/module/attribute_accessors'
6
- require 'active_support/core_ext/module/introspection'
7
- require 'active_support/core_ext/module/anonymous'
8
- require 'active_support/core_ext/object/blank'
9
- require 'active_support/core_ext/load_error'
10
- require 'active_support/core_ext/name_error'
11
- require 'active_support/core_ext/string/starts_ends_with'
12
- require 'active_support/inflector'
13
-
14
- module ActiveSupport #:nodoc:
15
- module Dependencies #:nodoc:
16
- extend self
17
-
18
- # Should we turn on Ruby warnings on the first load of dependent files?
19
- mattr_accessor :warnings_on_first_load
20
- self.warnings_on_first_load = false
21
-
22
- # All files ever loaded.
23
- mattr_accessor :history
24
- self.history = Set.new
25
-
26
- # All files currently loaded.
27
- mattr_accessor :loaded
28
- self.loaded = Set.new
29
-
30
- # Should we load files or require them?
31
- mattr_accessor :mechanism
32
- self.mechanism = ENV['NO_RELOAD'] ? :require : :load
33
-
34
- # The set of directories from which we may automatically load files. Files
35
- # under these directories will be reloaded on each request in development mode,
36
- # unless the directory also appears in load_once_paths.
37
- mattr_accessor :load_paths
38
- self.load_paths = []
39
-
40
- # The set of directories from which automatically loaded constants are loaded
41
- # only once. All directories in this set must also be present in +load_paths+.
42
- mattr_accessor :load_once_paths
43
- self.load_once_paths = []
44
-
45
- # An array of qualified constant names that have been loaded. Adding a name to
46
- # this array will cause it to be unloaded the next time Dependencies are cleared.
47
- mattr_accessor :autoloaded_constants
48
- self.autoloaded_constants = []
49
-
50
- mattr_accessor :references
51
- self.references = {}
52
-
53
- # An array of constant names that need to be unloaded on every request. Used
54
- # to allow arbitrary constants to be marked for unloading.
55
- mattr_accessor :explicitly_unloadable_constants
56
- self.explicitly_unloadable_constants = []
57
-
58
- # The logger is used for generating information on the action run-time (including benchmarking) if available.
59
- # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
60
- mattr_accessor :logger
61
-
62
- # Set to true to enable logging of const_missing and file loads
63
- mattr_accessor :log_activity
64
- self.log_activity = false
65
-
66
- class WatchStack < Array
67
- def initialize
68
- @mutex = Mutex.new
69
- end
70
-
71
- def self.locked(*methods)
72
- methods.each { |m| class_eval "def #{m}(*) lock { super } end", __FILE__, __LINE__ }
73
- end
74
-
75
- def get(key)
76
- (val = assoc(key)) ? val[1] : []
77
- end
78
-
79
- locked :concat, :each, :delete_if, :<<
80
-
81
- def new_constants_for(frames)
82
- constants = []
83
- frames.each do |mod_name, prior_constants|
84
- mod = Inflector.constantize(mod_name) if Dependencies.qualified_const_defined?(mod_name)
85
- next unless mod.is_a?(Module)
86
-
87
- new_constants = mod.local_constant_names - prior_constants
88
- get(mod_name).concat(new_constants)
89
-
90
- new_constants.each do |suffix|
91
- constants << ([mod_name, suffix] - ["Object"]).join("::")
92
- end
93
- end
94
- constants
95
- end
96
-
97
- # Add a set of modules to the watch stack, remembering the initial constants
98
- def add_modules(modules)
99
- list = modules.map do |desc|
100
- name = Dependencies.to_constant_name(desc)
101
- consts = Dependencies.qualified_const_defined?(name) ?
102
- Inflector.constantize(name).local_constant_names : []
103
- [name, consts]
104
- end
105
- concat(list)
106
- list
107
- end
108
-
109
- def lock
110
- @mutex.synchronize { yield self }
111
- end
112
- end
113
-
114
- # An internal stack used to record which constants are loaded by any block.
115
- mattr_accessor :constant_watch_stack
116
- self.constant_watch_stack = WatchStack.new
117
-
118
- # Module includes this module
119
- module ModuleConstMissing #:nodoc:
120
- def self.append_features(base)
121
- base.class_eval do
122
- # Emulate #exclude via an ivar
123
- return if defined?(@_const_missing) && @_const_missing
124
- @_const_missing = instance_method(:const_missing)
125
- remove_method(:const_missing)
126
- end
127
- super
128
- end
129
-
130
- def self.exclude_from(base)
131
- base.class_eval do
132
- define_method :const_missing, @_const_missing
133
- @_const_missing = nil
134
- end
135
- end
136
-
137
- # Use const_missing to autoload associations so we don't have to
138
- # require_association when using single-table inheritance.
139
- def const_missing(const_name, nesting = nil)
140
- klass_name = name.presence || "Object"
141
-
142
- if !nesting
143
- # We'll assume that the nesting of Foo::Bar is ["Foo::Bar", "Foo"]
144
- # even though it might not be, such as in the case of
145
- # class Foo::Bar; Baz; end
146
- nesting = []
147
- klass_name.to_s.scan(/::|$/) { nesting.unshift $` }
148
- end
149
-
150
- # If there are multiple levels of nesting to search under, the top
151
- # level is the one we want to report as the lookup fail.
152
- error = nil
153
-
154
- nesting.each do |namespace|
155
- begin
156
- return Dependencies.load_missing_constant namespace.constantize, const_name
157
- rescue NoMethodError then raise
158
- rescue NameError => e
159
- error ||= e
160
- end
161
- end
162
-
163
- # Raise the first error for this set. If this const_missing came from an
164
- # earlier const_missing, this will result in the real error bubbling
165
- # all the way up
166
- raise error
167
- end
168
-
169
- def unloadable(const_desc = self)
170
- super(const_desc)
171
- end
172
- end
173
-
174
- # Object includes this module
175
- module Loadable #:nodoc:
176
- def self.exclude_from(base)
177
- base.class_eval { define_method(:load, Kernel.instance_method(:load)) }
178
- end
179
-
180
- def require_or_load(file_name)
181
- Dependencies.require_or_load(file_name)
182
- end
183
-
184
- def require_dependency(file_name, message = "No such file to load -- %s")
185
- unless file_name.is_a?(String)
186
- raise ArgumentError, "the file name must be a String -- you passed #{file_name.inspect}"
187
- end
188
-
189
- Dependencies.depend_on(file_name, false, message)
190
- end
191
-
192
- def require_association(file_name)
193
- Dependencies.associate_with(file_name)
194
- end
195
-
196
- def load_dependency(file)
197
- if Dependencies.load?
198
- Dependencies.new_constants_in(Object) { yield }.presence
199
- else
200
- yield
201
- end
202
- rescue Exception => exception # errors from loading file
203
- exception.blame_file! file
204
- raise
205
- end
206
-
207
- def load(file, *)
208
- load_dependency(file) { super }
209
- end
210
-
211
- def require(file, *)
212
- load_dependency(file) { super }
213
- end
214
-
215
- # Mark the given constant as unloadable. Unloadable constants are removed each
216
- # time dependencies are cleared.
217
- #
218
- # Note that marking a constant for unloading need only be done once. Setup
219
- # or init scripts may list each unloadable constant that may need unloading;
220
- # each constant will be removed for every subsequent clear, as opposed to for
221
- # the first clear.
222
- #
223
- # The provided constant descriptor may be a (non-anonymous) module or class,
224
- # or a qualified constant name as a string or symbol.
225
- #
226
- # Returns true if the constant was not previously marked for unloading, false
227
- # otherwise.
228
- def unloadable(const_desc)
229
- Dependencies.mark_for_unload const_desc
230
- end
231
- end
232
-
233
- # Exception file-blaming
234
- module Blamable #:nodoc:
235
- def blame_file!(file)
236
- (@blamed_files ||= []).unshift file
237
- end
238
-
239
- def blamed_files
240
- @blamed_files ||= []
241
- end
242
-
243
- def describe_blame
244
- return nil if blamed_files.empty?
245
- "This error occurred while loading the following files:\n #{blamed_files.join "\n "}"
246
- end
247
-
248
- def copy_blame!(exc)
249
- @blamed_files = exc.blamed_files.clone
250
- self
251
- end
252
- end
253
-
254
- def hook!
255
- Object.class_eval { include Loadable }
256
- Module.class_eval { include ModuleConstMissing }
257
- Exception.class_eval { include Blamable }
258
- true
259
- end
260
-
261
- def unhook!
262
- ModuleConstMissing.exclude_from(Module)
263
- Loadable.exclude_from(Object)
264
- true
265
- end
266
-
267
- def load?
268
- mechanism == :load
269
- end
270
-
271
- def depend_on(file_name, swallow_load_errors = false, message = "No such file to load -- %s.rb")
272
- path = search_for_file(file_name)
273
- require_or_load(path || file_name)
274
- rescue LoadError => load_error
275
- unless swallow_load_errors
276
- if file_name = load_error.message[/ -- (.*?)(\.rb)?$/, 1]
277
- raise LoadError.new(message % file_name).copy_blame!(load_error)
278
- end
279
- raise
280
- end
281
- end
282
-
283
- def associate_with(file_name)
284
- depend_on(file_name, true)
285
- end
286
-
287
- def clear
288
- log_call
289
- loaded.clear
290
- remove_unloadable_constants!
291
- end
292
-
293
- def require_or_load(file_name, const_path = nil)
294
- log_call file_name, const_path
295
- file_name = $1 if file_name =~ /^(.*)\.rb$/
296
- expanded = File.expand_path(file_name)
297
- return if loaded.include?(expanded)
298
-
299
- # Record that we've seen this file *before* loading it to avoid an
300
- # infinite loop with mutual dependencies.
301
- loaded << expanded
302
-
303
- begin
304
- if load?
305
- log "loading #{file_name}"
306
-
307
- # Enable warnings iff this file has not been loaded before and
308
- # warnings_on_first_load is set.
309
- load_args = ["#{file_name}.rb"]
310
- load_args << const_path unless const_path.nil?
311
-
312
- if !warnings_on_first_load or history.include?(expanded)
313
- result = load_file(*load_args)
314
- else
315
- enable_warnings { result = load_file(*load_args) }
316
- end
317
- else
318
- log "requiring #{file_name}"
319
- result = require file_name
320
- end
321
- rescue Exception
322
- loaded.delete expanded
323
- raise
324
- end
325
-
326
- # Record history *after* loading so first load gets warnings.
327
- history << expanded
328
- return result
329
- end
330
-
331
- # Is the provided constant path defined?
332
- def qualified_const_defined?(path)
333
- names = path.sub(/^::/, '').to_s.split('::')
334
-
335
- names.inject(Object) do |mod, name|
336
- return false unless local_const_defined?(mod, name)
337
- mod.const_get name
338
- end
339
- end
340
-
341
- if Module.method(:const_defined?).arity == 1
342
- # Does this module define this constant?
343
- # Wrapper to accomodate changing Module#const_defined? in Ruby 1.9
344
- def local_const_defined?(mod, const)
345
- mod.const_defined?(const)
346
- end
347
- else
348
- def local_const_defined?(mod, const) #:nodoc:
349
- mod.const_defined?(const, false)
350
- end
351
- end
352
-
353
- # Given +path+, a filesystem path to a ruby file, return an array of constant
354
- # paths which would cause Dependencies to attempt to load this file.
355
- def loadable_constants_for_path(path, bases = load_paths)
356
- expanded_path = Pathname.new(path[/\A(.*?)(\.rb)?\Z/, 1]).expand_path
357
-
358
- bases.inject([]) do |paths, root|
359
- expanded_root = Pathname.new(root).expand_path
360
- nesting = expanded_path.relative_path_from(expanded_root).to_s
361
- next paths if nesting =~ /\.\./
362
- paths << nesting.camelize
363
- end.uniq
364
- end
365
-
366
- # Search for a file in load_paths matching the provided suffix.
367
- def search_for_file(path_suffix)
368
- path_suffix = path_suffix.sub(/(\.rb)?$/, ".rb")
369
-
370
- load_paths.each do |root|
371
- path = File.join(root, path_suffix)
372
- return path if File.file? path
373
- end
374
- nil # Gee, I sure wish we had first_match ;-)
375
- end
376
-
377
- # Does the provided path_suffix correspond to an autoloadable module?
378
- # Instead of returning a boolean, the autoload base for this module is returned.
379
- def autoloadable_module?(path_suffix)
380
- load_paths.each do |load_path|
381
- return load_path if File.directory? File.join(load_path, path_suffix)
382
- end
383
- nil
384
- end
385
-
386
- def load_once_path?(path)
387
- load_once_paths.any? { |base| path.starts_with? base }
388
- end
389
-
390
- # Attempt to autoload the provided module name by searching for a directory
391
- # matching the expect path suffix. If found, the module is created and assigned
392
- # to +into+'s constants with the name +const_name+. Provided that the directory
393
- # was loaded from a reloadable base path, it is added to the set of constants
394
- # that are to be unloaded.
395
- def autoload_module!(into, const_name, qualified_name, path_suffix)
396
- return nil unless base_path = autoloadable_module?(path_suffix)
397
- mod = Module.new
398
- into.const_set const_name, mod
399
- autoloaded_constants << qualified_name unless load_once_paths.include?(base_path)
400
- return mod
401
- end
402
-
403
- # Load the file at the provided path. +const_paths+ is a set of qualified
404
- # constant names. When loading the file, Dependencies will watch for the
405
- # addition of these constants. Each that is defined will be marked as
406
- # autoloaded, and will be removed when Dependencies.clear is next called.
407
- #
408
- # If the second parameter is left off, then Dependencies will construct a set
409
- # of names that the file at +path+ may define. See
410
- # +loadable_constants_for_path+ for more details.
411
- def load_file(path, const_paths = loadable_constants_for_path(path))
412
- log_call path, const_paths
413
- const_paths = [const_paths].compact unless const_paths.is_a? Array
414
- parent_paths = const_paths.collect { |const_path| /(.*)::[^:]+\Z/ =~ const_path ? $1 : :Object }
415
-
416
- result = nil
417
- newly_defined_paths = new_constants_in(*parent_paths) do
418
- result = Kernel.load path
419
- end
420
-
421
- autoloaded_constants.concat newly_defined_paths unless load_once_path?(path)
422
- autoloaded_constants.uniq!
423
- log "loading #{path} defined #{newly_defined_paths * ', '}" unless newly_defined_paths.empty?
424
- return result
425
- end
426
-
427
- # Return the constant path for the provided parent and constant name.
428
- def qualified_name_for(mod, name)
429
- mod_name = to_constant_name mod
430
- mod_name == "Object" ? name.to_s : "#{mod_name}::#{name}"
431
- end
432
-
433
- # Load the constant named +const_name+ which is missing from +from_mod+. If
434
- # it is not possible to load the constant into from_mod, try its parent module
435
- # using const_missing.
436
- def load_missing_constant(from_mod, const_name)
437
- log_call from_mod, const_name
438
-
439
- unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).equal?(from_mod)
440
- raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
441
- end
442
-
443
- raise ArgumentError, "#{from_mod} is not missing constant #{const_name}!" if local_const_defined?(from_mod, const_name)
444
-
445
- qualified_name = qualified_name_for from_mod, const_name
446
- path_suffix = qualified_name.underscore
447
-
448
- trace = caller.reject {|l| l =~ %r{#{Regexp.escape(__FILE__)}}}
449
- name_error = NameError.new("uninitialized constant #{qualified_name}")
450
- name_error.set_backtrace(trace)
451
-
452
- file_path = search_for_file(path_suffix)
453
-
454
- if file_path && ! loaded.include?(File.expand_path(file_path)) # We found a matching file to load
455
- require_or_load file_path
456
- raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless local_const_defined?(from_mod, const_name)
457
- return from_mod.const_get(const_name)
458
- elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
459
- return mod
460
- elsif (parent = from_mod.parent) && parent != from_mod &&
461
- ! from_mod.parents.any? { |p| local_const_defined?(p, const_name) }
462
- # If our parents do not have a constant named +const_name+ then we are free
463
- # to attempt to load upwards. If they do have such a constant, then this
464
- # const_missing must be due to from_mod::const_name, which should not
465
- # return constants from from_mod's parents.
466
- begin
467
- return parent.const_missing(const_name)
468
- rescue NameError => e
469
- raise unless e.missing_name? qualified_name_for(parent, const_name)
470
- raise name_error
471
- end
472
- else
473
- raise name_error
474
- end
475
- end
476
-
477
- # Remove the constants that have been autoloaded, and those that have been
478
- # marked for unloading.
479
- def remove_unloadable_constants!
480
- autoloaded_constants.each { |const| remove_constant const }
481
- autoloaded_constants.clear
482
- Reference.clear!
483
- explicitly_unloadable_constants.each { |const| remove_constant const }
484
- end
485
-
486
- class Reference
487
- @@constants = Hash.new { |h, k| h[k] = Inflector.constantize(k) }
488
-
489
- attr_reader :name
490
-
491
- def initialize(name)
492
- @name = name.to_s
493
- @@constants[@name] = name if name.respond_to?(:name)
494
- end
495
-
496
- def get
497
- @@constants[@name]
498
- end
499
-
500
- def self.clear!
501
- @@constants.clear
502
- end
503
- end
504
-
505
- def ref(name)
506
- references[name] ||= Reference.new(name)
507
- end
508
-
509
- def constantize(name)
510
- ref(name).get
511
- end
512
-
513
- # Determine if the given constant has been automatically loaded.
514
- def autoloaded?(desc)
515
- # No name => anonymous module.
516
- return false if desc.is_a?(Module) && desc.anonymous?
517
- name = to_constant_name desc
518
- return false unless qualified_const_defined? name
519
- return autoloaded_constants.include?(name)
520
- end
521
-
522
- # Will the provided constant descriptor be unloaded?
523
- def will_unload?(const_desc)
524
- autoloaded?(const_desc) ||
525
- explicitly_unloadable_constants.include?(to_constant_name(const_desc))
526
- end
527
-
528
- # Mark the provided constant name for unloading. This constant will be
529
- # unloaded on each request, not just the next one.
530
- def mark_for_unload(const_desc)
531
- name = to_constant_name const_desc
532
- if explicitly_unloadable_constants.include? name
533
- return false
534
- else
535
- explicitly_unloadable_constants << name
536
- return true
537
- end
538
- end
539
-
540
- # Run the provided block and detect the new constants that were loaded during
541
- # its execution. Constants may only be regarded as 'new' once -- so if the
542
- # block calls +new_constants_in+ again, then the constants defined within the
543
- # inner call will not be reported in this one.
544
- #
545
- # If the provided block does not run to completion, and instead raises an
546
- # exception, any new constants are regarded as being only partially defined
547
- # and will be removed immediately.
548
- def new_constants_in(*descs)
549
- log_call(*descs)
550
- watch_frames = constant_watch_stack.add_modules(descs)
551
-
552
- aborting = true
553
- begin
554
- yield # Now yield to the code that is to define new constants.
555
- aborting = false
556
- ensure
557
- new_constants = constant_watch_stack.new_constants_for(watch_frames)
558
-
559
- log "New constants: #{new_constants * ', '}"
560
- return new_constants unless aborting
561
-
562
- log "Error during loading, removing partially loaded constants "
563
- new_constants.each {|c| remove_constant(c) }.clear
564
- end
565
-
566
- return []
567
- ensure
568
- # Remove the stack frames that we added.
569
- watch_frames.each {|f| constant_watch_stack.delete(f) } if watch_frames.present?
570
- end
571
-
572
- class LoadingModule #:nodoc:
573
- # Old style environment.rb referenced this method directly. Please note, it doesn't
574
- # actually *do* anything any more.
575
- def self.root(*args)
576
- if defined?(Rails) && Rails.logger
577
- Rails.logger.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases."
578
- Rails.logger.warn "For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19"
579
- end
580
- end
581
- end
582
-
583
- # Convert the provided const desc to a qualified constant name (as a string).
584
- # A module, class, symbol, or string may be provided.
585
- def to_constant_name(desc) #:nodoc:
586
- name = case desc
587
- when String then desc.sub(/^::/, '')
588
- when Symbol then desc.to_s
589
- when Module
590
- desc.name.presence ||
591
- raise(ArgumentError, "Anonymous modules have no name to be referenced by")
592
- else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
593
- end
594
- end
595
-
596
- def remove_constant(const) #:nodoc:
597
- return false unless qualified_const_defined? const
598
-
599
- # Normalize ::Foo, Foo, Object::Foo, and ::Object::Foo to Object::Foo
600
- names = const.to_s.sub(/^::(Object)?/, 'Object::').split("::")
601
- to_remove = names.pop
602
- parent = Inflector.constantize(names * '::')
603
-
604
- log "removing constant #{const}"
605
- parent.instance_eval { remove_const to_remove }
606
-
607
- return true
608
- end
609
-
610
- protected
611
- def log_call(*args)
612
- if logger && log_activity
613
- arg_str = args.collect { |arg| arg.inspect } * ', '
614
- /in `([a-z_\?\!]+)'/ =~ caller(1).first
615
- selector = $1 || '<unknown>'
616
- log "called #{selector}(#{arg_str})"
617
- end
618
- end
619
-
620
- def log(msg)
621
- if logger && log_activity
622
- logger.debug "Dependencies: #{msg}"
623
- end
624
- end
625
- end
626
- end
627
-
628
- ActiveSupport::Dependencies.hook!