bundler 2.0.0.pre.1 → 2.1.0.pre.3

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

Potentially problematic release.


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

Files changed (230) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +774 -574
  3. data/LICENSE.md +18 -19
  4. data/README.md +9 -8
  5. data/bundler.gemspec +12 -23
  6. data/exe/bundle +19 -3
  7. data/lib/bundler.rb +203 -87
  8. data/lib/bundler/build_metadata.rb +14 -7
  9. data/lib/bundler/capistrano.rb +5 -5
  10. data/lib/bundler/cli.rb +181 -143
  11. data/lib/bundler/cli/add.rb +28 -16
  12. data/lib/bundler/cli/cache.rb +25 -13
  13. data/lib/bundler/cli/common.rb +11 -12
  14. data/lib/bundler/cli/config.rb +161 -86
  15. data/lib/bundler/cli/console.rb +2 -2
  16. data/lib/bundler/cli/doctor.rb +4 -4
  17. data/lib/bundler/cli/exec.rb +4 -16
  18. data/lib/bundler/cli/gem.rb +5 -5
  19. data/lib/bundler/cli/info.rb +17 -5
  20. data/lib/bundler/cli/init.rb +1 -1
  21. data/lib/bundler/cli/install.rb +12 -11
  22. data/lib/bundler/cli/issue.rb +3 -3
  23. data/lib/bundler/cli/open.rb +10 -6
  24. data/lib/bundler/cli/outdated.rb +85 -81
  25. data/lib/bundler/cli/plugin.rb +9 -2
  26. data/lib/bundler/cli/pristine.rb +1 -1
  27. data/lib/bundler/cli/show.rb +1 -1
  28. data/lib/bundler/cli/update.rb +32 -12
  29. data/lib/bundler/compact_index_client.rb +25 -9
  30. data/lib/bundler/compact_index_client/updater.rb +2 -6
  31. data/lib/bundler/current_ruby.rb +9 -7
  32. data/lib/bundler/definition.rb +36 -27
  33. data/lib/bundler/dependency.rb +16 -4
  34. data/lib/bundler/deployment.rb +2 -2
  35. data/lib/bundler/dsl.rb +18 -42
  36. data/lib/bundler/env.rb +8 -13
  37. data/lib/bundler/environment_preserver.rb +0 -1
  38. data/lib/bundler/feature_flag.rb +1 -11
  39. data/lib/bundler/fetcher.rb +14 -11
  40. data/lib/bundler/fetcher/compact_index.rb +26 -12
  41. data/lib/bundler/fetcher/dependency.rb +1 -1
  42. data/lib/bundler/fetcher/downloader.rb +4 -1
  43. data/lib/bundler/fetcher/index.rb +4 -2
  44. data/lib/bundler/friendly_errors.rb +5 -6
  45. data/lib/bundler/gem_helper.rb +38 -25
  46. data/lib/bundler/gem_helpers.rb +2 -4
  47. data/lib/bundler/gem_tasks.rb +1 -1
  48. data/lib/bundler/gem_version_promoter.rb +3 -3
  49. data/lib/bundler/graph.rb +2 -2
  50. data/lib/bundler/injector.rb +10 -8
  51. data/lib/bundler/inline.rb +25 -20
  52. data/lib/bundler/installer.rb +7 -14
  53. data/lib/bundler/installer/gem_installer.rb +5 -1
  54. data/lib/bundler/installer/parallel_installer.rb +4 -8
  55. data/lib/bundler/installer/standalone.rb +1 -2
  56. data/lib/bundler/lazy_specification.rb +2 -2
  57. data/lib/bundler/lockfile_parser.rb +14 -21
  58. data/lib/bundler/match_platform.rb +1 -1
  59. data/lib/bundler/plugin.rb +42 -29
  60. data/lib/bundler/plugin/api.rb +1 -1
  61. data/lib/bundler/plugin/api/source.rb +2 -2
  62. data/lib/bundler/plugin/index.rb +14 -3
  63. data/lib/bundler/plugin/installer.rb +28 -15
  64. data/lib/bundler/psyched_yaml.rb +1 -1
  65. data/lib/bundler/resolver.rb +72 -24
  66. data/lib/bundler/resolver/spec_group.rb +3 -2
  67. data/lib/bundler/retry.rb +2 -2
  68. data/lib/bundler/ruby_version.rb +4 -19
  69. data/lib/bundler/rubygems_ext.rb +11 -67
  70. data/lib/bundler/rubygems_gem_installer.rb +1 -1
  71. data/lib/bundler/rubygems_integration.rb +143 -395
  72. data/lib/bundler/runtime.rb +2 -9
  73. data/lib/bundler/settings.rb +15 -48
  74. data/lib/bundler/setup.rb +7 -13
  75. data/lib/bundler/shared_helpers.rb +57 -73
  76. data/lib/bundler/similarity_detector.rb +2 -2
  77. data/lib/bundler/source.rb +5 -5
  78. data/lib/bundler/source/git.rb +19 -12
  79. data/lib/bundler/source/git/git_proxy.rb +36 -40
  80. data/lib/bundler/source/metadata.rb +9 -5
  81. data/lib/bundler/source/path.rb +13 -8
  82. data/lib/bundler/source/rubygems.rb +11 -5
  83. data/lib/bundler/source/rubygems/remote.rb +1 -2
  84. data/lib/bundler/source_list.rb +9 -12
  85. data/lib/bundler/spec_set.rb +23 -12
  86. data/lib/bundler/stub_specification.rb +18 -30
  87. data/lib/bundler/templates/Executable.bundler +23 -14
  88. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +3 -3
  89. data/lib/bundler/templates/newgem/Gemfile.tt +8 -2
  90. data/lib/bundler/templates/newgem/README.md.tt +4 -3
  91. data/lib/bundler/templates/newgem/newgem.gemspec.tt +6 -27
  92. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +1 -1
  93. data/lib/bundler/templates/newgem/travis.yml.tt +0 -1
  94. data/lib/bundler/ui.rb +3 -3
  95. data/lib/bundler/ui/rg_proxy.rb +1 -1
  96. data/lib/bundler/ui/shell.rb +4 -8
  97. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +161 -0
  98. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +66 -0
  99. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +176 -0
  100. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +3 -0
  101. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +273 -147
  102. data/lib/bundler/vendor/fileutils/lib/fileutils/version.rb +5 -0
  103. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +6 -6
  104. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -2
  105. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -1
  106. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -1
  107. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -1
  108. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -1
  109. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +6 -6
  110. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -1
  111. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -1
  112. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +30 -8
  113. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +1 -1
  114. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +4 -4
  115. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +2 -2
  116. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +248 -279
  117. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +40 -0
  118. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +53 -0
  119. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +79 -0
  120. data/lib/bundler/vendor/thor/lib/thor.rb +12 -4
  121. data/lib/bundler/vendor/thor/lib/thor/actions.rb +22 -11
  122. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +1 -1
  123. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +1 -1
  124. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +7 -17
  125. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +16 -7
  126. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +19 -8
  127. data/lib/bundler/vendor/thor/lib/thor/base.rb +25 -24
  128. data/lib/bundler/vendor/thor/lib/thor/command.rb +21 -14
  129. data/lib/bundler/vendor/thor/lib/thor/error.rb +78 -0
  130. data/lib/bundler/vendor/thor/lib/thor/group.rb +3 -3
  131. data/lib/bundler/vendor/thor/lib/thor/invocation.rb +1 -0
  132. data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +2 -2
  133. data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +1 -1
  134. data/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +6 -6
  135. data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -4
  136. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +1 -1
  137. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +8 -6
  138. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +20 -5
  139. data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +1 -0
  140. data/lib/bundler/vendor/thor/lib/thor/runner.rb +8 -6
  141. data/lib/bundler/vendor/thor/lib/thor/shell.rb +4 -4
  142. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +52 -7
  143. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +6 -2
  144. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +1 -1
  145. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  146. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  147. data/lib/bundler/vendored_fileutils.rb +1 -6
  148. data/lib/bundler/vendored_molinillo.rb +1 -1
  149. data/lib/bundler/vendored_persistent.rb +7 -5
  150. data/lib/bundler/vendored_thor.rb +2 -2
  151. data/lib/bundler/version.rb +1 -20
  152. data/lib/bundler/version_ranges.rb +51 -5
  153. data/lib/bundler/vlad.rb +3 -3
  154. data/lib/bundler/worker.rb +1 -3
  155. data/lib/bundler/yaml_serializer.rb +2 -3
  156. data/man/bundle-add.1 +10 -2
  157. data/man/bundle-add.1.txt +11 -5
  158. data/man/bundle-add.ronn +7 -1
  159. data/man/bundle-binstubs.1 +2 -2
  160. data/man/bundle-binstubs.1.txt +2 -2
  161. data/man/bundle-binstubs.ronn +1 -1
  162. data/man/bundle-cache.1 +55 -0
  163. data/man/bundle-cache.1.txt +78 -0
  164. data/man/{bundle-package.ronn → bundle-cache.ronn} +15 -15
  165. data/man/bundle-check.1 +1 -1
  166. data/man/bundle-check.1.txt +6 -6
  167. data/man/bundle-clean.1 +1 -1
  168. data/man/bundle-clean.1.txt +1 -1
  169. data/man/bundle-config.1 +36 -36
  170. data/man/bundle-config.1.txt +66 -67
  171. data/man/bundle-config.ronn +42 -40
  172. data/man/bundle-doctor.1 +1 -1
  173. data/man/bundle-doctor.1.txt +1 -1
  174. data/man/bundle-exec.1 +2 -2
  175. data/man/bundle-exec.1.txt +2 -2
  176. data/man/bundle-exec.ronn +1 -1
  177. data/man/bundle-gem.1 +1 -1
  178. data/man/bundle-gem.1.txt +3 -3
  179. data/man/bundle-info.1 +1 -1
  180. data/man/bundle-info.1.txt +1 -1
  181. data/man/bundle-init.1 +2 -2
  182. data/man/bundle-init.1.txt +2 -2
  183. data/man/bundle-init.ronn +1 -1
  184. data/man/bundle-inject.1 +1 -1
  185. data/man/bundle-inject.1.txt +1 -1
  186. data/man/bundle-install.1 +8 -5
  187. data/man/bundle-install.1.txt +56 -51
  188. data/man/bundle-install.ronn +9 -4
  189. data/man/bundle-list.1 +1 -1
  190. data/man/bundle-list.1.txt +1 -1
  191. data/man/bundle-lock.1 +1 -1
  192. data/man/bundle-lock.1.txt +16 -16
  193. data/man/bundle-open.1 +1 -1
  194. data/man/bundle-open.1.txt +1 -1
  195. data/man/bundle-outdated.1 +1 -1
  196. data/man/bundle-outdated.1.txt +1 -1
  197. data/man/bundle-platform.1 +1 -1
  198. data/man/bundle-platform.1.txt +1 -1
  199. data/man/bundle-pristine.1 +1 -1
  200. data/man/bundle-pristine.1.txt +1 -1
  201. data/man/bundle-remove.1 +1 -1
  202. data/man/bundle-remove.1.txt +1 -1
  203. data/man/bundle-show.1 +1 -1
  204. data/man/bundle-show.1.txt +1 -1
  205. data/man/bundle-update.1 +4 -4
  206. data/man/bundle-update.1.txt +64 -65
  207. data/man/bundle-update.ronn +3 -3
  208. data/man/bundle-viz.1 +1 -1
  209. data/man/bundle-viz.1.txt +1 -1
  210. data/man/bundle.1 +7 -3
  211. data/man/bundle.1.txt +11 -8
  212. data/man/bundle.ronn +5 -2
  213. data/man/gemfile.5 +17 -20
  214. data/man/gemfile.5.ronn +14 -18
  215. data/man/gemfile.5.txt +108 -112
  216. data/man/index.txt +1 -1
  217. metadata +19 -107
  218. data/exe/bundle_ruby +0 -60
  219. data/lib/bundler/cli/package.rb +0 -49
  220. data/lib/bundler/compatibility_guard.rb +0 -14
  221. data/lib/bundler/ssl_certs/.document +0 -1
  222. data/lib/bundler/ssl_certs/certificate_manager.rb +0 -66
  223. data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +0 -21
  224. data/lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +0 -23
  225. data/lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +0 -25
  226. data/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb +0 -27
  227. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb +0 -129
  228. data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +0 -129
  229. data/man/bundle-package.1 +0 -55
  230. data/man/bundle-package.1.txt +0 -79
