MuranoCLI 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.agignore +1 -0
  3. data/.rubocop.yml +67 -5
  4. data/Gemfile +6 -3
  5. data/MuranoCLI.gemspec +14 -10
  6. data/README.markdown +299 -126
  7. data/Rakefile +6 -1
  8. data/bin/murano +2 -2
  9. data/docs/completions/murano_completion-bash +93 -0
  10. data/lib/MrMurano.rb +19 -2
  11. data/lib/MrMurano/Business.rb +22 -19
  12. data/lib/MrMurano/Config.rb +19 -9
  13. data/lib/MrMurano/Content.rb +4 -4
  14. data/lib/MrMurano/Exchange-Element.rb +99 -0
  15. data/lib/MrMurano/Exchange.rb +137 -0
  16. data/lib/MrMurano/Gateway.rb +9 -9
  17. data/lib/MrMurano/Keystore.rb +4 -2
  18. data/lib/MrMurano/ReCommander.rb +3 -5
  19. data/lib/MrMurano/Solution-ServiceConfig.rb +12 -12
  20. data/lib/MrMurano/Solution-Services.rb +15 -14
  21. data/lib/MrMurano/Solution-Users.rb +2 -2
  22. data/lib/MrMurano/Solution.rb +43 -49
  23. data/lib/MrMurano/SolutionId.rb +28 -28
  24. data/lib/MrMurano/SyncUpDown.rb +32 -22
  25. data/lib/MrMurano/Webservice-Endpoint.rb +2 -1
  26. data/lib/MrMurano/Webservice.rb +5 -5
  27. data/lib/MrMurano/commands.rb +2 -1
  28. data/lib/MrMurano/commands/business.rb +21 -19
  29. data/lib/MrMurano/commands/domain.rb +16 -2
  30. data/lib/MrMurano/commands/exchange.rb +272 -0
  31. data/lib/MrMurano/commands/globals.rb +17 -1
  32. data/lib/MrMurano/commands/init.rb +3 -3
  33. data/lib/MrMurano/commands/link.rb +16 -16
  34. data/lib/MrMurano/commands/postgresql.rb +2 -2
  35. data/lib/MrMurano/commands/show.rb +13 -7
  36. data/lib/MrMurano/commands/solution.rb +23 -17
  37. data/lib/MrMurano/commands/solution_picker.rb +49 -44
  38. data/lib/MrMurano/commands/sync.rb +2 -1
  39. data/lib/MrMurano/commands/timeseries.rb +2 -2
  40. data/lib/MrMurano/commands/tsdb.rb +2 -2
  41. data/lib/MrMurano/hash.rb +19 -7
  42. data/lib/MrMurano/http.rb +12 -2
  43. data/lib/MrMurano/orderedhash.rb +200 -0
  44. data/lib/MrMurano/spec_commander.rb +98 -0
  45. data/lib/MrMurano/verbosing.rb +2 -2
  46. data/lib/MrMurano/version.rb +2 -2
  47. data/spec/Business_spec.rb +8 -6
  48. data/spec/Solution-ServiceConfig_spec.rb +1 -1
  49. data/spec/SyncUpDown_spec.rb +6 -6
  50. data/spec/_workspace.rb +9 -4
  51. data/spec/cmd_business_spec.rb +8 -2
  52. data/spec/cmd_common.rb +266 -25
  53. data/spec/cmd_exchange_spec.rb +118 -0
  54. data/spec/cmd_help_spec.rb +54 -13
  55. data/spec/cmd_init_spec.rb +1 -12
  56. data/spec/cmd_link_spec.rb +94 -72
  57. data/spec/spec_helper.rb +11 -16
  58. metadata +23 -17
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.02 /coding: utf-8
1
+ # Last Modified: 2017.09.11 /coding: utf-8
2
2
 
3
3
  # Copyright © 2016-2017 Exosite LLC.
4
4
  # License: MIT. See LICENSE.txt.
@@ -37,6 +37,7 @@ RSpec.describe MrMurano::Business do
37
37
  pid: "ABC",
38
38
  modelId: "cde",
39
39
  label: "fts",
40
+ api_id: "XYZ",
40
41
  sid: "XYZ",
41
42
  name: "XYZ",},
42
43
  {bizid: "XYZxyz",
@@ -44,6 +45,7 @@ RSpec.describe MrMurano::Business do
44
45
  pid: "fgh",
45
46
  modelId: "ijk",
46
47
  label: "lua-test",
48
+ api_id: "XYZ",
47
49
  sid: "XYZ",
48
50
  name: "XYZ",},
