rubyinstaller-build 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE.md +8 -0
  3. data/.gitignore +12 -0
  4. data/.yardopts +7 -0
  5. data/CHANGELOG-2.4.md +166 -0
  6. data/CHANGELOG-2.5.md +87 -0
  7. data/CHANGELOG-2.6.md +62 -0
  8. data/CHANGELOG-2.7.md +22 -0
  9. data/Gemfile +6 -0
  10. data/LICENSE.txt +25 -0
  11. data/README.md +114 -0
  12. data/Rakefile +164 -0
  13. data/appveyor-key.asc.asc +61 -0
  14. data/appveyor.yml +141 -0
  15. data/docker/Dockerfile +50 -0
  16. data/docker/Rakefile +22 -0
  17. data/gems/rubyinstaller-build.yaml +2 -0
  18. data/lib/devkit.rb +3 -0
  19. data/lib/ruby_installer.rb +3 -0
  20. data/lib/ruby_installer/build.rb +23 -0
  21. data/lib/ruby_installer/build/ca_cert_file.rb +66 -0
  22. data/lib/ruby_installer/build/colors.rb +45 -0
  23. data/lib/ruby_installer/build/components/01_msys2.rb +97 -0
  24. data/lib/ruby_installer/build/components/02_pacman_update.rb +35 -0
  25. data/lib/ruby_installer/build/components/03_dev_tools.rb +68 -0
  26. data/lib/ruby_installer/build/components/base.rb +58 -0
  27. data/lib/ruby_installer/build/components_installer.rb +53 -0
  28. data/lib/ruby_installer/build/dll_directory.rb +97 -0
  29. data/lib/ruby_installer/build/erb_compiler.rb +61 -0
  30. data/lib/ruby_installer/build/gem_version.rb +5 -0
  31. data/lib/ruby_installer/build/gems.rb +74 -0
  32. data/lib/ruby_installer/build/msys2_installation.rb +280 -0
  33. data/lib/ruby_installer/build/openstruct.rb +29 -0
  34. data/lib/ruby_installer/build/release.rb +120 -0
  35. data/lib/ruby_installer/build/singleton.rb +45 -0
  36. data/lib/ruby_installer/build/task.rb +20 -0
  37. data/lib/ruby_installer/build/utils.rb +110 -0
  38. data/lib/ruby_installer/runtime.rb +18 -0
  39. data/lib/ruby_installer/runtime/ridk.rb +195 -0
  40. data/packages/ri-msys/Rakefile +72 -0
  41. data/packages/ri-msys/recipes/sandbox/70-add-msys2-installation.rake +18 -0
  42. data/packages/ri/Rakefile +60 -0
  43. data/recipes/archive-7z/10-define-variables.rake +2 -0
  44. data/recipes/archive-7z/70-create-archive.rake +10 -0
  45. data/recipes/archive-7z/90-define-main-task.rake +2 -0
  46. data/recipes/installer-inno/10-define-variables.rake +2 -0
  47. data/recipes/installer-inno/50-generate-filelist.rake +28 -0
  48. data/recipes/installer-inno/60-generate-iss-file.rake +8 -0
  49. data/recipes/installer-inno/70-run-iscc.rake +19 -0
  50. data/recipes/installer-inno/90-define-main-task.rake +2 -0
  51. data/recipes/installer-inno/events.iss +88 -0
  52. data/recipes/installer-inno/images/fake.bmp +0 -0
  53. data/recipes/installer-inno/images/wizard-large.bmp +0 -0
  54. data/recipes/installer-inno/images/wizard-logo.bmp +0 -0
  55. data/recipes/installer-inno/ri_gui.iss +286 -0
  56. data/recipes/installer-inno/rubyinstaller.iss.erb +157 -0
  57. data/recipes/installer-inno/util.iss +271 -0
  58. data/recipes/msys2/10-define-variables.rake +6 -0
  59. data/recipes/msys2/30-download-msys2-base.rake +4 -0
  60. data/recipes/msys2/40-extract-msys2-base.rake +9 -0
  61. data/recipes/msys2/50-init-msys.rake +8 -0
  62. data/recipes/msys2/50-install-components.rake +19 -0
  63. data/recipes/msys2/90-define-main-task.rake +2 -0
  64. data/recipes/sandbox/10-define-variables.rake +6 -0
  65. data/recipes/sandbox/20-add-runtime-files.rake +15 -0
  66. data/recipes/sandbox/20-define-import-files.rake +16 -0
  67. data/recipes/sandbox/20-define-import-readline.rake +28 -0
  68. data/recipes/sandbox/20-extend-irb.rake +13 -0
  69. data/recipes/sandbox/40-fix-rake-shebang.rake +6 -0
  70. data/recipes/sandbox/40-generate-rake-cmd.rake +7 -0
  71. data/recipes/sandbox/40-generate-version-file.rake +20 -0
  72. data/recipes/sandbox/50-do-import-files.rake +17 -0
  73. data/recipes/sandbox/50-gather-sandbox-files.rake +6 -0
  74. data/recipes/sandbox/60-define-gem-wrappers.rake +5 -0
  75. data/recipes/sandbox/60-side-by-side-assembly.rake +81 -0
  76. data/recipes/sandbox/70-add-gem-bin-wrappers.rake +10 -0
  77. data/recipes/sandbox/70-install-gems.rake +11 -0
  78. data/recipes/sandbox/80-copy-msys-files.rake +8 -0
  79. data/recipes/sandbox/90-define-main-task.rake +2 -0
  80. data/recipes/sandbox/LICENSE.txt +24 -0
  81. data/recipes/sandbox/rubyinstaller-2.3.4-x64.files +4 -0
  82. data/recipes/sandbox/rubyinstaller-2.3.4-x86.files +4 -0
  83. data/recipes/sandbox/rubyinstaller-2.3.4.files +43 -0
  84. data/recipes/sandbox/rubyinstaller-2.4.10-x64.files +4 -0
  85. data/recipes/sandbox/rubyinstaller-2.4.10-x86.files +4 -0
  86. data/recipes/sandbox/rubyinstaller-2.4.10.files +44 -0
  87. data/recipes/sandbox/rubyinstaller-2.5.8-x64.files +6 -0
  88. data/recipes/sandbox/rubyinstaller-2.5.8-x86.files +6 -0
  89. data/recipes/sandbox/rubyinstaller-2.5.8.files +33 -0
  90. data/recipes/sandbox/rubyinstaller-2.6.6-x64.files +6 -0
  91. data/recipes/sandbox/rubyinstaller-2.6.6-x86.files +6 -0
  92. data/recipes/sandbox/rubyinstaller-2.6.6.files +35 -0
  93. data/recipes/sandbox/rubyinstaller-2.7.1-x64.files +6 -0
  94. data/recipes/sandbox/rubyinstaller-2.7.1-x86.files +6 -0
  95. data/recipes/sandbox/rubyinstaller-2.7.1.files +35 -0
  96. data/recipes/sandbox/rubyinstaller-head-x64.files +6 -0
  97. data/recipes/sandbox/rubyinstaller-head-x86.files +6 -0
  98. data/recipes/sandbox/rubyinstaller-head.files +35 -0
  99. data/recipes/unpack/10-define-variables.rake +5 -0
  100. data/recipes/unpack/20-define-msys-packages.rake +1 -0
  101. data/recipes/unpack/30-add-ri2-repo-to-msys.rake +41 -0
  102. data/recipes/unpack/50-install-msys-packages.rake +28 -0
  103. data/recipes/unpack/90-define-main-task.rake +2 -0
  104. data/recipes/unpack/appveyor-repo-key.asc +29 -0
  105. data/resources/files/irbrc_predefiner.rb +21 -0
  106. data/resources/files/operating_system.rb +21 -0
  107. data/resources/files/readline.rb +17 -0
  108. data/resources/files/reline.rb +437 -0
  109. data/resources/files/reline/ansi.rb +177 -0
  110. data/resources/files/reline/config.rb +297 -0
  111. data/resources/files/reline/general_io.rb +75 -0
  112. data/resources/files/reline/history.rb +56 -0
  113. data/resources/files/reline/key_actor.rb +7 -0
  114. data/resources/files/reline/key_actor/base.rb +7 -0
  115. data/resources/files/reline/key_actor/emacs.rb +517 -0
  116. data/resources/files/reline/key_actor/vi_command.rb +518 -0
  117. data/resources/files/reline/key_actor/vi_insert.rb +517 -0
  118. data/resources/files/reline/key_stroke.rb +53 -0
  119. data/resources/files/reline/kill_ring.rb +113 -0
  120. data/resources/files/reline/line_editor.rb +2231 -0
  121. data/resources/files/reline/unicode.rb +527 -0
  122. data/resources/files/reline/unicode/east_asian_width.rb +1145 -0
  123. data/resources/files/reline/version.rb +3 -0
  124. data/resources/files/reline/windows.rb +273 -0
  125. data/resources/files/ridk.cmd +39 -0
  126. data/resources/files/ridk.ps1 +26 -0
  127. data/resources/files/ridk_use/ridk.cmd +13 -0
  128. data/resources/files/ridk_use/ridk.ps1 +17 -0
  129. data/resources/files/ridk_use/ridk_use.rb +221 -0
  130. data/resources/files/setrbvars.cmd +14 -0
  131. data/resources/icons/ruby-doc.ico +0 -0
  132. data/resources/ssl/README-SSL.md +37 -0
  133. data/resources/ssl/c_rehash.rb +167 -0
  134. data/resources/ssl/cacert.pem +4105 -0
  135. data/rubyinstaller-build.gemspec +28 -0
  136. metadata +226 -0