@@ -0,0 +1,66 @@
1
+ # Global monotonic clock from Concurrent Ruby 1.0.
2
+ # Copyright (c) Jerry D'Antonio -- released under the MIT license.
3
+ # Slightly modified; used with permission.
4
+ # https://github.com/ruby-concurrency/concurrent-ruby
5
+
6
+ require 'thread'
7
+
8
+ class Bundler::ConnectionPool
9
+
10
+ class_definition = Class.new do
11
+
12
+ if defined?(Process::CLOCK_MONOTONIC)
13
+
14
+ # @!visibility private
15
+ def get_time
16
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
17
+ end
18
+
19
+ elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
20
+
21
+ # @!visibility private
22
+ def get_time
23
+ java.lang.System.nanoTime() / 1_000_000_000.0
24
+ end
25
+
26
+ else
27
+
28
+ # @!visibility private
29
+ def initialize
30
+ @mutex = Mutex.new
31
+ @last_time = Time.now.to_f
32
+ end
33
+
34
+ # @!visibility private
35
+ def get_time
36
+ @mutex.synchronize do
37
+ now = Time.now.to_f
38
+ if @last_time < now
39
+ @last_time = now
40
+ else # clock has moved back in time
41
+ @last_time += 0.000_001
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ ##
49
+ # Clock that cannot be set and represents monotonic time since
50
+ # some unspecified starting point.
51
+ #
52
+ # @!visibility private
53
+ GLOBAL_MONOTONIC_CLOCK = class_definition.new
54
+ private_constant :GLOBAL_MONOTONIC_CLOCK
55
+
56
+ class << self
57
+ ##
58
+ # Returns the current time a tracked by the application monotonic clock.
59
+ #
60
+ # @return [Float] The current monotonic time when `since` not given else
61
+ # the elapsed monotonic time between `since` and the current time
62
+ def monotonic_time
63
+ GLOBAL_MONOTONIC_CLOCK.get_time
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,176 @@
1
+ require 'thread'
2
+ require 'timeout'
3
+ require_relative 'monotonic_time'
4
+
5
+ ##
6
+ # Raised when you attempt to retrieve a connection from a pool that has been
7
+ # shut down.
8
+
9
+ class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end
10
+
11
+ ##
12
+ # The TimedStack manages a pool of homogeneous connections (or any resource
13
+ # you wish to manage). Connections are created lazily up to a given maximum
14
+ # number.
15
+
16
+ # Examples:
17
+ #
18
+ # ts = TimedStack.new(1) { MyConnection.new }
19
+ #
20
+ # # fetch a connection
21
+ # conn = ts.pop
22
+ #
23
+ # # return a connection
24
+ # ts.push conn
25
+ #
26
+ # conn = ts.pop
27
+ # ts.pop timeout: 5
28
+ # #=> raises Timeout::Error after 5 seconds
29
+
30
+ class Bundler::ConnectionPool::TimedStack
31
+ attr_reader :max
32
+
33
+ ##
34
+ # Creates a new pool with +size+ connections that are created from the given
35
+ # +block+.
36
+
37
+ def initialize(size = 0, &block)
38
+ @create_block = block
39
+ @created = 0
40
+ @que = []
41
+ @max = size
42
+ @mutex = Mutex.new
43
+ @resource = ConditionVariable.new
44
+ @shutdown_block = nil
45
+ end
46
+
47
+ ##
48
+ # Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
49
+ # used by subclasses that extend TimedStack.
50
+
51
+ def push(obj, options = {})
52
+ @mutex.synchronize do
53
+ if @shutdown_block
54
+ @shutdown_block.call(obj)
55
+ else
56
+ store_connection obj, options
57
+ end
58
+
59
+ @resource.broadcast
60
+ end
61
+ end
62
+ alias_method :<<, :push
63
+
64
+ ##
65
+ # Retrieves a connection from the stack. If a connection is available it is
66
+ # immediately returned. If no connection is available within the given
67
+ # timeout a Timeout::Error is raised.
68
+ #
69
+ # +:timeout+ is the only checked entry in +options+ and is preferred over
70
+ # the +timeout+ argument (which will be removed in a future release). Other
71
+ # options may be used by subclasses that extend TimedStack.
72
+
73
+ def pop(timeout = 0.5, options = {})
74
+ options, timeout = timeout, 0.5 if Hash === timeout
75
+ timeout = options.fetch :timeout, timeout
76
+
77
+ deadline = Bundler::ConnectionPool.monotonic_time + timeout
78
+ @mutex.synchronize do
79
+ loop do
80
+ raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
81
+ return fetch_connection(options) if connection_stored?(options)
82
+
83
+ connection = try_create(options)
84
+ return connection if connection
85
+
86
+ to_wait = deadline - Bundler::ConnectionPool.monotonic_time
87
+ raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
88
+ @resource.wait(@mutex, to_wait)
89
+ end
90
+ end
91
+ end
92
+
93
+ ##
94
+ # Shuts down the TimedStack which prevents connections from being checked
95
+ # out. The +block+ is called once for each connection on the stack.
96
+
97
+ def shutdown(&block)
98
+ raise ArgumentError, "shutdown must receive a block" unless block_given?
99
+
100
+ @mutex.synchronize do
101
+ @shutdown_block = block
102
+ @resource.broadcast
103
+
104
+ shutdown_connections
105
+ end
106
+ end
107
+
108
+ ##
109
+ # Returns +true+ if there are no available connections.
110
+
111
+ def empty?
112
+ (@created - @que.length) >= @max
113
+ end
114
+
115
+ ##
116
+ # The number of connections available on the stack.
117
+
118
+ def length
119
+ @max - @created + @que.length
120
+ end
121
+
122
+ private
123
+
124
+ ##
125
+ # This is an extension point for TimedStack and is called with a mutex.
126
+ #
127
+ # This method must returns true if a connection is available on the stack.
128
+
129
+ def connection_stored?(options = nil)
130
+ !@que.empty?
131
+ end
132
+
133
+ ##
134
+ # This is an extension point for TimedStack and is called with a mutex.
135
+ #
136
+ # This method must return a connection from the stack.
137
+
138
+ def fetch_connection(options = nil)
139
+ @que.pop
140
+ end
141
+
142
+ ##
143
+ # This is an extension point for TimedStack and is called with a mutex.
144
+ #
145
+ # This method must shut down all connections on the stack.
146
+
147
+ def shutdown_connections(options = nil)
148
+ while connection_stored?(options)
149
+ conn = fetch_connection(options)
150
+ @shutdown_block.call(conn)
151
+ end
152
+ end
153
+
154
+ ##
155
+ # This is an extension point for TimedStack and is called with a mutex.
156
+ #
157
+ # This method must return +obj+ to the stack.
158
+
159
+ def store_connection(obj, options = nil)
160
+ @que.push obj
161
+ end
162
+
163
+ ##
164
+ # This is an extension point for TimedStack and is called with a mutex.
165
+ #
166
+ # This method must create a connection if and only if the total number of
167
+ # connections allowed has not been met.
168
+
169
+ def try_create(options = nil)
170
+ unless @created == @max
171
+ object = @create_block.call
172
+ @created += 1
173
+ object
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,3 @@
1
+ class Bundler::ConnectionPool
2
+ VERSION = "2.2.2"
3
+ end
@@ -1,4 +1,13 @@
1
1
  # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'rbconfig'
