aspera-cli 4.18.0 → 4.18.1

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.
@@ -14,23 +14,28 @@ module Aspera
14
14
  module Api
15
15
  # Provides additional functions using node API with gen4 extensions (access keys)
16
16
  class Node < Aspera::Rest
17
- # node api permissions
18
- ACCESS_LEVELS = %w[delete list mkdir preview read rename write].freeze
19
- HEADER_X_ASPERA_ACCESS_KEY = 'X-Aspera-AccessKey'
20
17
  SCOPE_SEPARATOR = ':'
21
- SCOPE_USER = 'user:all'
22
- SCOPE_ADMIN = 'admin:all'
23
18
  SCOPE_NODE_PREFIX = 'node.'
24
19
  # prefix for ruby code for filter (deprecated)
25
20
  MATCH_EXEC_PREFIX = 'exec:'
26
21
  MATCH_TYPES = [String, Proc, Regexp, NilClass].freeze
27
- PATH_SEPARATOR = '/'
28
22
  SIGNATURE_DELIMITER = '==SIGNATURE=='
29
23
  BEARER_TOKEN_VALIDITY_DEFAULT = 86400
30
- BEARER_TOKEN_SCOPE_DEFAULT = SCOPE_USER
31
- private_constant :MATCH_EXEC_PREFIX, :MATCH_TYPES,
32
- :SIGNATURE_DELIMITER, :BEARER_TOKEN_VALIDITY_DEFAULT, :BEARER_TOKEN_SCOPE_DEFAULT,
33
- :SCOPE_SEPARATOR, :SCOPE_NODE_PREFIX
24
+ # fields in @app_info
25
+ REQUIRED_APP_INFO_FIELDS = %i[api app node_info workspace_id workspace_name].freeze
26
+ # methods of @app_info[:api]
27
+ REQUIRED_APP_API_METHODS = %i[node_api_from add_ts_tags].freeze
28
+ private_constant :SCOPE_SEPARATOR, :SCOPE_NODE_PREFIX, :MATCH_EXEC_PREFIX, :MATCH_TYPES,
29
+ :SIGNATURE_DELIMITER, :BEARER_TOKEN_VALIDITY_DEFAULT,
30
+ :REQUIRED_APP_INFO_FIELDS, :REQUIRED_APP_API_METHODS
31
+
32
+ # node api permissions
33
+ ACCESS_LEVELS = %w[delete list mkdir preview read rename write].freeze
34
+ HEADER_X_ASPERA_ACCESS_KEY = 'X-Aspera-AccessKey'
35
+ HEADER_X_TOTAL_COUNT = 'X-Total-Count'
36
+ SCOPE_USER = 'user:all'
37
+ SCOPE_ADMIN = 'admin:all'
38
+ PATH_SEPARATOR = '/'
34
39
 
35
40
  # register node special token decoder
36
41
  OAuth::Factory.instance.register_decoder(lambda{|token|Node.decode_bearer_token(token)})
@@ -59,7 +64,7 @@ module Aspera
59
64
  end
60
65
 
61
66
  def file_matcher_from_argument(options)
62
- return file_matcher(options.get_next_argument('filter', type: MATCH_TYPES, mandatory: false))
67
+ return file_matcher(options.get_next_argument('filter', validation: MATCH_TYPES, mandatory: false))
63
68
  end
64
69
 
65
70
  # node API scopes
@@ -86,7 +91,7 @@ module Aspera
86
91
  # manage convenience parameters
87
92
  expiration_sec = payload['_validity'] || BEARER_TOKEN_VALIDITY_DEFAULT
88
93
  payload.delete('_validity')
89
- scope = payload['_scope'] || BEARER_TOKEN_SCOPE_DEFAULT
94
+ scope = payload['_scope'] || SCOPE_USER
90
95
  payload.delete('_scope')
91
96
  payload['scope'] ||= token_scope(access_key, scope)
92
97
  payload['auth_type'] ||= 'access_key'