@@ -0,0 +1,3 @@
1
+ module Reline
2
+ VERSION = '0.1.3'
3
+ end
@@ -0,0 +1,273 @@
1
+ require 'fiddle/import'
2
+
3
+ class Reline::Windows
4
+ def self.encoding
5
+ Encoding::UTF_8
6
+ end
7
+
8
+ def self.win?
9
+ true
10
+ end
11
+
12
+ RAW_KEYSTROKE_CONFIG = {
13
+ [224, 72] => :ed_prev_history, # ↑
14
+ [224, 80] => :ed_next_history, # ↓
15
+ [224, 77] => :ed_next_char, # →
16
+ [224, 75] => :ed_prev_char, # ←
17
+ [224, 83] => :key_delete, # Del
18
+ [224, 71] => :ed_move_to_beg, # Home
19
+ [224, 79] => :ed_move_to_end, # End
20
+ [ 0, 41] => :ed_unassigned, # input method on/off
21
+ [ 0, 72] => :ed_prev_history, # ↑
22
+ [ 0, 80] => :ed_next_history, # ↓
23
+ [ 0, 77] => :ed_next_char, # →
24
+ [ 0, 75] => :ed_prev_char, # ←
25
+ [ 0, 83] => :key_delete, # Del
26
+ [ 0, 71] => :ed_move_to_beg, # Home
27
+ [ 0, 79] => :ed_move_to_end # End
28
+ }
29
+
30
+ if defined? JRUBY_VERSION
31
+ require 'win32api'
32
+ else
33
+ class Win32API
34
+ DLL = {}
35
+ TYPEMAP = {"0" => Fiddle::TYPE_VOID, "S" => Fiddle::TYPE_VOIDP, "I" => Fiddle::TYPE_LONG}
36
+ POINTER_TYPE = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
37
+
38
+ WIN32_TYPES = "VPpNnLlIi"
39
+ DL_TYPES = "0SSI"
40
+
41
+ def initialize(dllname, func, import, export = "0", calltype = :stdcall)
42
+ @proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1')
43
+ import = @proto.chars.map {|win_type| TYPEMAP[win_type.tr(WIN32_TYPES, DL_TYPES)]}
44
+ export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)]
45
+ calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype]
46
+
47
+ handle = DLL[dllname] ||=
48
+ begin
49
+ Fiddle.dlopen(dllname)
50
+ rescue Fiddle::DLError
51
+ raise unless File.extname(dllname).empty?
52
+ Fiddle.dlopen(dllname + ".dll")
53
+ end
54
+
55
+ @func = Fiddle::Function.new(handle[func], import, export, calltype)
56
+ rescue Fiddle::DLError => e
57
+ raise LoadError, e.message, e.backtrace
58
+ end
59
+
60
+ def call(*args)
61
+ import = @proto.split("")
62
+ args.each_with_index do |x, i|
63
+ args[i], = [x == 0 ? nil : x].pack("p").unpack(POINTER_TYPE) if import[i] == "S"
64
+ args[i], = [x].pack("I").unpack("i") if import[i] == "I"
65
+ end
66
+ ret, = @func.call(*args)
67
+ return ret || 0
68
+ end
69
+ end
70
+ end
71
+
72
+ VK_MENU = 0x12
73
+ VK_LMENU = 0xA4
74
+ VK_CONTROL = 0x11
75
+ VK_SHIFT = 0x10
76
+ STD_INPUT_HANDLE = -10
77
+ STD_OUTPUT_HANDLE = -11
78
+ WINDOW_BUFFER_SIZE_EVENT = 0x04
79
+ FILE_TYPE_PIPE = 0x0003
80
+ FILE_NAME_INFO = 2
81
+ @@getwch = Win32API.new('msvcrt', '_getwch', [], 'I')
82
+ @@kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I')
83
+ @@GetKeyState = Win32API.new('user32', 'GetKeyState', ['L'], 'L')
84
+ @@GetConsoleScreenBufferInfo = Win32API.new('kernel32', 'GetConsoleScreenBufferInfo', ['L', 'P'], 'L')
85
+ @@SetConsoleCursorPosition = Win32API.new('kernel32', 'SetConsoleCursorPosition', ['L', 'L'], 'L')
86
+ @@GetStdHandle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
87
+ @@FillConsoleOutputCharacter = Win32API.new('kernel32', 'FillConsoleOutputCharacter', ['L', 'L', 'L', 'L', 'P'], 'L')
88
+ @@ScrollConsoleScreenBuffer = Win32API.new('kernel32', 'ScrollConsoleScreenBuffer', ['L', 'P', 'P', 'L', 'P'], 'L')
89
+ @@hConsoleHandle = @@GetStdHandle.call(STD_OUTPUT_HANDLE)
90
+ @@hConsoleInputHandle = @@GetStdHandle.call(STD_INPUT_HANDLE)
91
+ @@GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['L', 'P'], 'L')
92
+ @@ReadConsoleInput = Win32API.new('kernel32', 'ReadConsoleInput', ['L', 'P', 'L', 'P'], 'L')
93
+ @@GetFileType = Win32API.new('kernel32', 'GetFileType', ['L'], 'L')
94
+ @@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I')
95
+
96
+ @@input_buf = []
97
+ @@output_buf = []
98
+
99
+ def self.msys_tty?(io=@@hConsoleInputHandle)
100
+ # check if fd is a pipe
101
+ if @@GetFileType.call(io) != FILE_TYPE_PIPE
102
+ return false
103
+ end
104
+
105
+ bufsize = 1024
106
+ p_buffer = "\0" * bufsize
107
+ res = @@GetFileInformationByHandleEx.call(io, FILE_NAME_INFO, p_buffer, bufsize - 2)
108
+ return false if res == 0
109
+
110
+ # get pipe name: p_buffer layout is:
111
+ # struct _FILE_NAME_INFO {
112
+ # DWORD FileNameLength;
113
+ # WCHAR FileName[1];
114
+ # } FILE_NAME_INFO
115
+ len = p_buffer[0, 4].unpack("L")[0]
116
+ name = p_buffer[4, len].encode(Encoding::UTF_8, Encoding::UTF_16LE, invalid: :replace)
117
+
118
+ # Check if this could be a MSYS2 pty pipe ('\msys-XXXX-ptyN-XX')
119
+ # or a cygwin pty pipe ('\cygwin-XXXX-ptyN-XX')
120
+ name =~ /(msys-|cygwin-).*-pty/ ? true : false
121
+ end
122
+
123
+ def self.getwch
124
+ unless @@input_buf.empty?
125
+ return @@input_buf.shift
126
+ end
127
+ while @@kbhit.call == 0
128
+ sleep(0.001)
129
+ end
130
+ until @@kbhit.call == 0
131
+ ret = @@getwch.call
132
+ if ret == 0 or ret == 0xE0
133
+ @@input_buf << ret
134
+ ret = @@getwch.call
135
+ @@input_buf << ret
136
+ return @@input_buf.shift
137
+ end
138
+ begin
139
+ bytes = ret.chr(Encoding::UTF_8).bytes
140
+ @@input_buf.push(*bytes)
141
+ rescue Encoding::UndefinedConversionError
142
+ @@input_buf << ret
143
+ @@input_buf << @@getwch.call if ret == 224
144
+ end
145
+ end
146
+ @@input_buf.shift
147
+ end
148
+
149
+ def self.getc
150
+ num_of_events = 0.chr * 8
151
+ while @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) != 0 and num_of_events.unpack('L').first > 0
152
+ input_record = 0.chr * 18
153
+ read_event = 0.chr * 4
154
+ if @@ReadConsoleInput.(@@hConsoleInputHandle, input_record, 1, read_event) != 0
155
+ event = input_record[0, 2].unpack('s*').first
156
+ if event == WINDOW_BUFFER_SIZE_EVENT
157
+ @@winch_handler.()
158
+ end
159
+ end
160
+ end
161
+ unless @@output_buf.empty?
162
+ return @@output_buf.shift
163
+ end
164
+ input = getwch
165
+ meta = (@@GetKeyState.call(VK_LMENU) & 0x80) != 0
166
+ control = (@@GetKeyState.call(VK_CONTROL) & 0x80) != 0
167
+ shift = (@@GetKeyState.call(VK_SHIFT) & 0x80) != 0
168
+ force_enter = !input.instance_of?(Array) && (control or shift) && input == 0x0D
169
+ if force_enter
170
+ # It's treated as Meta+Enter on Windows
171
+ @@output_buf.push("\e".ord)
172
+ @@output_buf.push(input)
173
+ else
174
+ case input
175
+ when 0x00
176
+ meta = false
177
+ @@output_buf.push(input)
178
+ input = getwch
179
+ @@output_buf.push(*input)
180
+ when 0xE0
181
+ @@output_buf.push(input)
182
+ input = getwch
183
+ @@output_buf.push(*input)
184
+ when 0x03
185
+ @@output_buf.push(input)
186
+ else
187
+ @@output_buf.push(input)
188
+ end
189
+ end
190
+ if meta
191
+ "\e".ord
192
+ else
193
+ @@output_buf.shift
194
+ end
195
+ end
196
+
197
+ def self.ungetc(c)
198
+ @@output_buf.unshift(c)
199
+ end
200
+
201
+ def self.get_screen_size
202
+ csbi = 0.chr * 22
203
+ @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
204
+ csbi[0, 4].unpack('SS').reverse
205
+ end
206
+
207
+ def self.cursor_pos
208
+ csbi = 0.chr * 22
209
+ @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
210
+ x = csbi[4, 2].unpack('s*').first
211
+ y = csbi[6, 2].unpack('s*').first
212
+ Reline::CursorPos.new(x, y)
213
+ end
214
+
215
+ def self.move_cursor_column(val)
216
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, cursor_pos.y * 65536 + val)
217
+ end
218
+
219
+ def self.move_cursor_up(val)
220
+ if val > 0
221
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y - val) * 65536 + cursor_pos.x)
222
+ elsif val < 0
223
+ move_cursor_down(-val)
224
+ end
225
+ end
226
+
227
+ def self.move_cursor_down(val)
228
+ if val > 0
229
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y + val) * 65536 + cursor_pos.x)
230
+ elsif val < 0
231
+ move_cursor_up(-val)
232
+ end
233
+ end
234
+
235
+ def self.erase_after_cursor
236
+ csbi = 0.chr * 24
237
+ @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
238
+ cursor = csbi[4, 4].unpack('L').first
239
+ written = 0.chr * 4
240
+ @@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
241
+ end
242
+
243
+ def self.scroll_down(val)
244
+ return if val.zero?
245
+ scroll_rectangle = [0, val, get_screen_size.last, get_screen_size.first].pack('s4')
246
+ destination_origin = 0 # y * 65536 + x
247
+ fill = [' '.ord, 0].pack('SS')
248
+ @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
249
+ end
250
+
251
+ def self.clear_screen
252
+ # TODO: Use FillConsoleOutputCharacter and FillConsoleOutputAttribute
253
+ write "\e[2J"
254
+ write "\e[1;1H"
255
+ end
256
+
257
+ def self.set_screen_size(rows, columns)
258
+ raise NotImplementedError
259
+ end
260
+
261
+ def self.set_winch_handler(&handler)
262
+ @@winch_handler = handler
263
+ end
264
+
265
+ def self.prep
266
+ # do nothing
267
+ nil
268
+ end
269
+
270
+ def self.deprep(otio)
271
+ # do nothing
272
+ end
273
+ end
@@ -0,0 +1,39 @@
1
+ @echo off
2
+
3
+ if "x%~1" == "xenable" (
4
+ goto :setvars
5
+ )
6
+ if "x%~1" == "xdisable" (
7
+ goto :setvars
8
+ )
9
+ if "x%~1" == "xexec" (
10
+ goto :exec
11
+ )
12
+ if "x%~1" == "xuse" (
13
+ goto :use
14
+ )
15
+
16
+ "%~dp0ruby" -x "%~f0" %*
17
+ @exit /b %ERRORLEVEL%
18
+
19
+ :exec
20
+ rem pass the command to a bash shell
21
+ setlocal
22
+ for /f "delims=" %%x in ('"%~dp0ruby" --disable-gems -x '%~f0' %1') do set "%%x"
23
+ shift
24
+ shift
25
+ %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
26
+ @exit /b %ERRORLEVEL%
27
+
28
+ :setvars
29
+ @echo on
30
+ @for /f "delims=" %%x in ('"%~dp0ruby" --disable-gems -x '%~f0' %*') do set "%%x"
31
+ @exit /b %ERRORLEVEL%
32
+
33
+ :use
34
+ "%~dp0../ridk_use/ridk.cmd" %*
35
+ @exit /b %ERRORLEVEL%
36
+
37
+ #!/mingw64/bin/ruby
38
+ require "ruby_installer/runtime"
39
+ RubyInstaller::Runtime::Ridk.run!(ARGV)
@@ -0,0 +1,26 @@
1
+ $rubydir = split-path $MyInvocation.MyCommand.Definition -parent
2
+
3
+ # Execute 'enable' and 'disable' in the context of the current powershell session, so that env vars are effective for subsequent commands.
4
+ if ($args[0] -eq "enable" -or $args[0] -eq "disable") {
5
+ $rubyfile = $rubydir + "/ruby"
6
+ $op = $args[0] + "ps1"
7
+ $vars = & $rubyfile --disable-gems -x $MyInvocation.MyCommand.Definition $op
8
+ Invoke-Expression $vars
9
+ exit $LastExitCode
10
+ }
11
+
12
+ # Forward 'use' to the script in ridk_use
13
+ if ($args[0] -eq "use") {
14
+ $ridkfile = $rubydir + "/../ridk_use/ridk.ps1"
15
+ . $ridkfile @args
16
+ exit $LastExitCode
17
+ }
18
+
19
+ # Pass all other commands through to ridk.cmd, so that a separate context for env vars is used.
20
+ $cmdfile = $rubydir + "/ridk.cmd"
21
+ & $cmdfile @args
22
+ exit $LastExitCode
23
+
24
+ #!/mingw64/bin/ruby
25
+ require "ruby_installer/runtime"
26
+ RubyInstaller::Runtime::Ridk.run!(ARGV)
@@ -0,0 +1,13 @@
1
+ @echo off
2
+
3
+ if "x%~1" == "xuse" (
4
+ @echo on
5
+ @for /f "delims=" %%x in ('%~dp0../bin/ruby --disable-gems '%~dp0ridk_use.rb' %*') do @set "%%x"
6
+ @exit /b %ERRORLEVEL%
7
+ )
8
+
9
+ :: Forward any other ridk call to ridk.cmd of the active ruby version
10
+ @for /f "delims=" %%x in ('ruby -rrbconfig -e "puts RbConfig::TOPDIR"') do set "RPATH=%%x"
11
+ "%RPATH%\bin\ridk.cmd" %*
12
+ @exit /b %ERRORLEVEL%
13
+ #%/
@@ -0,0 +1,17 @@
1
+ $rubydir = split-path $MyInvocation.MyCommand.Definition -parent
2
+ $rubyfile = $rubydir + "/../bin/ruby"
3
+
4
+ # Execute 'use' in the context of the current powershell session, so that env vars are effective for subsequent commands.
5
+ if ($args[0] -eq "use") {
6
+ $op, $rest = $args
7
+ $op = $op + "ps1"
8
+ $vars = & $rubyfile --disable-gems $rubydir/ridk_use.rb $op $rest
9
+ if ($vars){ Invoke-Expression $vars }
10
+ exit $LastExitCode
11
+ }
12
+
13
+ # Forward any other ridk call to ridk.ps1 of the active ruby version
14
+ $rpath = & ruby -rrbconfig -e "puts RbConfig::TOPDIR" $op
15
+ $ps1file = $rpath + "/bin/ridk.ps1"
16
+ . $ps1file @args
17
+ exit $LastExitCode
@@ -0,0 +1,221 @@
1
+ require "yaml"
2
+
3
+ def ridkuse_dirname
4
+ File.expand_path("..", __FILE__)
5
+ end
6
+
7
+ def rubies_filename
8
+ ENV['RIDK_USE_RUBIES'] || File.join(ridkuse_dirname, "rubies.yml")
9
+ end
10
+
11
+ def backslachs(path)
12
+ path.gsub("/", "\\")
13
+ end
14
+
15
+ def forwardslachs(path)
16
+ path.gsub("\\", "/")
17
+ end
18
+
19
+ RUBY_INSTALL_KEY = "SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/"
20
+
21
+ def find_each_ruby_from_registry
22
+ return to_enum(:find_each_ruby_from_registry) unless block_given?
23
+
24
+ require "win32/registry"
25
+ begin
26
+ Win32::Registry::HKEY_CURRENT_USER.open(backslachs(RUBY_INSTALL_KEY)) do |reg|
27
+ reg.each_key do |subkey|
28
+ subreg = reg.open(subkey)
29
+ begin
30
+ if subreg['DisplayName'] =~ /^Ruby / && File.directory?(il=subreg['InstallLocation'])
31
+ yield il
32
+ end
33
+ rescue Encoding::InvalidByteSequenceError
34
+ # Ignore entries with broken character encoding
35
+ end
36
+ end
37
+ end
38
+ rescue Win32::Registry::Error
39
+ end
40
+ end
41
+
42
+ def find_each_ruby_from_yml
43
+ return to_enum(:find_each_ruby_from_yml) unless block_given?
44
+ YAML.load_file(rubies_filename).each do |rubypath|
45
+ yield rubypath
46
+ end
47
+ end
48
+
49
+ def find_each_ruby(&block)
50
+ return to_enum(:find_each_ruby) unless block_given?
51
+
52
+ if File.exist?(rubies_filename)
53
+ find_each_ruby_from_yml(&block)
54
+ else
55
+ find_each_ruby_from_registry(&block)
56
+ end
57
+ end
58
+
59
+ def each_ruby
60
+ return to_enum(:each_ruby) unless block_given?
61
+
62
+ find_each_ruby.each_with_index do |rubypath, idx|
63
+ yield(idx + 1, File.expand_path(rubypath))
64
+ end
65
+ end
66
+
67
+ def list_rubies
68
+ each_ruby do |idx, rubypath|
69
+ rubyver = begin
70
+ `#{File.join(rubypath, "bin/ruby")} -v`
71
+ rescue => err
72
+ err.to_s
73
+ end
74
+ $stderr.puts "#{idx} - #{rubypath} \t#{rubyver}"
75
+ end
76
+ end
77
+
78
+ def update_rubies
79
+ if File.exist?(rubies_filename)
80
+ rubies = YAML.load_file(rubies_filename)
81
+ else
82
+ rubies = []
83
+ end
84
+
85
+ find_each_ruby_from_registry do |rubypath|
86
+ rubypath = File.expand_path(rubypath)
87
+ unless rubies.find{|r| File.expand_path(r) == rubypath }
88
+ rubies << rubypath
89
+ end
90
+ end
91
+
92
+ $stderr.puts "Update #{rubies_filename}"
93
+ File.write(rubies_filename, YAML.dump(rubies))
94
+ end
95
+
96
+ def in_path_regex(path)
97
+ pathregex = Regexp.escape(forwardslachs(path)).gsub(/\//, "[\\/\\\\\\\\]")
98
+ /(^|;)#{pathregex}[^;]*(;|$)/i
99
+ end
100
+
101
+ def remove_rubies_from_path(vars, rubies)
102
+ if path=vars['PATH']
103
+ rubies.each do |rubypath|
104
+ path = path.gsub(in_path_regex(rubypath)) do |a|
105
+ res = $1.empty? || $2.empty? ? "" : ";"
106
+ $stderr.puts "Disable #{rubypath}"
107
+ res
108
+ end
109
+ end
110
+ vars['PATH'] = path
111
+ end
112
+ end
113
+
114
+ def ensure_ridk_use_in_path(vars)
115
+ if path=vars['PATH']
116
+ ridkusepath = ridkuse_dirname
117
+ unless in_path_regex(ridkusepath).match(path)
118
+ path = backslachs(ridkusepath) + ";" + path
119
+ end
120
+ vars['PATH'] = path
121
+ end
122
+ end
123
+
124
+ def enable_ruby_in_path(vars, rubypath)
125
+ if (path=vars["PATH"]) && !in_path_regex(rubypath).match(path)
126
+ $stderr.puts "Enable #{rubypath}"
127
+ vars['PATH'] = backslachs(File.join(rubypath, "bin")) + ";" + vars['PATH']
128
+ end
129
+ end
130
+
131
+ def switch_ruby_per_cmd(rubypath, rubies, ps1)
132
+ vars = {
133
+ "PATH" => ENV['PATH'],
134
+ }
135
+ remove_rubies_from_path(vars, rubies)
136
+ enable_ruby_in_path(vars, rubypath)
137
+ ensure_ridk_use_in_path(vars)
138
+
139
+ if ps1
140
+ vars.map do |key, val|
141
+ "$env:#{key}=\"#{val.gsub('"', '`"')}\""
142
+ end.join(";")
143
+ else
144
+ vars.map do |key, val|
145
+ "#{key}=#{val}"
146
+ end.join("\n")
147
+ end
148
+ end
149
+
150
+ def select_ruby(rubies, selector)
151
+ ridx = selector.to_i
152
+ if ridx > 0
153
+ rubies = each_ruby.to_h
154
+ selpath = rubies[ridx]
155
+ end
156
+ return selpath if selpath
157
+
158
+ if selector =~ /^\/(.*)\/$/
159
+ regex = $1
160
+ _, selpath = rubies.find do |idx, rubypath|
161
+ /#{regex}/i.match(rubypath)
162
+ end
163
+ return selpath
164
+ end
165
+ end
166
+
167
+ def print_help
168
+ $stderr.puts <<-EOT
169
+ Usage:
170
+ ridk use [<option>]
171
+
172
+ Option:
173
+ Start interactive version selection
174
+ list Search and list installed ruby versions
175
+ update Save or update the found ruby versions to rubies.yml
176
+ <number> Change the active ruby version by index
177
+ /<regex>/ Change the active ruby version by regex
178
+ help Display this help and exit
179
+ EOT
180
+ end
181
+
182
+ def run!(args)
183
+ case args[0]
184
+ when "use", "useps1"
185
+ ps1 = args[0] == "useps1"
186
+ case args[1]
187
+ when 'help'
188
+ print_help
189
+ when 'list'
190
+ list_rubies
191
+ when 'update'
192
+ update_rubies
193
+ when String
194
+ rubies = each_ruby.to_h
195
+ rubypath = select_ruby(rubies, args[1])
196
+ unless rubypath
197
+ $stderr.print "Invalid ruby: #{args[1].inspect}"
198
+ exit 1
199
+ end
200
+ puts switch_ruby_per_cmd(rubypath, rubies.values, ps1)
201
+ else
202
+ list_rubies
203
+ rubies = each_ruby.to_h
204
+
205
+ loop do
206
+ $stderr.print "Select ruby version to enable: "
207
+ selector = $stdin.gets.strip
208
+ rubypath = select_ruby(rubies, selector)
209
+ next unless rubypath
210
+ puts switch_ruby_per_cmd(rubypath, rubies.values, ps1)
211
+ break
212
+ end
213
+ end
214
+ else
215
+ $stderr.puts "Invalid option #{args[0].inspect}"
216
+ end
217
+ end
218
+
219
+ if $0 == __FILE__
220
+ run!(ARGV)
221
+ end