5
+ rescue LoadError
6
+ # for make mjit-headers
7
+ end
8
+
9
+ require_relative "fileutils/version"
10
+
2
11
  #
3
12
  # = fileutils.rb
4
13
  #
@@ -15,48 +24,58 @@
15
24
  #
16
25
  # require 'bundler/vendor/fileutils/lib/fileutils'
17
26
  #
18
- # Bundler::FileUtils.cd(dir, options)
19
- # Bundler::FileUtils.cd(dir, options) {|dir| block }
27
+ # Bundler::FileUtils.cd(dir, **options)
28
+ # Bundler::FileUtils.cd(dir, **options) {|dir| block }
20
29
  # Bundler::FileUtils.pwd()
21
- # Bundler::FileUtils.mkdir(dir, options)
22
- # Bundler::FileUtils.mkdir(list, options)
23
- # Bundler::FileUtils.mkdir_p(dir, options)
24
- # Bundler::FileUtils.mkdir_p(list, options)
25
- # Bundler::FileUtils.rmdir(dir, options)
26
- # Bundler::FileUtils.rmdir(list, options)
27
- # Bundler::FileUtils.ln(target, link, options)
28
- # Bundler::FileUtils.ln(targets, dir, options)
29
- # Bundler::FileUtils.ln_s(target, link, options)
30
- # Bundler::FileUtils.ln_s(targets, dir, options)
31
- # Bundler::FileUtils.ln_sf(target, link, options)
32
- # Bundler::FileUtils.cp(src, dest, options)
33
- # Bundler::FileUtils.cp(list, dir, options)
34
- # Bundler::FileUtils.cp_r(src, dest, options)
35
- # Bundler::FileUtils.cp_r(list, dir, options)
36
- # Bundler::FileUtils.mv(src, dest, options)
37
- # Bundler::FileUtils.mv(list, dir, options)
38
- # Bundler::FileUtils.rm(list, options)
39
- # Bundler::FileUtils.rm_r(list, options)
40
- # Bundler::FileUtils.rm_rf(list, options)
41
- # Bundler::FileUtils.install(src, dest, options)
42
- # Bundler::FileUtils.chmod(mode, list, options)
43
- # Bundler::FileUtils.chmod_R(mode, list, options)
44
- # Bundler::FileUtils.chown(user, group, list, options)
45
- # Bundler::FileUtils.chown_R(user, group, list, options)
46
- # Bundler::FileUtils.touch(list, options)
30
+ # Bundler::FileUtils.mkdir(dir, **options)
31
+ # Bundler::FileUtils.mkdir(list, **options)
32
+ # Bundler::FileUtils.mkdir_p(dir, **options)
33
+ # Bundler::FileUtils.mkdir_p(list, **options)
34
+ # Bundler::FileUtils.rmdir(dir, **options)
35
+ # Bundler::FileUtils.rmdir(list, **options)
36
+ # Bundler::FileUtils.ln(target, link, **options)
37
+ # Bundler::FileUtils.ln(targets, dir, **options)
38
+ # Bundler::FileUtils.ln_s(target, link, **options)
39
+ # Bundler::FileUtils.ln_s(targets, dir, **options)
40
+ # Bundler::FileUtils.ln_sf(target, link, **options)
41
+ # Bundler::FileUtils.cp(src, dest, **options)
42
+ # Bundler::FileUtils.cp(list, dir, **options)
43
+ # Bundler::FileUtils.cp_r(src, dest, **options)
44
+ # Bundler::FileUtils.cp_r(list, dir, **options)
45
+ # Bundler::FileUtils.mv(src, dest, **options)
46
+ # Bundler::FileUtils.mv(list, dir, **options)
47
+ # Bundler::FileUtils.rm(list, **options)
48
+ # Bundler::FileUtils.rm_r(list, **options)
49
+ # Bundler::FileUtils.rm_rf(list, **options)
50
+ # Bundler::FileUtils.install(src, dest, **options)
51
+ # Bundler::FileUtils.chmod(mode, list, **options)
52
+ # Bundler::FileUtils.chmod_R(mode, list, **options)
53
+ # Bundler::FileUtils.chown(user, group, list, **options)
54
+ # Bundler::FileUtils.chown_R(user, group, list, **options)
55
+ # Bundler::FileUtils.touch(list, **options)
47
56
  #