@@ -117,19 +122,13 @@ module Aspera
117
122
  end
118
123
  end
119
124
 
120
- # fields in @app_info
121
- REQUIRED_APP_INFO_FIELDS = %i[api app node_info workspace_id workspace_name].freeze
122
- # methods of @app_info[:api]
123
- REQUIRED_APP_API_METHODS = %i[node_api_from add_ts_tags].freeze
124
- private_constant :REQUIRED_APP_INFO_FIELDS, :REQUIRED_APP_API_METHODS
125
-
126
125
  attr_reader :app_info
127
126
 
127
+ # @param app_info [Hash,NilClass] Special processing for AoC
128
+ # @param add_tspec [Hash,NilClass] Additional transfer spec
128
129
  # @param base_url [String] Rest parameters
129
130
  # @param auth [String,NilClass] Rest parameters
130
131
  # @param headers [String,NilClass] Rest parameters
131
- # @param app_info [Hash,NilClass] Special processing for AoC
132
- # @param add_tspec [Hash,NilClass] Additional transfer spec
133
132
  def initialize(app_info: nil, add_tspec: nil, **rest_args)
134
133
  # init Rest
135
134
  super(**rest_args)
@@ -162,25 +161,42 @@ module Aspera
162
161
  workspace_id: @app_info[:workspace_id],
163
162
  workspace_name: @app_info[:workspace_name])
164
163
  end
165
- Log.log.warn{"cannot resolve link with node id #{node_id}"}
164
+ Log.log.warn{"Cannot resolve link with node id #{node_id}, no resolver"}
166
165
  return nil
167
166
  end
168
167
 
168
+ # Check if a link entry in folder has target information
169
+ # @param entry [Hash] entry in folder
170
+ # @return [Boolean] true if target information is available
171
+ def entry_has_link_information(entry)
172
+ # if target information is missing in folder, try to get it on entry
173
+ if entry['target_node_id'].nil? || entry['target_id'].nil?
174
+ link_entry = read("files/#{entry['id']}")[:data]
175
+ entry['target_node_id'] = link_entry['target_node_id']
176
+ entry['target_id'] = link_entry['target_id']
177
+ end
178
+ return true unless entry['target_node_id'].nil? || entry['target_id'].nil?
179
+ Log.log.warn{"Missing target information for link: #{entry['name']}"}
180
+ return false
181
+ end
182
+
169
183
  # Recursively browse in a folder (with non-recursive method)
170
184
  # sub folders are processed if the processing method returns true
185
+ # links are processed on the respective node
171
186
  # @param state [Object] state object sent to processing method
172
187
  # @param top_file_id [String] file id to start at (default = access key root file id)
173
188
  # @param top_file_path [String] path of top folder (default = /)
174
189
  # @param block [Proc] processing method, arguments: entry, path, state
175
- def process_folder_tree(state:, top_file_id:, top_file_path: '/', &block)
190
+ def process_folder_tree(method_sym:, state:, top_file_id:, top_file_path: '/')
176
191
  Aspera.assert(!top_file_path.nil?){'top_file_path not set'}
177
- Aspera.assert(block){'Missing block'}
192
+ Log.log.debug{"process_folder_tree: node=#{@app_info ? @app_info[:node_info]['id'] : 'nil'}, file id=#{top_file_id}, path=#{top_file_path}"}
178
193
  # start at top folder
179
194
  folders_to_explore = [{id: top_file_id, path: top_file_path}]
180
195
  Log.log.debug{Log.dump(:folders_to_explore, folders_to_explore)}
181
196
  until folders_to_explore.empty?
197
+ # consume first in job list
182
198
  current_item = folders_to_explore.shift
183
- Log.log.debug{"searching #{current_item[:path]}".bg_green}
199
+ Log.log.debug{"Exploring #{current_item[:path]}".bg_green}
184
200
  # get folder content
185
201
  folder_contents =
186
202
  begin