49
51
  ]
@@ -106,14 +108,14 @@ RSpec.describe MrMurano::Business do
106
108
  {bizid: "XYZxyz",
107
109
  type: "application",
108
110
  domain: "XYZxyz.apps.exosite.io",
109
- apiId: "ACBabc",
111
+ api_id: "ACBabc",
110
112
  sid: "ACBabc",
111
113
  name: "ijk",
112
114
  },
113
115
  {bizid: "XYZxyz",
114
116
  type: "application",
115
117
  domain: "XYZxyz.apps.exosite.io",
116
- apiId: "DEFdef",
118
+ api_id: "DEFdef",
117
119
  sid: "DEFdef",
118
120
  name: "lmn",
119
121
  },
@@ -183,7 +185,7 @@ RSpec.describe MrMurano::Business do
183
185
  {bizid: "XYZxyz",
184
186
  type: "product",
185
187
  domain: "ABCabc.m2.exosite.io",
186
- apiId: "ABCabc",
188
+ api_id: "ABCabc",
187
189
  sid: "ABCabc",
188
190
  name: "XXX",
189
191
  },
@@ -192,7 +194,7 @@ RSpec.describe MrMurano::Business do
192
194
  {bizid: "XYZxyz",
193
195
  type: "application",
194
196
  domain: "XYZxyz.apps.exosite.io",
195
- apiId: "DEFdef",
197
+ api_id: "DEFdef",
196
198
  sid: "DEFdef",
197
199
  name: "XXX",
198
200
  },
@@ -222,7 +224,7 @@ RSpec.describe MrMurano::Business do
222
224
 
223
225
  sol = @biz.new_solution!("one", :product)
224
226
  expect(sol.valid?).to be true
225
- expect(sol.sid).to eq("abc123def456ghi78")
227
+ expect(sol.api_id).to eq("abc123def456ghi78")
226
228
  end
227
229
 
228
230
  # if false
@@ -18,7 +18,7 @@ RSpec.describe MrMurano::ServiceConfig do
18
18
  $cfg['product.id'] = 'XYZ'
19
19
  $cfg['application.id'] = 'XYZ'
20
20
 
21
- # ServiceConfig needs an sid, else one could instantiate
21
+ # ServiceConfig needs an api_id, else one could instantiate
22
22
  # ServiceConfigApplication or ServiceConfigProduct.
23
23
  @srv = MrMurano::ServiceConfig.new('XYZ')
24
24
  allow(@srv).to receive(:token).and_return("TTTTTTTTTT")
@@ -12,20 +12,20 @@ class TSUD
12
12
 
13
13
  def initialize
14
14
  # 2017-07-03: See MrMurano::SolutionBase.state for the list of attrs.
15
- @sid = 'XYZ'
16
- @valid_sid = true
15
+ @api_id = 'XYZ'
16
+ @valid_api_id = true
17
17
  @uriparts = []
18
18
  @solntype = 'application.id'
19
19
  @itemkey = :name
20
20
  @project_section = :routes
21
21
  end
22
22
 
23
- def sid
24
- @sid
23
+ def api_id
24
+ @api_id
25
25
  end
26
26
 
27
- def sid?
28
- @valid_sid
27
+ def api_id?
28
+ @valid_api_id
29
29
  end
30
30
 
31
31
  def fetch(id)
@@ -1,9 +1,15 @@
1
+ # Last Modified: 2017.08.29 /coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright © 2016-2017 Exosite LLC.
5
+ # License: MIT. See LICENSE.txt.
6
+ # vim:tw=0:ts=2:sw=2:et:ai
7
+
1
8
  require 'fileutils'
2
9
  require 'pathname'
3
10
  require 'tmpdir'
4
11
 
5
- RSpec.shared_context "WORKSPACE" do
6
-
12
+ RSpec.shared_context 'WORKSPACE' do
7
13
  around(:example) do |ex|
8
14
  @testdir = Pathname.new(Dir.pwd).realpath
9
15
  Dir.mktmpdir do |hdir|
@@ -16,7 +22,7 @@ RSpec.shared_context "WORKSPACE" do
16
22
  @project_dir = File.join(ENV['HOME'], 'work', 'project')
17
23
  FileUtils.mkpath(@project_dir)
18
24
  Dir.chdir(@project_dir) do