48
- # The <tt>options</tt> parameter is a hash of options, taken from the list
49
- # <tt>:force</tt>, <tt>:noop</tt>, <tt>:preserve</tt>, and <tt>:verbose</tt>.
50
- # <tt>:noop</tt> means that no changes are made. The other three are obvious.
51
- # Each method documents the options that it honours.
57
+ # Possible <tt>options</tt> are:
58
+ #
59
+ # <tt>:force</tt> :: forced operation (rewrite files if exist, remove
60
+ # directories if not empty, etc.);
61
+ # <tt>:verbose</tt> :: print command to be run, in bash syntax, before
62
+ # performing it;
63
+ # <tt>:preserve</tt> :: preserve object's group, user and modification
64
+ # time on copying;
65
+ # <tt>:noop</tt> :: no changes are made (usable in combination with
66
+ # <tt>:verbose</tt> which will print the command to run)
67
+ #
68
+ # Each method documents the options that it honours. See also ::commands,
69
+ # ::options and ::options_of methods to introspect which command have which
70
+ # options.
52
71
  #
53
72
  # All methods that have the concept of a "source" file or directory can take
54
73
  # either one file or a list of files in that argument. See the method
55
74
  # documentation for examples.
56
75
  #
57
- # There are some `low level' methods, which do not accept any option:
76
+ # There are some `low level' methods, which do not accept keyword arguments:
58
77
  #
59
- # Bundler::FileUtils.copy_entry(src, dest, preserve = false, dereference = false)
78
+ # Bundler::FileUtils.copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
60
79
  # Bundler::FileUtils.copy_file(src, dest, preserve = false, dereference = true)
61
80
  # Bundler::FileUtils.copy_stream(srcstream, deststream)
62
81
  # Bundler::FileUtils.remove_entry(path, force = false)
@@ -84,7 +103,6 @@
84
103
  # files/directories. This equates to passing the <tt>:noop</tt> and
85
104
  # <tt>:verbose</tt> flags to methods in Bundler::FileUtils.
86
105
  #
87
-
88
106
  module Bundler::FileUtils
89
107
 
90
108
  def self.private_module_function(name) #:nodoc:
@@ -106,19 +124,22 @@ module Bundler::FileUtils
106
124
  #
107
125
  # Changes the current directory to the directory +dir+.
108
126
  #
109
- # If this method is called with block, resumes to the old
110
- # working directory after the block execution finished.
127
+ # If this method is called with block, resumes to the previous
128
+ # working directory after the block execution has finished.
111
129
  #
112
- # Bundler::FileUtils.cd('/', :verbose => true) # chdir and report it
130
+ # Bundler::FileUtils.cd('/') # change directory
113
131
  #
114
- # Bundler::FileUtils.cd('/') do # chdir
132
+ # Bundler::FileUtils.cd('/', verbose: true) # change directory and report it
133
+ #
134
+ # Bundler::FileUtils.cd('/') do # change directory
115
135
  # # ... # do something
116
136
  # end # return to original directory
117
137
  #
118
138
  def cd(dir, verbose: nil, &block) # :yield: dir
119
139
  fu_output_message "cd #{dir}" if verbose
120
- Dir.chdir(dir, &block)
140
+ result = Dir.chdir(dir, &block)
121
141
  fu_output_message 'cd -' if verbose and block
142
+ result
122
143
  end
123
144
  module_function :cd
124
145
 
@@ -153,9 +174,9 @@ module Bundler::FileUtils
153
174
  # Creates one or more directories.
154
175
  #
155
176
  # Bundler::FileUtils.mkdir 'test'
156
- # Bundler::FileUtils.mkdir %w( tmp data )
157
- # Bundler::FileUtils.mkdir 'notexist', :noop => true # Does not really create.
158
- # Bundler::FileUtils.mkdir 'tmp', :mode => 0700
177
+ # Bundler::FileUtils.mkdir %w(tmp data)
178
+ # Bundler::FileUtils.mkdir 'notexist', noop: true # Does not really create.
179
+ # Bundler::FileUtils.mkdir 'tmp', mode: 0700
159
180
  #
160
181
  def mkdir(list, mode: nil, noop: nil, verbose: nil)
161
182
  list = fu_list(list)
@@ -174,7 +195,7 @@ module Bundler::FileUtils
174
195
  #
175
196
  # Bundler::FileUtils.mkdir_p '/usr/local/lib/ruby'
176
197
  #
177
- # causes to make following directories, if it does not exist.
198
+ # causes to make following directories, if they do not exist.
178
199
  #
179
200
  # * /usr
180
201
  # * /usr/local
@@ -238,22 +259,22 @@ module Bundler::FileUtils
238
259
  # Bundler::FileUtils.rmdir 'somedir'
239
260
  # Bundler::FileUtils.rmdir %w(somedir anydir otherdir)
240
261
  # # Does not really remove directory; outputs message.
241
- # Bundler::FileUtils.rmdir 'somedir', :verbose => true, :noop => true
262
+ # Bundler::FileUtils.rmdir 'somedir', verbose: true, noop: true
242
263
  #
243
264
  def rmdir(list, parents: nil, noop: nil, verbose: nil)
244
265
  list = fu_list(list)