@@ -192,19 +208,21 @@ module Aspera
192
208
  Log.log.debug{Log.dump(:folder_contents, folder_contents)}
193
209
  folder_contents.each do |entry|
194
210
  relative_path = File.join(current_item[:path], entry['name'])
195
- Log.log.debug{"process_folder_tree checking #{relative_path}"}
196
- # continue only if method returns true
197
- next unless yield(entry, relative_path, state)
211
+ Log.log.debug{"process_folder_tree: checking #{relative_path}"}
212
+ # call block, continue only if method returns true
213
+ next unless send(method_sym, entry, relative_path, state)
198
214
  # entry type is file, folder or link
199
215
  case entry['type']
200
216
  when 'folder'
201
217
  folders_to_explore.push({id: entry['id'], path: relative_path})
202
218
  when 'link'
203
- node_id_to_node(entry['target_node_id'])&.process_folder_tree(
204
- state: state,
205
- top_file_id: entry['target_id'],
206
- top_file_path: relative_path,
207
- &block)
219
+ if entry_has_link_information(entry)
220
+ node_id_to_node(entry['target_node_id'])&.process_folder_tree(
221
+ method_sym: method_sym,
222
+ state: state,
223
+ top_file_id: entry['target_id'],
224
+ top_file_path: relative_path)
225
+ end
208
226
  end
209
227
  end
210
228
  end
@@ -216,60 +234,23 @@ module Aspera
216
234
  # @return [Hash] {.api,.file_id}
217
235
  def resolve_api_fid(top_file_id, path)
218
236
  Aspera.assert_type(top_file_id, String)
237
+ Aspera.assert_type(path, String)
238
+ # if last element is a link and followed by "/", we list the content of that folder, else we return the link
219
239
  process_last_link = path.end_with?(PATH_SEPARATOR)
240
+ # keep only non-empty elements
220
241
  path_elements = path.split(PATH_SEPARATOR).reject(&:empty?)
221
242
  return {api: self, file_id: top_file_id} if path_elements.empty?
222
- resolve_state = {path: path_elements, result: nil}
223
- process_folder_tree(state: resolve_state, top_file_id: top_file_id) do |entry, _path, state|
224
- # this block is called recursively for each entry in folder
225
- # stop digging here if not in right path
226
- next false unless entry['name'].eql?(state[:path].first)
227
- # ok it matches, so we remove the match
228
- state[:path].shift
229
- case entry['type']
230
- when 'file'
231
- # file must be terminal
232
- raise "#{entry['name']} is a file, expecting folder to find: #{state[:path]}" unless state[:path].empty?
233
- # it's terminal, we found it
234
- state[:result] = {api: self, file_id: entry['id']}
235
- next false
236
- when 'folder'
237
- if state[:path].empty?
238
- # we found it
239
- state[:result] = {api: self, file_id: entry['id']}
240
- next false
241
- end
242
- when 'link'
243
- if state[:path].empty?
244
- if process_last_link
245
- # we found it
246
- other_node = node_id_to_node(entry['target_node_id'])
247
- raise 'cannot resolve link' if other_node.nil?
248
- state[:result] = {api: other_node, file_id: entry['target_id']}
249
- else
250
- # we found it but we do not process the link
251
- state[:result] = {api: self, file_id: entry['id']}
252
- end
253
- next false
254
- end
255
- else
256
- Log.log.warn{"Unknown element type: #{entry['type']}"}
257
- end
258
- # continue to dig folder
259
- next true
260
- end
243
+ resolve_state = {path: path_elements, result: nil, process_last_link: process_last_link}
244
+ process_folder_tree(method_sym: :process_api_fid, state: resolve_state, top_file_id: top_file_id)
261
245
  raise "entry not found: #{resolve_state[:path]}" if resolve_state[:result].nil?
246
+ Log.log.debug{"resolve_api_fid: #{path} -> #{resolve_state[:result][:api].base_url} #{resolve_state[:result][:file_id]}"}
262
247
  return resolve_state[:result]