19
- ex.run
25
+ ex.run
20
26
  end
21
27
  end
22
28
  ENV['HOME'] = saved_home
@@ -24,4 +30,3 @@ RSpec.shared_context "WORKSPACE" do
24
30
  end
25
31
  end
26
32
 
27
- # vim: set ai et sw=2 ts=2 :
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.17 /coding: utf-8
1
+ # Last Modified: 2017.08.31 /coding: utf-8
2
2
  # frozen_string_literal: probably not yet
3
3
 
4
4
  # Copyright © 2016-2017 Exosite LLC.
@@ -13,6 +13,12 @@ require 'cmd_common'
13
13
  RSpec.describe 'murano business', :cmd, :needs_password do
14
14
  include_context "CI_CMD"
15
15
 
16
+ context "without project" do
17
+ it "help" do
18
+ cmd_verify_help('business')
19
+ end
20
+ end
21
+
16
22
  context "list" do
17
23
  it "as table" do
18
24
  out, err, status = Open3.capture3(capcmd('murano', 'business', 'list'))
@@ -28,7 +34,7 @@ RSpec.describe 'murano business', :cmd, :needs_password do
28
34
  it "as json" do
29
35
  out, err, status = Open3.capture3(capcmd('murano', 'business', 'list', '-c', 'outformat=json'))
30
36
  expect(err).to eq("")
31
- expect{JSON.parse(out)}.to_not raise_error
37
+ expect{ JSON.parse(out) }.to_not raise_error
32
38
  expect(status.exitstatus).to eq(0)
33
39
  end
34
40
 
@@ -1,17 +1,68 @@
1
+ # Last Modified: 2017.08.31 /coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright © 2016-2017 Exosite LLC.
5
+ # License: MIT. See LICENSE.txt.
6
+ # vim:tw=0:ts=2:sw=2:et:ai
7
+
8
+ require 'highline'
9
+ # Set HighLine's $terminal global.
10
+ require 'highline/import'
1
11
  require 'pathname'
2
12
  require 'shellwords'
3
13
  require 'timeout'
4
14
  require 'tmpdir'
15
+ require 'webmock/rspec'
16
+
5
17
  require 'MrMurano/Config'
6
18
 