245
266
  fu_output_message "rmdir #{parents ? '-p ' : ''}#{list.join ' '}" if verbose
246
267
  return if noop
247
268
  list.each do |dir|
248
- begin
249
- Dir.rmdir(dir = remove_trailing_slash(dir))
250
- if parents
269
+ Dir.rmdir(dir = remove_trailing_slash(dir))
270
+ if parents
271
+ begin
251
272
  until (parent = File.dirname(dir)) == '.' or parent == dir
252
273
  dir = parent
253
274
  Dir.rmdir(dir)
254
275
  end
276
+ rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
255
277
  end
256
- rescue Errno::ENOTEMPTY, Errno::EEXIST, Errno::ENOENT
257
278
  end
258
279
  end
259
280
  end
@@ -267,7 +288,7 @@ module Bundler::FileUtils
267
288
  #
268
289
  # In the first form, creates a hard link +link+ which points to +target+.
269
290
  # If +link+ already exists, raises Errno::EEXIST.
270
- # But if the :force option is set, overwrites +link+.
291
+ # But if the +force+ option is set, overwrites +link+.
271
292
  #
272
293
  # Bundler::FileUtils.ln 'gcc', 'cc', verbose: true
273
294
  # Bundler::FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs'
@@ -293,6 +314,39 @@ module Bundler::FileUtils
293
314
  alias link ln
294
315
  module_function :link
295
316
 
317
+ #
318
+ # Hard link +src+ to +dest+. If +src+ is a directory, this method links
319
+ # all its contents recursively. If +dest+ is a directory, links
320
+ # +src+ to +dest/src+.
321
+ #
322
+ # +src+ can be a list of files.
323
+ #
324
+ # If +dereference_root+ is true, this method dereference tree root.
325
+ #
326
+ # If +remove_destination+ is true, this method removes each destination file before copy.
327
+ #
328
+ # Bundler::FileUtils.rm_r site_ruby + '/mylib', force: true
329
+ # Bundler::FileUtils.cp_lr 'lib/', site_ruby + '/mylib'
330
+ #
331
+ # # Examples of linking several files to target directory.
332
+ # Bundler::FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail'
333
+ # Bundler::FileUtils.cp_lr Dir.glob('*.rb'), '/home/aamine/lib/ruby', noop: true, verbose: true
334
+ #
335
+ # # If you want to link all contents of a directory instead of the
336
+ # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
337
+ # # use the following code.
338
+ # Bundler::FileUtils.cp_lr 'src/.', 'dest' # cp_lr('src', 'dest') makes dest/src, but this doesn't.
339
+ #
340
+ def cp_lr(src, dest, noop: nil, verbose: nil,
341
+ dereference_root: true, remove_destination: false)
342
+ fu_output_message "cp -lr#{remove_destination ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if verbose
343
+ return if noop
344
+ fu_each_src_dest(src, dest) do |s, d|
345
+ link_entry s, d, dereference_root, remove_destination
346
+ end
347
+ end
348
+ module_function :cp_lr
349
+
296
350
  #
297
351
  # :call-seq:
298
352
  # Bundler::FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil)
@@ -301,7 +355,7 @@ module Bundler::FileUtils
301
355
  #
302
356
  # In the first form, creates a symbolic link +link+ which points to +target+.
303
357
  # If +link+ already exists, raises Errno::EEXIST.
304
- # But if the :force option is set, overwrites +link+.
358
+ # But if the <tt>force</tt> option is set, overwrites +link+.
305
359
  #
306
360
  # Bundler::FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby'
307
361
  # Bundler::FileUtils.ln_s 'verylongsourcefilename.c', 'c', force: true
@@ -339,6 +393,26 @@ module Bundler::FileUtils
339
393
  end
340
394
  module_function :ln_sf
341
395
 
396
+ #
397
+ # Hard links a file system entry +src+ to +dest+.
398
+ # If +src+ is a directory, this method links its contents recursively.
399
+ #
400
+ # Both of +src+ and +dest+ must be a path name.
401
+ # +src+ must exist, +dest+ must not exist.
402
+ #
403
+ # If +dereference_root+ is true, this method dereferences the tree root.
404
+ #
405
+ # If +remove_destination+ is true, this method removes each destination file before copy.
406
+ #
407
+ def link_entry(src, dest, dereference_root = false, remove_destination = false)
408
+ Entry_.new(src, nil, dereference_root).traverse do |ent|
409
+ destent = Entry_.new(dest, ent.rel, false)
410
+ File.unlink destent.path if remove_destination && File.file?(destent.path)
411
+ ent.link destent.path
412
+ end
413
+ end
414
+ module_function :link_entry
415
+
342
416
  #
343
417
  # Copies a file content +src+ to +dest+. If +dest+ is a directory,
344
418
  # copies +src+ to +dest/src+.
@@ -347,7 +421,7 @@ module Bundler::FileUtils
347
421
  #
348
422
  # Bundler::FileUtils.cp 'eval.c', 'eval.c.org'
349
423
  # Bundler::FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6'
350
- # Bundler::FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', :verbose => true
424
+ # Bundler::FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', verbose: true
351
425
  # Bundler::FileUtils.cp 'symlink', 'dest' # copy content, "dest" is not a symlink
352
426
  #
353
427
  def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
@@ -369,13 +443,17 @@ module Bundler::FileUtils
369
443
  #
370
444
  # +src+ can be a list of files.
371
445
  #
446
+ # If +dereference_root+ is true, this method dereference tree root.
447
+ #
448
+ # If +remove_destination+ is true, this method removes each destination file before copy.
449
+ #
372
450
  # # Installing Ruby library "mylib" under the site_ruby
373
- # Bundler::FileUtils.rm_r site_ruby + '/mylib', :force
451
+ # Bundler::FileUtils.rm_r site_ruby + '/mylib', force: true
374
452
  # Bundler::FileUtils.cp_r 'lib/', site_ruby + '/mylib'
375
453
  #
376
454
  # # Examples of copying several files to target directory.
377
455
  # Bundler::FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
378
- # Bundler::FileUtils.cp_r Dir.glob('*.rb'), '/home/foo/lib/ruby', :noop => true, :verbose => true
456
+ # Bundler::FileUtils.cp_r Dir.glob('*.rb'), '/home/foo/lib/ruby', noop: true, verbose: true
379
457
  #
380
458
  # # If you want to copy all contents of a directory instead of the
381
459
  # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
@@ -410,9 +488,13 @@ module Bundler::FileUtils
410
488
  # If +remove_destination+ is true, this method removes each destination file before copy.
411
489
  #
412
490
  def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