263
248
  end
264
249
 
265
250
  def find_files(top_file_id, test_block)
266
251
  Log.log.debug{"find_files: file id=#{top_file_id}"}
267
252
  find_state = {found: [], test_block: test_block}
268
- process_folder_tree(state: find_state, top_file_id: top_file_id) do |entry, path, state|
269
- state[:found].push(entry.merge({'path' => path})) if state[:test_block].call(entry)
270
- # test all files deeply
271
- true
272
- end
253
+ process_folder_tree(method_sym: :process_find_files, state: find_state, top_file_id: top_file_id)
273
254
  return find_state[:found]
274
255
  end
275
256
 
@@ -306,7 +287,7 @@ module Aspera
306
287
  ak_name = params[:headers][HEADER_X_ASPERA_ACCESS_KEY]
307
288
  # TODO: token_generation_lambda = lambda{|do_refresh|oauth.token(refresh: do_refresh)}
308
289
  # get bearer token, possibly use cache
309
- ak_token = oauth.token(refresh: false)
290
+ ak_token = oauth.token
310
291
  else Aspera.error_unexpected_value(auth_params[:type])
311
292
  end
312
293
  transfer_spec = {
@@ -352,6 +333,58 @@ module Aspera
352
333
  unless transfer_spec['remote_user'].eql?(Transfer::Spec::ACCESS_KEY_TRANSFER_USER)
353
334
  return transfer_spec
354
335
  end
336
+
337
+ private
338
+
339
+ def process_api_fid(entry, path, state)
340
+ # this block is called recursively for each entry in folder
341
+ # stop digging here if not in right path
342
+ return false unless entry['name'].eql?(state[:path].first)
343
+ # ok it matches, so we remove the match, and continue digging
344
+ state[:path].shift
345
+ path_fully_consumed = state[:path].empty?
346
+ case entry['type']
347
+ when 'file'
348
+ # file must be terminal
349
+ raise "#{entry['name']} is a file, expecting folder to find: #{state[:path]}" unless path_fully_consumed
350
+ # it's terminal, we found it
351
+ Log.log.debug{"resolve_api_fid: found #{path} -> #{entry['id']}"}
352
+ state[:result] = {api: self, file_id: entry['id']}
353
+ return false
354
+ when 'folder'
355
+ if path_fully_consumed
356
+ # we found it
357
+ state[:result] = {api: self, file_id: entry['id']}
358
+ return false
359
+ end
360
+ when 'link'
361
+ if path_fully_consumed
362
+ if state[:process_last_link]
363
+ # we found it
364
+ other_node = nil
365
+ if entry_has_link_information(entry)
366
+ other_node = node_id_to_node(entry['target_node_id'])
367
+ end
368
+ raise 'Cannot resolve link' if other_node.nil?
369
+ state[:result] = {api: other_node, file_id: entry['target_id']}
370
+ else
371
+ # we found it but we do not process the link
372
+ state[:result] = {api: self, file_id: entry['id']}
373
+ end
374
+ return false
375
+ end
376
+ else
377
+ Log.log.warn{"Unknown element type: #{entry['type']}"}
378
+ end
379
+ # continue to dig folder
380
+ return true
381
+ end
382
+
383
+ def process_find_files(entry, _path, state)
384
+ state[:found].push(entry.merge({'path' => path})) if state[:test_block].call(entry)
385
+ # test all files deeply
386
+ return true
387
+ end
355
388
  end
356
389
  end
357
390
  end
@@ -44,7 +44,7 @@ module Aspera
44
44
  app_root: File.join('C:', 'Program Files', 'Aspera', 'Enterprise Server'),
45
45
  log_root: File.join('C:', 'Program Files', 'Aspera', 'Enterprise Server', 'var', 'log')
46
46
  }]