7
- RSpec.shared_context "CI_CMD" do
19
+ # Prevent Commander from registering its at_exit hook.
20
+ # - Also print warning if spec exits, which rspec doesn't see as wrong.
21
+ # - Note that this comes before importing Commander.
22
+ $exited_abnormally = false
23
+ at_exit do
24
+ if $exited_abnormally
25
+ STDERR.puts('¡!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
26
+ STDERR.puts('¡Unexpected spec exit killed rspec!')
27
+ STDERR.puts('¡!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
28
+ end
29
+ end
30
+ alias original_at_exit at_exit
31
+ def at_exit(*args, &block)
32
+ #original_at_exit *args, &block
33
+ # pass!
34
+ end
35
+
36
+ require 'MrMurano/spec_commander.rb'
37
+
38
+ module Commander
39
+ class Command
40
+ attr_writer :when_called
41
+ #def when_called=(args)
42
+ # @when_called = args
43
+ #end
44
+
45
+ def peek_when_called
46
+ @when_called
47
+ end
48
+ end
49
+
50
+ class Runner
51
+ def force_args(args)
52
+ @args = args
53
+ end
54
+ end
55
+ end
56
+
57
+ RSpec.shared_context 'CI_CMD' do
58
+ # capcmd makes an Open3-ready `murano` command from a list of args.
8
59
  def capcmd(*args)
9
- args = [args] unless args.kind_of? Array
60
+ args = [args] unless args.is_a? Array
10
61
  args.flatten!
11
62
  testdir = File.realpath(@testdir.to_s)
12
- if ENV['CI_MR_EXE'].nil? then
63
+ if ENV['CI_MR_EXE'].nil?
13
64
  args[0] = File.join(testdir, 'bin', args[0])
14
- args.unshift("ruby", "-I#{File.join(testdir, 'lib')}")
65
+ args.unshift('ruby', "-I#{File.join(testdir, 'lib')}")
15
66
  else
16
67
  args[0] = File.join(testdir, (args[0] + '.exe'))
17
68
  end
@@ -20,13 +71,13 @@ RSpec.shared_context "CI_CMD" do
20
71
  # The spinner output would make it hard to write expects().
21
72
  args.push '--no-progress'
22
73
 
23
- if Gem.win_platform? then
74
+ if Gem.win_platform?
24
75
  cmd = args.map do |i|
25
76
  case i
26
77
  when /[ ]/
27
- %{"#{i}"}
78
+ %("#{i}")
28
79
  when /[\*#]/
29
- i.gsub(/([\*#])/,'^\1')
80
+ i.gsub(/([\*#])/, '^\1')
30
81
  else
31
82
  i
32
83
  end
@@ -38,17 +89,9 @@ RSpec.shared_context "CI_CMD" do
38
89
  cmd
39
90
  end
40
91
 
41
- def rname(name)
42
- #"#{name}-#{Random.new.rand.hash.abs.to_s(16)}"
43
- # MUR-2454: Product name may only contain letters and numbers.
44
- #"#{name}#{Random.new.rand.hash.abs.to_s(16)}"
45
- # MUR-XXXX: Product name must be lowercase.
46
- # 2017-06-01: From [cr]: "I'll be having bizapi convert to lower case
47
- # in the short term, and pegasus is updating to allow upper case."
48
- # LATER: Remove .downcase once PAAS fixed.
49
- "#{name.downcase}#{Random.new.rand.hash.abs.to_s(16)}"
50
- end
92
+ # *** Utility fcns: symlinks.
51
93
 
94
+ # Makes a symlink to the /tmp project dir.
52
95
  def mk_symlink
53
96
  # Make it easy to debug tests, e.g., add breakpoint before capcmd('murano', ...)
54
97
  # run test, then open another terminal window and `cd /tmp/murcli-test`.
@@ -56,8 +99,8 @@ RSpec.shared_context "CI_CMD" do
56
99
  # Since this is for DEVs only, we can hack around this.
57
100
  tmpdir = Dir.tmpdir()
58
101
  return unless tmpdir == '/tmp'
59
- @dev_symlink = File.join(tmpdir, "murcli-test")
60
- FileUtils.rm(@dev_symlink, :force => true)
102
+ @dev_symlink = File.join(tmpdir, 'murcli-test')
103
+ FileUtils.rm(@dev_symlink, force: true)
61
104
  begin
62
105
  FileUtils.ln_s(Dir.pwd, @dev_symlink)
63
106
  rescue NotImplementedError => err
@@ -65,22 +108,220 @@ RSpec.shared_context "CI_CMD" do
65
108
  require 'rbconfig'
66
109
  # Check the platform, e.g., "linux-gnu", or other.
67
110
  is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
68
- $stderr.puts(
69
- "Unexpected: ln_s failed on non-Windows machine / host_os: #{RbConfig::CONFIG['host_os']} / err: #{err}"
70
- ) unless is_windows
111
+ unless is_windows
112
+ $stderr.puts(
113
+ 'Unexpected: ln_s failed on non-Windows machine / ' \
114
+ "host_os: #{RbConfig::CONFIG['host_os']} / err: #{err}"
115
+ )
116
+ end
71
117
  end
72
118
  end
73
119
 
120
+ # Removes the /tmp project directory symlink.
74
121
  def rm_symlink
75
- FileUtils.rm(@dev_symlink, :force => true) if defined?(@dev_symlink)
122
+ FileUtils.rm(@dev_symlink, force: true) if defined?(@dev_symlink)
123
+ end
124
+
125
+ # *** Utility fcns: Murano Solutions management: create/delete/expunge.
126
+
127
+ def murano_solutions_expunge_yes
128
+ out, err, status = Open3.capture3(
129
+ capcmd('murano', 'solutions', 'expunge', '-y')
130
+ )
131
+ expect(out).to \
132
+ eq('').or \
133
+ eq("No solutions found\n").or \
134
+ match(/^Deleted [\d]+ solutions/)
135
+ expect(strip_color(err)).to eq('').or eq("No solutions found\n")
136
+ expect(status.exitstatus).to eq(0).or eq(1)
76
137
  end
77
138
 
139
+ def project_up(skip_link: false)
140
+ # Preemptive clean up!
141
+ murano_solutions_expunge_yes if defined?(PRE_EXPUNGE) && PRE_EXPUNGE
142
+
143
+ @proj_name_prod = rname('MurCLITestProd')
144
+ out, err, status = Open3.capture3(
145
+ capcmd('murano', 'product', 'create', @proj_name_prod, '--save')
146
+ )
147
+ expect(err).to eq('')
148
+ expect(out.chomp).to match(/^[a-zA-Z0-9]+$/)
149
+ expect(status.exitstatus).to eq(0)
150
+
151
+ @proj_name_appy = rname('MurCLITestAppy')
152
+ out, err, status = Open3.capture3(
153
+ capcmd('murano', 'application', 'create', @proj_name_appy, '--save')
154
+ )
155
+ expect(err).to eq('')
156
+ soln_id = out
157
+ expect(soln_id.chomp).to match(/^[a-zA-Z0-9]+$/)
158
+ expect(status.exitstatus).to eq(0)
159
+
160
+ project_up_link unless skip_link
161
+ end
162
+
163
+ def project_up_link
164
+ out, err, status = Open3.capture3(capcmd('murano', 'assign', 'set'))
165
+ #expect(out).to a_string_starting_with("Linked product #{@proj_name_prod}")
166
+ olines = out.lines
167
+ expect(olines[0].encode!('UTF-8', 'UTF-8')).to eq(
168
+ "Linked ‘#{@proj_name_prod}’ to ‘#{@proj_name_appy}’\n"
169
+ )
170
+ expect(olines[1]).to eq("Created default event handler\n")
171
+ expect(err).to eq('')
172
+ expect(status.exitstatus).to eq(0)
173
+ end
174
+
175
+ def project_down
176
+ return if defined?(PRE_EXPUNGE) && PRE_EXPUNGE
177
+
178
+ out, err, status = Open3.capture3(
179
+ capcmd('murano', 'solution', 'delete', @proj_name_appy, '-y')
180
+ )
181
+ expect(out).to eq('')
182
+ expect(err).to eq('')
183
+ expect(status.exitstatus).to eq(0)
184
+
185
+ out, err, status = Open3.capture3(
186
+ capcmd('murano', 'solution', 'delete', @proj_name_prod, '-y')
187
+ )
188
+ expect(out).to eq('')
189
+ expect(err).to eq('')
190
+ expect(status.exitstatus).to eq(0)
191
+ end
192
+
193
+ # Utility fcns: Strings.
194
+
195
+ # rname makes a random Murano-acceptable Solution name.
196
+ def rname(name)
197
+ #"#{name}-#{Random.new.rand.hash.abs.to_s(16)}"
198
+ # MUR-2454: Product name may only contain letters and numbers.
199
+ #"#{name}#{Random.new.rand.hash.abs.to_s(16)}"
200
+ # MUR-XXXX: Product name must be lowercase.
201
+ # 2017-06-01: From [cr]: "I'll be having bizapi convert to lower case
202
+ # in the short term, and pegasus is updating to allow upper case."
203
+ # LATER: Remove .downcase once PAAS fixed.
204
+ "#{name.downcase}#{Random.new.rand.hash.abs.to_s(16)}"
205
+ end
206
+
207
+ def strip_color(str)
208
+ str.gsub(/\e\[(\d+)m/, '')
209
+ end
210
+
211
+ # *** rb-commander goodies
212
+
213
+ def murano_command_run(cmd, *args)
214
+ murano_command_runner(cmd, *args)
215
+ end
216
+
217
+ def murano_command_exits(cmd, *args)
218
+ murano_command_runner(cmd, *args, wont_run: true)
219
+ end
220
+
221
+ def murano_command_wont_parse(cmd, *args)
222
+ murano_command_runner(cmd, *args, wont_parse: true)
223
+ end
224
+
225
+ def murano_command_runner(cmd, *args, wont_run: false, wont_parse: false)
226
+ # This is a functional test, so tell WebMock to back off.
227
+ # FIXME: Remember the setting and re-enable.
228
+ WebMock.allow_net_connect!
229
+
230
+ wasout = $stdout
231
+ waserr = $stderr
232
+ wasterm = $terminal
233
+ tmpout = StringIO.new
234
+ tmperr = StringIO.new
235
+
236
+ # Commander's `say` calls HighLine's $terminal.say, so redirect that, too.
237
+ hline = HighLine.new($stdin, tmpout)
238
+ $terminal = hline
239
+ # DEVs: If you set a byebug break after this point, the byebug will
240
+ # show when the code breaks, but you'll see no echo or output. So
241
+ # comment this code out if you're debugging.
242
+ $stdout = tmpout
243
+ $stderr = tmperr
244
+
245
+ # When Commander is loaded, it sets an at_exit hook, which we monkey
246
+ # patch in ReCommander. Since Config.validate_cmd is called before
247
+ # at_exit, it uses runner.command_exit to tell ReCommander's at_exit
248
+ # monkey patch not to call Commander.run!. Via rspec, we don't use the
249
+ # at_exit hook, or ReCommander.
250
+ $cfg = MrMurano::Config.new(::Commander::Runner.instance)
251
+ $cfg.load
252
+ $cfg.validate_cmd(cmd)
253
+ $cfg['tool.no-progress'] = true
254
+ runner = ::Commander::Runner.instance
255
+ unless defined?(runner.command_exit) && runner.command_exit
256
+ # Commander's at_exit hook calls runner.run! which runs the command
257
+ # that was determined with Commander was loaded. I [lb] tried a few
258
+ # different ways to reset Runner.instance, but nothing worked; our
259
+ # best bet is to just call the command directly.
260
+ the_cmd = command(cmd.to_sym)
261
+ when_called = the_cmd.peek_when_called.dup
262
+
263
+ runner.force_args(args.dup)
264
+ $exited_abnormally = true
265
+ #runner.parse_global_options
266
+ if wont_parse
267
+ expect { runner.old_parse_global_options }.to raise_error(SystemExit)
268
+ else
269
+ runner.old_parse_global_options
270
+ runner.remove_global_options runner.options, args
271
+ if wont_run
272
+ expect { the_cmd.run(*args) }.to raise_error(SystemExit)
273
+ else
274
+ the_cmd.run(*args)
275
+ end
276
+ end
277
+ $exited_abnormally = false
278
+
279
+ # Reset proxy_options otherwise Commander::Command.call
280
+ # uses them the next time this command is called.
281
+ the_cmd.proxy_options = []
282
+ the_cmd.when_called = when_called
283
+ end
284
+ runner.command_exit = nil
285
+
286
+ # Ruby provides std i/o constants, so we could do this:
287
+ # $stdout, $stderr = STDOUT, STDERR
288
+ $stdout = wasout
289
+ $stderr = waserr
290
+ $terminal = wasterm
291
+ [strip_color(tmpout.string), strip_color(tmperr.string)]
292
+ end
293
+
294
+ def cmd_verify_help(cmd_name)
295
+ stdout, stderr = murano_command_run(cmd_name)
296
+ expect(stdout).to start_with(
297
+ " NAME:\n\n murano #{cmd_name}\n\n DESCRIPTION:\n\n "
298
+ )
299
+ expect(stderr).to eq('')
300
+ end
301
+
302
+ # *** before() and around()
303
+
304
+ # Before: Load Config.
78
305
  before(:example) do
79
306
  $cfg = MrMurano::Config.new
80
307
  $cfg.load
81
308
  end
82
309
 
310
+ # Around: Make project dir under /tmp.
83
311
  around(:example) do |ex|
312
+ # Load the byebug library now, before changing directories.
313
+ # This sets Setting[:histfile]. Within byebug, try `show histfile`.
314
+ # Make sure this is set now, otherwise, byebug crashes, e.g.,
315
+ # <Errno::ENOENT: No such file or directory @ rb_sysopen -
316
+ # /tmp/d20170830-10087-h7tq6a/project/.byebug_history>
317
+ # This happens if the first call to byebug is after the chdir.
318
+ # Byebug creates the histfile in the tmp dir. So the next time
319
+ # the method containing `byebug` is called, it's from within a
320
+ # different tmp dir, and the old tmp dir has been removed. So
321
+ # byebug crashes trying to access the old, missing histfile.
322
+ require 'byebug/settings/histfile'
323
+ _ignored = ::Byebug::HistfileSetting::DEFAULT
324
+
84
325
  @testdir = Pathname.new(Dir.pwd).realpath
85
326
  Dir.mktmpdir do |hdir|
86
327
  ENV['HOME'] = hdir
@@ -90,7 +331,8 @@ RSpec.shared_context "CI_CMD" do
90
331
  Dir.mkdir(@tmpdir)
91
332
  Dir.chdir(@tmpdir) do
92
333
  mk_symlink
93
- Timeout::timeout(300) do
334
+ # Timeout after 300 secs/5 mins.
335
+ Timeout.timeout(300) do
94
336
  ex.run
95
337
  end
96
338
  rm_symlink
@@ -100,4 +342,3 @@ RSpec.shared_context "CI_CMD" do
100
342
  end
101
343
  end
102
344
 
103
- # vim: set ai et sw=2 ts=2 :