413
- Entry_.new(src, nil, dereference_root).wrap_traverse(proc do |ent|
491
+ if dereference_root
492
+ src = File.realpath(src)
493
+ end
494
+
495
+ Entry_.new(src, nil, false).wrap_traverse(proc do |ent|
414
496
  destent = Entry_.new(dest, ent.rel, false)
415
- File.unlink destent.path if remove_destination && File.file?(destent.path)
497
+ File.unlink destent.path if remove_destination && (File.file?(destent.path) || File.symlink?(destent.path))
416
498
  ent.copy destent.path
417
499
  end, proc do |ent|
418
500
  destent = Entry_.new(dest, ent.rel, false)
@@ -447,10 +529,10 @@ module Bundler::FileUtils
447
529
  # disk partition, the file is copied then the original file is removed.
448
530
  #
449
531
  # Bundler::FileUtils.mv 'badname.rb', 'goodname.rb'
450
- # Bundler::FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', :force => true # no error
532
+ # Bundler::FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', force: true # no error
451
533
  #
452
534
  # Bundler::FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/'
453
- # Bundler::FileUtils.mv Dir.glob('test*.rb'), 'test', :noop => true, :verbose => true
535
+ # Bundler::FileUtils.mv Dir.glob('test*.rb'), 'test', noop: true, verbose: true
454
536
  #
455
537
  def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
456
538
  fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
@@ -461,13 +543,12 @@ module Bundler::FileUtils
461
543
  if destent.exist?
462
544
  if destent.directory?
463
545
  raise Errno::EEXIST, d
464
- else
465
- destent.remove_file if rename_cannot_overwrite_file?
466
546
  end
467
547
  end
468
548
  begin
469
549
  File.rename s, d
470
- rescue Errno::EXDEV
550
+ rescue Errno::EXDEV,
551
+ Errno::EPERM # move from unencrypted to encrypted dir (ext4)
471
552
  copy_entry s, d, true
472
553
  if secure
473
554
  remove_entry_secure s, force
@@ -485,18 +566,13 @@ module Bundler::FileUtils
485
566
  alias move mv
486
567
  module_function :move
487
568
 
488
- def rename_cannot_overwrite_file? #:nodoc:
489
- /emx/ =~ RUBY_PLATFORM
490
- end
491
- private_module_function :rename_cannot_overwrite_file?
492
-
493
569
  #
494
570
  # Remove file(s) specified in +list+. This method cannot remove directories.
495
571
  # All StandardErrors are ignored when the :force option is set.
496
572
  #
497
573
  # Bundler::FileUtils.rm %w( junk.txt dust.txt )
498
574
  # Bundler::FileUtils.rm Dir.glob('*.so')
499
- # Bundler::FileUtils.rm 'NotExistFile', :force => true # never raises exception
575
+ # Bundler::FileUtils.rm 'NotExistFile', force: true # never raises exception
500
576
  #
501
577
  def rm(list, force: nil, noop: nil, verbose: nil)
502
578
  list = fu_list(list)
@@ -515,7 +591,7 @@ module Bundler::FileUtils
515
591
  #
516
592
  # Equivalent to
517
593
  #
518
- # Bundler::FileUtils.rm(list, :force => true)
594
+ # Bundler::FileUtils.rm(list, force: true)
519
595
  #
520
596
  def rm_f(list, noop: nil, verbose: nil)
521
597
  rm list, force: true, noop: noop, verbose: verbose
@@ -531,18 +607,18 @@ module Bundler::FileUtils
531
607
  # StandardError when :force option is set.
532
608
  #
533
609
  # Bundler::FileUtils.rm_r Dir.glob('/tmp/*')
534
- # Bundler::FileUtils.rm_r 'some_dir', :force => true
610
+ # Bundler::FileUtils.rm_r 'some_dir', force: true
535
611
  #
536
612
  # WARNING: This method causes local vulnerability
537
613
  # if one of parent directories or removing directory tree are world
538
614
  # writable (including /tmp, whose permission is 1777), and the current
539
615
  # process has strong privilege such as Unix super user (root), and the
540
616
  # system has symbolic link. For secure removing, read the documentation
541
- # of #remove_entry_secure carefully, and set :secure option to true.
542
- # Default is :secure=>false.
617
+ # of remove_entry_secure carefully, and set :secure option to true.
618
+ # Default is <tt>secure: false</tt>.
543
619
  #
544
- # NOTE: This method calls #remove_entry_secure if :secure option is set.
545
- # See also #remove_entry_secure.
620
+ # NOTE: This method calls remove_entry_secure if :secure option is set.
621
+ # See also remove_entry_secure.
546
622
  #
547
623
  def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
548
624
  list = fu_list(list)
@@ -561,10 +637,10 @@ module Bundler::FileUtils
561
637
  #
562
638
  # Equivalent to
563
639
  #
564
- # Bundler::FileUtils.rm_r(list, :force => true)
640
+ # Bundler::FileUtils.rm_r(list, force: true)
565
641
  #
566
642
  # WARNING: This method causes local vulnerability.
567
- # Read the documentation of #rm_r first.
643
+ # Read the documentation of rm_r first.
568
644
  #
569
645
  def rm_rf(list, noop: nil, verbose: nil, secure: nil)
570
646
  rm_r list, force: true, noop: noop, verbose: verbose, secure: secure
@@ -578,7 +654,7 @@ module Bundler::FileUtils
578
654
  # This method removes a file system entry +path+. +path+ shall be a
579
655
  # regular file, a directory, or something. If +path+ is a directory,
580
656
  # remove it recursively. This method is required to avoid TOCTTOU
581
- # (time-of-check-to-time-of-use) local security vulnerability of #rm_r.
657
+ # (time-of-check-to-time-of-use) local security vulnerability of rm_r.
582
658
  # #rm_r causes security hole when:
583
659
  #
584
660
  # * Parent directory is world writable (including /tmp).
@@ -601,8 +677,8 @@ module Bundler::FileUtils
601
677
  #
602
678
  # For details of this security vulnerability, see Perl's case:
603
679
  #
604
- # * http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448
605
- # * http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
680
+ # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448
681
+ # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
606
682
  #
607
683
  # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
608
684
  #
@@ -626,22 +702,38 @@ module Bundler::FileUtils
626
702
  unless parent_st.sticky?
627
703
  raise ArgumentError, "parent directory is world writable, Bundler::FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})"
628
704
  end
705
+
629
706
  # freeze tree root
630
707
  euid = Process.euid
631
- File.open(fullpath + '/.') {|f|
632
- unless fu_stat_identical_entry?(st, f.stat)
633
- # symlink (TOC-to-TOU attack?)
634
- File.unlink fullpath
635
- return
636
- end
637
- f.chown euid, -1
638
- f.chmod 0700
639
- unless fu_stat_identical_entry?(st, File.lstat(fullpath))
640
- # TOC-to-TOU attack?
641
- File.unlink fullpath
642
- return
643
- end
644
- }
708
+ dot_file = fullpath + "/."
709
+ begin
710
+ File.open(dot_file) {|f|
711
+ unless fu_stat_identical_entry?(st, f.stat)
712
+ # symlink (TOC-to-TOU attack?)
713
+ File.unlink fullpath
714
+ return
715
+ end
716
+ f.chown euid, -1
717
+ f.chmod 0700
718
+ }
719
+ rescue Errno::EISDIR # JRuby in non-native mode can't open files as dirs
720
+ File.lstat(dot_file).tap {|fstat|
721
+ unless fu_stat_identical_entry?(st, fstat)
722
+ # symlink (TOC-to-TOU attack?)
723
+ File.unlink fullpath
724
+ return
725
+ end
726
+ File.chown euid, -1, dot_file
727
+ File.chmod 0700, dot_file
728
+ }
729
+ end
730
+
731
+ unless fu_stat_identical_entry?(st, File.lstat(fullpath))
732
+ # TOC-to-TOU attack?
733
+ File.unlink fullpath
734
+ return
735
+ end
736
+
645
737
  # ---- tree root is frozen ----
646
738
  root = Entry_.new(path)
647
739
  root.preorder_traverse do |ent|
@@ -681,7 +773,7 @@ module Bundler::FileUtils
681
773
  # +path+ might be a regular file, a directory, or something.
682
774
  # If +path+ is a directory, remove it recursively.
683
775
  #
684
- # See also #remove_entry_secure.
776
+ # See also remove_entry_secure.
685
777
  #
686
778
  def remove_entry(path, force = false)
687
779
  Entry_.new(path).postorder_traverse do |ent|
@@ -742,8 +834,15 @@ module Bundler::FileUtils
742
834
  #
743
835
  def compare_stream(a, b)
744
836
  bsize = fu_stream_blksize(a, b)
745
- sa = String.new(capacity: bsize)
746
- sb = String.new(capacity: bsize)
837
+
838
+ if RUBY_VERSION > "2.4"
839
+ sa = String.new(capacity: bsize)
840
+ sb = String.new(capacity: bsize)
841
+ else
842
+ sa = String.new
843
+ sb = String.new
844
+ end
845
+
747
846
  begin
748
847
  a.read(bsize, sa)
749
848
  b.read(bsize, sb)
@@ -758,8 +857,8 @@ module Bundler::FileUtils
758
857
  # mode to +mode+. If +dest+ is a directory, destination is +dest+/+src+.
759
858
  # This method removes destination before copy.
760
859
  #
761
- # Bundler::FileUtils.install 'ruby', '/usr/local/bin/ruby', :mode => 0755, :verbose => true
762
- # Bundler::FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', :verbose => true
860
+ # Bundler::FileUtils.install 'ruby', '/usr/local/bin/ruby', mode: 0755, verbose: true
861
+ # Bundler::FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', verbose: true
763
862
  #
764
863
  def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil,
765
864
  noop: nil, verbose: nil)
@@ -889,12 +988,12 @@ module Bundler::FileUtils
889
988
  # Absolute mode is
890
989
  # Bundler::FileUtils.chmod 0755, 'somecommand'
891
990
  # Bundler::FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
892
- # Bundler::FileUtils.chmod 0755, '/usr/bin/ruby', :verbose => true
991
+ # Bundler::FileUtils.chmod 0755, '/usr/bin/ruby', verbose: true
893
992
  #
894
993
  # Symbolic mode is
895
994
  # Bundler::FileUtils.chmod "u=wrx,go=rx", 'somecommand'
896
995
  # Bundler::FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb)
897
- # Bundler::FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', :verbose => true
996
+ # Bundler::FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', verbose: true
898
997
  #
899
998
  # "a" :: is user, group, other mask.
900
999
  # "u" :: is user's mask.
@@ -954,7 +1053,7 @@ module Bundler::FileUtils
954
1053
  # the attribute.
955
1054
  #
956
1055
  # Bundler::FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby'
957
- # Bundler::FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), :verbose => true
1056
+ # Bundler::FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), verbose: true
958
1057
  #
959
1058
  def chown(user, group, list, noop: nil, verbose: nil)
960
1059
  list = fu_list(list)
@@ -978,7 +1077,7 @@ module Bundler::FileUtils
978
1077
  # method does not change the attribute.
979
1078
  #
980
1079
  # Bundler::FileUtils.chown_R 'www', 'www', '/var/www/htdocs'
981
- # Bundler::FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', :verbose => true
1080
+ # Bundler::FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', verbose: true
982
1081
  #
983
1082
  def chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
984
1083
  list = fu_list(list)
@@ -1001,11 +1100,6 @@ module Bundler::FileUtils
1001
1100
  end
1002
1101
  module_function :chown_R
1003
1102
 
1004
- begin
1005
- require 'etc'
1006
- rescue LoadError # rescue LoadError for miniruby
1007
- end
1008
-
1009
1103
  def fu_get_uid(user) #:nodoc:
1010
1104
  return nil unless user
1011
1105
  case user
@@ -1014,6 +1108,7 @@ module Bundler::FileUtils
1014
1108
  when /\A\d+\z/
1015
1109
  user.to_i
1016
1110
  else
1111
+ require 'etc'
1017
1112
  Etc.getpwnam(user) ? Etc.getpwnam(user).uid : nil
1018
1113
  end
1019
1114
  end
@@ -1027,6 +1122,7 @@ module Bundler::FileUtils
1027
1122
  when /\A\d+\z/
1028
1123
  group.to_i
1029
1124
  else
1125
+ require 'etc'
1030
1126
  Etc.getgrnam(group) ? Etc.getgrnam(group).gid : nil
1031
1127
  end
1032
1128
  end
@@ -1067,8 +1163,11 @@ module Bundler::FileUtils
1067
1163
  module StreamUtils_
1068
1164
  private
1069
1165
 
1070
- def fu_windows?
1071
- /mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM
1166
+ case (defined?(::RbConfig) ? ::RbConfig::CONFIG['host_os'] : ::RUBY_PLATFORM)
1167
+ when /mswin|mingw/
1168
+ def fu_windows?; true end
1169
+ else
1170
+ def fu_windows?; false end
1072
1171
  end
1073
1172
 
1074
1173
  def fu_copy_stream0(src, dest, blksize = nil) #:nodoc:
@@ -1193,9 +1292,15 @@ module Bundler::FileUtils
1193
1292
  def entries
1194
1293
  opts = {}
1195
1294
  opts[:encoding] = ::Encoding::UTF_8 if fu_windows?
1196
- Dir.entries(path(), opts)\
1197
- .reject {|n| n == '.' or n == '..' }\
1198
- .map {|n| Entry_.new(prefix(), join(rel(), n.untaint)) }
1295
+
1296
+ files = if Dir.respond_to?(:children)
1297
+ Dir.children(path, **opts)
1298
+ else
1299
+ Dir.entries(path(), **opts)
1300
+ .reject {|n| n == '.' or n == '..' }
1301
+ end
1302
+
1303
+ files.map {|n| Entry_.new(prefix(), join(rel(), n.tap{|x| x.untaint if RUBY_VERSION < "2.7" })) }
1199
1304
  end
1200
1305
 
1201
1306
  def stat
@@ -1250,6 +1355,22 @@ module Bundler::FileUtils
1250
1355
  end
1251
1356
  end
1252
1357
 
1358
+ def link(dest)
1359
+ case
1360
+ when directory?
1361
+ if !File.exist?(dest) and descendant_directory?(dest, path)
1362
+ raise ArgumentError, "cannot link directory %s to itself %s" % [path, dest]
1363
+ end
1364
+ begin
1365
+ Dir.mkdir dest
1366
+ rescue
1367
+ raise unless File.directory?(dest)
1368
+ end
1369
+ else
1370
+ File.link path(), dest
1371
+ end
1372
+ end
1373
+
1253
1374
  def copy(dest)
1254
1375
  lstat
1255
1376
  case
@@ -1266,18 +1387,21 @@ module Bundler::FileUtils
1266
1387
  end
1267
1388
  when symlink?
1268
1389
  File.symlink File.readlink(path()), dest
1269
- when chardev?
1270
- raise "cannot handle device file" unless File.respond_to?(:mknod)
1271
- mknod dest, ?c, 0666, lstat().rdev
1272
- when blockdev?
1273
- raise "cannot handle device file" unless File.respond_to?(:mknod)
1274
- mknod dest, ?b, 0666, lstat().rdev
1390
+ when chardev?, blockdev?
1391
+ raise "cannot handle device file"
1275
1392
  when socket?
1276
- raise "cannot handle socket" unless File.respond_to?(:mknod)
1277
- mknod dest, nil, lstat().mode, 0
1393
+ begin
1394
+ require 'socket'
1395
+ rescue LoadError
1396
+ raise "cannot handle socket"
1397
+ else
1398
+ raise "cannot handle socket" unless defined?(UNIXServer)
1399
+ end
1400
+ UNIXServer.new(dest).close
1401
+ File.chmod lstat().mode, dest
1278
1402
  when pipe?
1279
1403
  raise "cannot handle FIFO" unless File.respond_to?(:mkfifo)
1280
- mkfifo dest, 0666
1404
+ File.mkfifo dest, lstat().mode
1281
1405
  when door?
1282
1406
  raise "cannot handle door: #{path()}"
1283
1407
  else
@@ -1396,14 +1520,14 @@ module Bundler::FileUtils
1396
1520
 
1397
1521
  private
1398
1522
 
1399
- $fileutils_rb_have_lchmod = nil
1523
+ @@fileutils_rb_have_lchmod = nil
1400
1524
 
1401
1525
  def have_lchmod?
1402
1526
  # This is not MT-safe, but it does not matter.
1403
- if $fileutils_rb_have_lchmod == nil
1404
- $fileutils_rb_have_lchmod = check_have_lchmod?
1527
+ if @@fileutils_rb_have_lchmod == nil
1528
+ @@fileutils_rb_have_lchmod = check_have_lchmod?
1405
1529
  end
1406
- $fileutils_rb_have_lchmod
1530
+ @@fileutils_rb_have_lchmod
1407
1531
  end
1408
1532
 
1409
1533
  def check_have_lchmod?
@@ -1414,14 +1538,14 @@ module Bundler::FileUtils
1414
1538
  return false
1415
1539
  end
1416
1540
 
1417
- $fileutils_rb_have_lchown = nil
1541
+ @@fileutils_rb_have_lchown = nil
1418
1542
 
1419
1543
  def have_lchown?
1420
1544
  # This is not MT-safe, but it does not matter.
1421
- if $fileutils_rb_have_lchown == nil
1422
- $fileutils_rb_have_lchown = check_have_lchown?
1545
+ if @@fileutils_rb_have_lchown == nil
1546
+ @@fileutils_rb_have_lchown = check_have_lchown?
1423
1547
  end
1424
- $fileutils_rb_have_lchown
1548
+ @@fileutils_rb_have_lchown
1425
1549
  end
1426
1550
 
1427
1551
  def check_have_lchown?
@@ -1443,10 +1567,13 @@ module Bundler::FileUtils
1443
1567
  else
1444
1568
  DIRECTORY_TERM = "(?=/|\\z)"
1445
1569
  end
1446
- SYSCASE = File::FNM_SYSCASE.nonzero? ? "-i" : ""
1447
1570
 
1448
1571
  def descendant_directory?(descendant, ascendant)
1449
- /\A(?#{SYSCASE}:#{Regexp.quote(ascendant)})#{DIRECTORY_TERM}/ =~ File.dirname(descendant)
1572
+ if File::FNM_SYSCASE.nonzero?
1573
+ File.expand_path(File.dirname(descendant)).casecmp(File.expand_path(ascendant)) == 0
1574
+ else
1575
+ File.expand_path(File.dirname(descendant)) == File.expand_path(ascendant)
1576
+ end
1450
1577
  end
1451
1578
  end # class Entry_
1452
1579
 
@@ -1485,13 +1612,13 @@ module Bundler::FileUtils
1485
1612
  end
1486
1613
  private_module_function :fu_same?
1487
1614
 
1488
- @fileutils_output = $stderr
1489
- @fileutils_label = ''
1490
-
1491
1615
  def fu_output_message(msg) #:nodoc:
1492
- @fileutils_output ||= $stderr
1493
- @fileutils_label ||= ''
1494
- @fileutils_output.puts @fileutils_label + msg
1616
+ output = @fileutils_output if defined?(@fileutils_output)
1617
+ output ||= $stderr
1618
+ if defined?(@fileutils_label)
1619
+ msg = @fileutils_label + msg
1620
+ end
1621
+ output.puts msg
1495
1622
  end
1496
1623
  private_module_function :fu_output_message
1497
1624
 
@@ -1502,8 +1629,11 @@ module Bundler::FileUtils
1502
1629
  tbl
1503
1630
  }
1504
1631
 
1632
+ public
1633
+
1505
1634
  #
1506
- # Returns an Array of method names which have any options.
1635
+ # Returns an Array of names of high-level methods that accept any keyword
1636
+ # arguments.
1507
1637
  #
1508
1638
  # p Bundler::FileUtils.commands #=> ["chmod", "cp", "cp_r", "install", ...]
1509
1639
  #
@@ -1542,7 +1672,7 @@ module Bundler::FileUtils
1542
1672
  end
1543
1673
 
1544
1674
  #
1545
- # Returns an Array of method names which have the option +opt+.
1675
+ # Returns an Array of methods names which have the option +opt+.
1546
1676
  #
1547
1677
  # p Bundler::FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"]
1548
1678
  #
@@ -1550,14 +1680,16 @@ module Bundler::FileUtils
1550
1680
  OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) }