47
- when Aspera::Environment::OS_X then [{
47
+ when Aspera::Environment::OS_MACOS then [{
48
48
  expected: CONNECT,
49
49
  app_root: File.join(Dir.home, 'Applications', 'Aspera Connect.app'),
50
50
  log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Connect'),
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # cspell:ignore csvt jsonpp
3
+ # cspell:ignore csvt jsonpp stdbin
4
4
  require 'aspera/uri_reader'
5
5
  require 'aspera/environment'
6
6
  require 'aspera/log'
@@ -17,11 +17,6 @@ module Aspera
17
17
  class ExtendedValue
18
18
  include Singleton
19
19
 
20
- # special values
21
- INIT = 'INIT'
22
- ALL = 'ALL'
23
- DEF = 'DEF'
24
-
25
20
  MARKER_START = '@'
26
21
  MARKER_END = ':'
27
22
  MARKER_IN_END = '@'
@@ -74,10 +69,22 @@ module Aspera
74
69
  zlib: lambda{|v|Zlib::Inflate.inflate(v)},
75
70
  extend: lambda{|v|ExtendedValue.instance.evaluate_all(v)}
76
71
  }
72
+ @default_decoder = nil
73
+ end
74
+
75
+ # Regex to match an extended value
76
+ def handler_regex_string
77
+ "#{MARKER_START}(#{modifiers.join('|')})#{MARKER_END}"
77
78
  end
78
79
 
79
80
  public
80
81
 
82
+ def default_decoder=(value)
83
+ Log.log.debug{"setting default decoder to #{value} (#{value.class})"}
84
+ Aspera.assert(value.nil? || @handlers.key?(value))
85
+ @default_decoder = value
86
+ end
87
+
81
88
  def modifiers; @handlers.keys; end
82
89
 
83
90
  # add a new handler
@@ -87,16 +94,13 @@ module Aspera
87
94
  @handlers[name] = method
88
95
  end
89
96
 
90
- # Regex to match an extended value
91
- def ext_re
92
- "#{MARKER_START}(#{modifiers.join('|')})#{MARKER_END}"
93
- end
94
-
95
- # parse an option value if it is a String using supported extended value modifiers
97
+ # parse an string value to extended value, if it is a String using supported extended value modifiers
96
98
  # other value types are returned as is
99
+ # @param value [String] the value to parse
100
+ # @param expect [Class,Array] one or a list of expected types
97
101
  def evaluate(value)
98
102
  return value unless value.is_a?(String)
99
- regex = Regexp.new("^#{ext_re}(.*)$", Regexp::MULTILINE)
103
+ regex = Regexp.new("^#{handler_regex_string}(.*)$", Regexp::MULTILINE)
100
104
  # first determine decoders, in reversed order
101
105
  handlers_reversed = []
102
106
  while (m = value.match(regex))
@@ -113,9 +117,18 @@ module Aspera
113
117
  return value
114
118
  end
115
119
 
120
+ # parse string value as extended value
121
+ # use default decoder if none is specified
122
+ def evaluate_with_default(value)
123
+ if value.is_a?(String) && value.match(/^#{handler_regex_string}.*$/).nil? && !@default_decoder.nil?
124
+ value = [MARKER_START, @default_decoder, MARKER_END, value].join
125
+ end
126
+ return evaluate(value)
127
+ end
128
+
116
129
  # find inner extended values
117
130
  def evaluate_all(value)
118
- regex = Regexp.new("^(.*)#{ext_re}([^#{MARKER_IN_END}]*)#{MARKER_IN_END}(.*)$", Regexp::MULTILINE)
131
+ regex = Regexp.new("^(.*)#{handler_regex_string}([^#{MARKER_IN_END}]*)#{MARKER_IN_END}(.*)$", Regexp::MULTILINE)
119
132
  while (m = value.match(regex))
120
133
  sub_value = "@#{m[2]}:#{m[3]}"
121
134
  Log.log.debug{"evaluating #{sub_value}"}
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # cspell:ignore jsonpp
4
+ require 'aspera/cli/special_values'
4
5
  require 'aspera/preview/terminal'
5
6
  require 'aspera/secret_hider'
6
7
  require 'aspera/environment'
@@ -110,7 +111,7 @@ module Aspera
110
111
  class << self
111
112
  def all_but(list)
112
113
  list = [list] unless list.is_a?(Array)
113
- return list.map{|i|"#{FIELDS_LESS}#{i}"}.unshift(ExtendedValue::ALL)
114
+ return list.map{|i|"#{FIELDS_LESS}#{i}"}.unshift(SpecialValues::ALL)
114
115
  end
115
116
 
116
117
  def tick(yes)
@@ -207,9 +208,9 @@ module Aspera
207
208
  options.declare(:output, 'Destination for results', types: String, handler: {o: self, m: :option_handler})
208
209
  options.declare(:display, 'Output only some information', values: DISPLAY_LEVELS, handler: {o: self, m: :option_handler}, default: :info)
209
210
  options.declare(
210
- :fields, "Comma separated list of: fields, or #{ExtendedValue::ALL}, or #{ExtendedValue::DEF}", handler: {o: self, m: :option_handler},
211
+ :fields, "Comma separated list of: fields, or #{SpecialValues::ALL}, or #{SpecialValues::DEF}", handler: {o: self, m: :option_handler},
211
212
  types: [String, Array, Regexp, Proc],
212
- default: ExtendedValue::DEF)
213
+ default: SpecialValues::DEF)
213
214
  options.declare(:select, 'Select only some items in lists: column, value', types: [Hash, Proc], handler: {o: self, m: :option_handler})
214
215
  options.declare(:table_style, 'Table display style', types: [Hash], handler: {o: self, m: :option_handler}, default: default_table_style)
215
216
  options.declare(:flat_hash, 'Display deep values as additional keys', values: :bool, handler: {o: self, m: :option_handler}, default: true)
@@ -256,7 +257,7 @@ module Aspera
256
257
  # the requested list of fields, but if can contain special values
257
258
  request =
258
259
  case @options[:fields]
259
- # when NilClass then [ExtendedValue::DEF]
260
+ # when NilClass then [SpecialValues::DEF]
260
261
  when String then @options[:fields].split(',')
261
262
  when Array then @options[:fields]
262
263
  when Regexp then return all_fields(data).select{|i|i.match(@options[:fields])}
@@ -272,10 +273,10 @@ module Aspera
272
273
  item = item[1..-1]
273
274
  end
274
275
  case item
275
- when ExtendedValue::ALL
276
+ when SpecialValues::ALL
276
277
  # get the list of all column names used in all lines, not just first one, as all lines may have different columns
277
278
  request.unshift(*all_fields(data))
278
- when ExtendedValue::DEF
279
+ when SpecialValues::DEF
279
280
  default = all_fields(data).select{|i|default.call(i)} if default.is_a?(Proc)
280
281
  default = all_fields(data) if default.nil?
281
282
  request.unshift(*default)
@@ -293,11 +294,11 @@ module Aspera
293
294
  # filter the list of items on the fields option
294
295
  def filter_list_on_fields(data)
295
296
  # by default, keep all data intact
296
- return data if @options[:fields].eql?(ExtendedValue::DEF) && @options[:select].nil?
297
+ return data if @options[:fields].eql?(SpecialValues::DEF) && @options[:select].nil?
297
298
  Aspera.assert_type(data, Array){'Filtering fields or select requires result is an Array of Hash'}
298
299
  Aspera.assert(data.all?(Hash)){'Filtering fields or select requires result is an Array of Hash'}
299
300
  filter_columns_on_select(data)
300
- return data if @options[:fields].eql?(ExtendedValue::DEF)
301
+ return data if @options[:fields].eql?(SpecialValues::DEF)
301
302
  selected_fields = compute_fields(data, @options[:fields])
302
303
  return data.map{|i|i[selected_fields.first]} if selected_fields.length == 1
303
304
  return data.map{|i|i.select{|k, _|selected_fields.include?(k)}}
@@ -358,8 +359,8 @@ module Aspera
358
359
  raise URI::InvalidURIError, 'not uri' if !(blob =~ /\A#{URI::DEFAULT_PARSER.make_regexp}\z/)
359
360
  # it's a url
360
361
  url = blob
361
- unless OpenApplication.instance.url_method.eql?(:text)
362
- OpenApplication.instance.uri(url)
362
+ unless Environment.instance.url_method.eql?(:text)
363
+ Environment.instance.open_uri(url)
363
364
  return ''
364
365
  end
365
366
  # remote_image = Rest.new(base_url: url).read('')
@@ -93,11 +93,11 @@ module Aspera
93
93
  @plug_init[:only_manual] = false
94
94
  # create formatter, in case there is an exception, it is used to display.
95
95
  @plug_init[:formatter] = Formatter.new
96
- @plug_init[:options] = Manager.new(PROGRAM_NAME)
97
- # give command line arguments to option manager
98
- options.parse_command_line(@argv)
96
+ # create command line manager with arguments
97
+ @plug_init[:options] = Manager.new(PROGRAM_NAME, @argv)
99
98
  # formatter adds options
100
- formatter.declare_options(options)
99
+ @plug_init[:formatter].declare_options(options)
100
+ ExtendedValue.instance.default_decoder = options.get_option(:struct_parser)
101
101
  # compare $0 with expected name
102
102
  current_prog_name = File.basename($PROGRAM_NAME)
103
103
  formatter.display_message(
@@ -162,9 +162,9 @@ module Aspera
162
162
  options.declare(:version, 'Display version', values: :none, short: 'v') { formatter.display_message(:data, Cli::VERSION); Process.exit(0) } # rubocop:disable Style/Semicolon, Layout/LineLength
163
163
  options.declare(
164
164
  :ui, 'Method to start browser',
165
- values: OpenApplication::USER_INTERFACES,
166
- handler: {o: OpenApplication.instance, m: :url_method},
167
- default: OpenApplication.default_gui_mode)
165
+ values: Environment::USER_INTERFACES,
166
+ handler: {o: Environment.instance, m: :url_method},
167
+ default: Environment.default_gui_mode)
168
168
  options.declare(:log_level, 'Log level', values: Log.levels, handler: {o: Log.instance, m: :level})
169
169
  options.declare(:logger, 'Logging method', values: Log::LOG_TYPES, handler: {o: Log.instance, m: :logger_type})
170
170
  options.declare(:lock_port, 'Prevent dual execution of a command, e.g. in cron', coerce: Integer, types: Integer)
@@ -189,7 +189,7 @@ module Aspera
189
189
  end
190
190
 
191
191
  def generate_bash_completion
192
- if options.get_next_argument('', expected: :multiple, mandatory: false).nil?
192
+ if options.get_next_argument('', multiple: true, mandatory: false).nil?
193
193
  PluginFactory.instance.plugin_list.each{|p|puts p}
194
194
  else
195
195
  Log.log.warn('only first level completion so far')
@@ -197,11 +197,11 @@ module Aspera
197
197
  Process.exit(0)
198
198
  end
199
199
 
200
- def exit_with_usage(all_plugins)
201
- Log.log.debug('exit_with_usage'.bg_red)
200
+ def exit_with_usage(include_all_plugins)
201
+ Log.log.debug{"exit_with_usage(#{include_all_plugins})".bg_red}
202
202
  # display main plugin options
203
203
  formatter.display_message(:error, options.parser)
204
- if all_plugins
204
+ if include_all_plugins
205
205
  # list plugins that have a "require" field, i.e. all but main plugin
206
206
  PluginFactory.instance.plugin_list.each do |plugin_name_sym|
207
207
  next if plugin_name_sym.eql?(COMMAND_CONFIG)