1551
1681
  end
1552
1682
 
1553
- LOW_METHODS = singleton_methods(false) - collect_method(:noop).map(&:intern)
1554
- module LowMethods
1683
+ private
1684
+
1685
+ LOW_METHODS = singleton_methods(false) - collect_method(:noop).map(&:intern) # :nodoc:
1686
+ module LowMethods # :nodoc: internal use only
1555
1687
  private
1556
1688
  def _do_nothing(*)end
1557
1689
  ::Bundler::FileUtils::LOW_METHODS.map {|name| alias_method name, :_do_nothing}
1558
1690
  end
1559
1691
 
1560
- METHODS = singleton_methods() - [:private_module_function,
1692
+ METHODS = singleton_methods() - [:private_module_function, # :nodoc:
1561
1693
  :commands, :options, :have_option?, :options_of, :collect_method]
1562
1694
 
1563
1695
  #
@@ -1567,8 +1699,6 @@ module Bundler::FileUtils
1567
1699
  #
1568
1700
  module Verbose
1569
1701
  include Bundler::FileUtils
1570
- @fileutils_output = $stderr
1571
- @fileutils_label = ''
1572
1702
  names = ::Bundler::FileUtils.collect_method(:verbose)
1573
1703
  names.each do |name|
1574
1704
  module_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@ -1592,8 +1722,6 @@ module Bundler::FileUtils
1592
1722
  module NoWrite
1593
1723
  include Bundler::FileUtils
1594
1724
  include LowMethods
1595
- @fileutils_output = $stderr
1596
- @fileutils_label = ''
1597
1725
  names = ::Bundler::FileUtils.collect_method(:noop)
1598
1726
  names.each do |name|
1599
1727
  module_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@ -1618,8 +1746,6 @@ module Bundler::FileUtils
1618
1746
  module DryRun
1619
1747
  include Bundler::FileUtils
1620
1748
  include LowMethods
1621
- @fileutils_output = $stderr
1622
- @fileutils_label = ''
1623
1749
  names = ::Bundler::FileUtils.collect_method(:noop)
1624
1750
  names.each do |name|
1625
1751
  module_eval(<<-EOS, __FILE__, __LINE__ + 1)