aspera-cli 4.25.0.pre → 4.25.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 (63) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +23 -17
  4. data/CONTRIBUTING.md +119 -47
  5. data/README.md +325 -239
  6. data/lib/aspera/agent/direct.rb +14 -12
  7. data/lib/aspera/agent/factory.rb +9 -6
  8. data/lib/aspera/agent/transferd.rb +8 -8
  9. data/lib/aspera/api/aoc.rb +33 -24
  10. data/lib/aspera/api/ats.rb +1 -0
  11. data/lib/aspera/api/faspex.rb +11 -5
  12. data/lib/aspera/ascmd.rb +1 -1
  13. data/lib/aspera/ascp/installation.rb +7 -7
  14. data/lib/aspera/ascp/management.rb +9 -5
  15. data/lib/aspera/assert.rb +3 -3
  16. data/lib/aspera/cli/extended_value.rb +10 -2
  17. data/lib/aspera/cli/formatter.rb +15 -62
  18. data/lib/aspera/cli/manager.rb +9 -43
  19. data/lib/aspera/cli/plugins/aoc.rb +71 -66
  20. data/lib/aspera/cli/plugins/ats.rb +30 -36
  21. data/lib/aspera/cli/plugins/base.rb +11 -6
  22. data/lib/aspera/cli/plugins/config.rb +21 -16
  23. data/lib/aspera/cli/plugins/console.rb +2 -1
  24. data/lib/aspera/cli/plugins/faspex.rb +7 -4
  25. data/lib/aspera/cli/plugins/faspex5.rb +12 -9
  26. data/lib/aspera/cli/plugins/faspio.rb +5 -2
  27. data/lib/aspera/cli/plugins/httpgw.rb +2 -1
  28. data/lib/aspera/cli/plugins/node.rb +10 -6
  29. data/lib/aspera/cli/plugins/oauth.rb +12 -11
  30. data/lib/aspera/cli/plugins/orchestrator.rb +2 -1
  31. data/lib/aspera/cli/plugins/preview.rb +2 -2
  32. data/lib/aspera/cli/plugins/server.rb +3 -2
  33. data/lib/aspera/cli/plugins/shares.rb +59 -20
  34. data/lib/aspera/cli/transfer_agent.rb +1 -2
  35. data/lib/aspera/cli/version.rb +1 -1
  36. data/lib/aspera/command_line_builder.rb +5 -5
  37. data/lib/aspera/coverage.rb +5 -1
  38. data/lib/aspera/dot_container.rb +108 -0
  39. data/lib/aspera/environment.rb +69 -89
  40. data/lib/aspera/faspex_postproc.rb +1 -1
  41. data/lib/aspera/id_generator.rb +7 -10
  42. data/lib/aspera/keychain/macos_security.rb +2 -2
  43. data/lib/aspera/log.rb +2 -1
  44. data/lib/aspera/oauth/base.rb +25 -38
  45. data/lib/aspera/oauth/factory.rb +5 -6
  46. data/lib/aspera/oauth/generic.rb +1 -1
  47. data/lib/aspera/oauth/jwt.rb +1 -1
  48. data/lib/aspera/oauth/url_json.rb +4 -3
  49. data/lib/aspera/oauth/web.rb +2 -2
  50. data/lib/aspera/preview/file_types.rb +1 -1
  51. data/lib/aspera/preview/terminal.rb +95 -29
  52. data/lib/aspera/preview/utils.rb +6 -5
  53. data/lib/aspera/rest.rb +5 -2
  54. data/lib/aspera/ssh.rb +6 -5
  55. data/lib/aspera/sync/conf.schema.yaml +2 -2
  56. data/lib/aspera/sync/operations.rb +3 -3
  57. data/lib/aspera/transfer/parameters.rb +6 -6
  58. data/lib/aspera/transfer/spec.schema.yaml +4 -4
  59. data/lib/aspera/transfer/spec_doc.rb +11 -21
  60. data/lib/aspera/uri_reader.rb +17 -3
  61. data.tar.gz.sig +0 -0
  62. metadata +17 -2
  63. metadata.gz.sig +0 -0
@@ -3,11 +3,87 @@
3
3
  # cspell:words Magick MAGICKCORE ITERM mintty winsize termcap
4
4
 
5
5
  require 'rainbow'
6
+ require 'base64'
6
7
  require 'io/console'
7
8
  require 'aspera/log'
8
9
  require 'aspera/environment'
10
+
9
11
  module Aspera
10
12
  module Preview
13
+ module Backend
14
+ # provides image pixels scaled to terminal
15
+ class Base
16
+ def initialize(reserve:, double:, font_ratio:)
17
+ @reserve = reserve
18
+ @height_ratio = double ? 2.0 : 1.0
19
+ @font_ratio = font_ratio
20
+ end
21
+ Aspera.require_method!(:terminal_pixels)
22
+ # compute scaling to fit terminal
23
+ def terminal_scaling(rows, columns)
24
+ (term_rows, term_columns) = IO.console.winsize || [24, 80]
25
+ term_rows = [term_rows - @reserve, 2].max
26
+ fit_term_ratio = [term_rows.to_f * @font_ratio / rows.to_f, term_columns.to_f / columns.to_f].min
27
+ [(columns * fit_term_ratio).to_i, (rows * fit_term_ratio * @height_ratio / @font_ratio).to_i]
28
+ end
29
+ end
30
+
31
+ class RMagick < Base
32
+ def initialize(blob, **kwargs)
33
+ super(**kwargs)
34
+ # do not require statically, as the package is optional
35
+ require 'rmagick' # https://rmagick.github.io/index.html
36
+ @image = Magick::ImageList.new.from_blob(blob)
37
+ end
38
+
39
+ def terminal_pixels
40
+ # quantum depth is 8 or 16, see: `magick xc: -format "%q" info:`
41
+ shift_for_8_bit = Magick::MAGICKCORE_QUANTUM_DEPTH - 8
42
+ # get all pixel colors, adjusted for Rainbow
43
+ pixel_colors = []
44
+ @image.scale(*terminal_scaling(@image.rows, @image.columns)).each_pixel do |pixel, col, row|
45
+ pixel_rgb = [pixel.red, pixel.green, pixel.blue]
46
+ pixel_rgb = pixel_rgb.map{ |color| color >> shift_for_8_bit} unless shift_for_8_bit.eql?(0)
47
+ # init 2-dim array
48
+ pixel_colors[row] ||= []
49
+ pixel_colors[row][col] = pixel_rgb
50
+ end
51
+ pixel_colors
52
+ end
53
+ end
54
+
55
+ class ChunkyPNG < Base
56
+ def initialize(blob, **kwargs)
57
+ super(**kwargs)
58
+ require 'chunky_png'
59
+ @png = ::ChunkyPNG::Image.from_blob(blob)
60
+ end
61
+
62
+ def terminal_pixels
63
+ src_w = @png.width
64
+ src_h = @png.height
65
+ dst_w, dst_h = terminal_scaling(src_h, src_w)
66
+ dst_w = [dst_w, 1].max
67
+ dst_h = [dst_h, 1].max
68
+ pixel_colors = Array.new(dst_h){Array.new(dst_w)}
69
+ x_ratio = src_w.to_f / dst_w
70
+ y_ratio = src_h.to_f / dst_h
71
+ dst_h.times do |dy|
72
+ sy = (dy * y_ratio).floor
73
+ sy = src_h - 1 if sy >= src_h
74
+ dst_w.times do |dx|
75
+ sx = (dx * x_ratio).floor
76
+ sx = src_w - 1 if sx >= src_w
77
+ rgba = @png.get_pixel(sx, sy)
78
+ # ChunkyPNG stores as 0xRRGGBBAA; extract 8-bit channels
79
+ pixel_colors[dy][dx] = %i[r g b].map{ |i| ::ChunkyPNG::Color.send(i, rgba)}
80
+ end
81
+ end
82
+ pixel_colors
83
+ end
84
+ end
85
+ end
86
+
11
87
  # Display a picture in the terminal.
12
88
  # Either use coloured characters or iTerm2 protocol.
13
89
  class Terminal
@@ -22,41 +98,31 @@ module Aspera
22
98
  private_constant :TERM_ENV_VARS, :ITERM_NAMES, :DEFAULT_FONT_RATIO
23
99
  class << self
24
100
  # @param blob [String] The image as a binary string
25
- # @param reserve [Integer] Number of lines to reserve for other text than the image
26
101
  # @param text [Boolean] `true` to display the image as text, `false` to use iTerm2 if supported
102
+ # @param reserve [Integer] Number of lines to reserve for other text than the image
27
103
  # @param double [Boolean] `true` to use colors on half lines, `false` to use colors on full lines
28
104
  # @param font_ratio [Float] ratio = font height / font width
29
105
  # @return [String] The image as text, or the iTerm2 escape sequence
30
- def build(blob, reserve: 3, text: false, double: true, font_ratio: DEFAULT_FONT_RATIO)
106
+ def build(blob, text: false, reserve: 3, double: true, font_ratio: DEFAULT_FONT_RATIO)
31
107
  return '[Image display requires a terminal]' unless Environment.terminal?
32
108
  return iterm_display_image(blob) if iterm_supported? && !text
33
- begin
34
- # do not require statically, as the package is optional
35
- require 'rmagick' # https://rmagick.github.io/index.html
36
- rescue LoadError => e
37
- Log.log.error('Install missing gem: gem install rmagick')
38
- # fallback to iterm, if supported
109
+ pixel_colors =
110
+ begin
111
+ Log.log.debug('Trying chunky_png')
112
+ Backend::ChunkyPNG.new(blob, reserve: reserve, double: double, font_ratio: font_ratio).terminal_pixels
113
+ rescue => e
114
+ Log.log.debug(e.message)
115
+ begin
116
+ Log.log.debug('Trying rmagick')
117
+ Backend::RMagick.new(blob, reserve: reserve, double: double, font_ratio: font_ratio).terminal_pixels
118
+ rescue => e
119
+ Log.log.debug(e.message)
120
+ nil
121
+ end
122
+ end
123
+ if pixel_colors.nil?
39
124
  return iterm_display_image(blob) if iterm_supported?
40
- Log.log.error('Cant display picture.')
41
- raise e
42
- end
43
- image = Magick::ImageList.new.from_blob(blob)
44
- (term_rows, term_columns) = IO.console.winsize
45
- term_rows -= reserve
46
- # compute scaling to fit terminal
47
- fit_term_ratio = [term_rows.to_f * font_ratio / image.rows.to_f, term_columns.to_f / image.columns.to_f].min
48
- height_ratio = double ? 2.0 : 1.0
49
- image = image.scale((image.columns * fit_term_ratio).to_i, (image.rows * fit_term_ratio * height_ratio / font_ratio).to_i)
50
- # quantum depth is 8 or 16, see: `magick xc: -format "%q" info:`
51
- shift_for_8_bit = Magick::MAGICKCORE_QUANTUM_DEPTH - 8
52
- # get all pixel colors, adjusted for Rainbow
53
- pixel_colors = []
54
- image.each_pixel do |pixel, col, row|
55
- pixel_rgb = [pixel.red, pixel.green, pixel.blue]
56
- pixel_rgb = pixel_rgb.map{ |color| color >> shift_for_8_bit} unless shift_for_8_bit.eql?(0)
57
- # init 2-dim array
58
- pixel_colors[row] ||= []
59
- pixel_colors[row][col] = pixel_rgb
125
+ raise 'Cannot decode picture.'
60
126
  end
61
127
  # now generate text
62
128
  text_pixels = []
@@ -88,7 +154,7 @@ module Aspera
88
154
  }.map{ |k, v| "#{k}=#{v}"}.join(';')
89
155
  # \a is BEL, \e is ESC : https://github.com/ruby/ruby/blob/master/doc/syntax/literals.rdoc#label-Strings
90
156
  # escape sequence for iTerm2 image display
91
- return "\e]1337;File=#{arguments}:#{Base64.encode64(blob)}\a"
157
+ return "\e]1337;File=#{arguments}:#{Base64.strict_encode64(blob)}\a"
92
158
  end
93
159
 
94
160
  # @return [Boolean] true if the terminal supports iTerm2 image display
@@ -44,17 +44,18 @@ module Aspera
44
44
  end
45
45
  end
46
46
 
47
- # execute external command
48
- # one could use "system", but we would need to redirect stdout/err
49
- # @return nil
47
+ # Execute external command
48
+ # @return [nil]
50
49
  def external_command(command_sym, command_args)
51
50
  Aspera.assert_values(command_sym, EXTERNAL_TOOLS){'command'}
52
- Environment.secure_execute(exec: command_sym.to_s, args: command_args.map(&:to_s), out: File::NULL, err: File::NULL)
51
+ Environment.secure_execute(command_sym.to_s, *command_args.map(&:to_s), out: File::NULL, err: File::NULL)
53
52
  end
54
53
 
54
+ # Execute external command and capture output
55
+ # @return [String]
55
56
  def external_capture(command_sym, command_args)
56
57
  Aspera.assert_values(command_sym, EXTERNAL_TOOLS){'command'}
57
- return Environment.secure_capture(exec: command_sym.to_s, args: command_args.map(&:to_s))
58
+ return Environment.secure_execute(command_sym.to_s, *command_args.map(&:to_s), mode: :capture)
58
59
  end
59
60
 
60
61
  def ffmpeg(gl_p: FFMPEG_DEFAULT_PARAMS, in_p: [], in_f:, out_p: [], out_f:)
data/lib/aspera/rest.rb CHANGED
@@ -307,9 +307,12 @@ module Aspera
307
307
  # @param body [Hash, String] body parameters
308
308
  # @param headers [Hash] additional headers (override Content-Type)
309
309
  # @param save_to_file [String, nil](filepath)
310
- # @param exception [Bool] `true`, error raise exception
310
+ # @param exception [Boolean] `true`, error raise exception
311
311
  # @param ret [:data, :resp, :both] Tell to return only data, only http response, or both
312
- # @return [Object, Array] only data, only http response, or both
312
+ # @return [(HTTPResponse,Hash)] If ret is :both
313
+ # @return [HTTPResponse] If ret is :resp
314
+ # @return [Hash] If ret is :data
315
+ # @raise [RestCallError] on error if `exception` is true
313
316
  def call(
314
317
  operation:,
315
318
  subpath: nil,
data/lib/aspera/ssh.rb CHANGED
@@ -35,16 +35,17 @@ module Aspera
35
35
  # ssh_options: same as Net::SSH.start
36
36
  # see: https://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start
37
37
  def initialize(host, username, ssh_options)
38
- Log.log.debug{"ssh:#{username}@#{host}"}
39
- Log.log.debug{"ssh_options:#{ssh_options}"}
40
38
  Aspera.assert_type(host, String)
41
39
  Aspera.assert_type(username, String)
42
40
  Aspera.assert_type(ssh_options, Hash)
43
- ssh_options[:use_agent] = false unless ssh_options.key?(:use_agent)
44
41
  @host = host
45
42
  @username = username
46
- @ssh_options = ssh_options
47
- @ssh_options[:logger] = Log.log
43
+ @ssh_options = ssh_options.dup
44
+ @ssh_options[:logger] = Log.log unless @ssh_options.key?(:logger)
45
+ @ssh_options[:verbose] = :warn unless @ssh_options.key?(:verbose)
46
+ @ssh_options[:use_agent] = false unless @ssh_options.key?(:use_agent)
47
+ Log.log.debug{"ssh:#{@username}@#{@host}"}
48
+ Log.dump(:ssh_options, @ssh_options)
48
49
  end
49
50
 
50
51
  # Anything on stderr raises an exception
@@ -4,8 +4,8 @@ description: Async session description, identical to `asyncs` Node API.
4
4
  $comment: >-
5
5
  This is a YAML version of the original JSON schema from asyncs API.
6
6
  It is modified with special `x-` fields.
7
- x-ts-name [Bool,String] `true` if same name in transfer spec, else real name in transfer spec
8
- x-ts-convert [String] Name of methods to convert value from transfer spec to `conf`
7
+ x-ts-name [Boolean,String] `true` if same name in transfer spec, else real name in transfer spec
8
+ x-ts-convert [String] Name of methods to convert value from transfer spec to `conf`
9
9
  `x-` fields are also documented in `command_line_builder.rb`
10
10
  type: object
11
11
  required:
@@ -146,7 +146,7 @@ module Aspera
146
146
  session_builder.process_params
147
147
  session_builder.add_env_args(env_args)
148
148
  end
149
- Environment.secure_execute(exec: Ascp::Installation.instance.path(:async), **env_args)
149
+ Environment.secure_execute(Ascp::Installation.instance.path(:async), *env_args[:args], env: env_args[:env])
150
150
  end
151
151
  return
152
152
  end
@@ -174,7 +174,7 @@ module Aspera
174
174
  # @return [Hash] parsed output of asyncadmin
175
175
  def admin_status(sync_info)
176
176
  Aspera.assert(PARAM_KEYS.any?{ |k| sync_info.key?(k)}, type: Error){'At least one of `local` or `sessions` must be present in async parameters'}
177
- arguments = ['--quiet']
177
+ arguments = [ASYNC_ADMIN_EXECUTABLE, '--quiet']
178
178
  if sync_info.key?('local')
179
179
  # `conf` format
180
180
  arguments.push("--name=#{sync_info['name']}")
@@ -197,7 +197,7 @@ module Aspera
197
197
  raise Error, 'Missing either local_db_dir or local_dir'
198
198
  end
199
199
  end
200
- stdout = Environment.secure_capture(exec: ASYNC_ADMIN_EXECUTABLE, args: arguments)
200
+ stdout = Environment.secure_execute(*arguments, mode: :capture)
201
201
  return parse_status(stdout)
202
202
  end
203
203
 
@@ -45,12 +45,12 @@ module Aspera
45
45
  end
46
46
  end
47
47
 
48
- # @param job_spec [Hash] Transfer spec
49
- # @param ascp_args [Array] Other ascp args
50
- # @param quiet [Bool] Remove ascp output
51
- # @param trusted_certs [Array] Trusted certificates
52
- # @param client_ssh_key [Symbol] :rsa or :dsa
53
- # @param check_ignore_cb [Proc] Callback
48
+ # @param job_spec [Hash] Transfer spec
49
+ # @param ascp_args [Array] Other ascp args
50
+ # @param quiet [Boolean] Remove ascp output
51
+ # @param trusted_certs [Array] Trusted certificates
52
+ # @param client_ssh_key [:rsa,:dsa] :rsa or :dsa
53
+ # @param check_ignore_cb [Proc] Callback
54
54
  def initialize(
55
55
  job_spec,
56
56
  ascp_args: nil,
@@ -7,8 +7,8 @@ $comment: >-
7
7
  The following extensions are used for mapping to ascp arguments.
8
8
  x-cli-envvar [String] Name of env var
9
9
  x-cli-option [String] Command line option (starts with "-"), or `true`: same as ts, or `false`: not an option
10
- x-cli-switch [Bool] `true` if option has no arg, else by default option has a value
11
- x-cli-special [Bool] `true` if not anaged by command line generator (special handling: option or argument)
10
+ x-cli-switch [Boolean] `true` if option has no arg, else by default option has a value
11
+ x-cli-special [Boolean] `true` if not anaged by command line generator (special handling: option or argument)
12
12
  x-cli-convert [String,Hash] Method name for Convert object or Conversion Hash for enum: ts to arg
13
13
  x-agents [Array] Supported agents (for doc only), if not specified: all
14
14
  x-deprecation [String] Deprecation message for doc
@@ -106,7 +106,7 @@ properties:
106
106
  delete_source:
107
107
  $comment: "TODO: implement"
108
108
  description: >-
109
- Remove transfered source files after transfer success.
109
+ Remove transferred source files after transfer success.
110
110
  Equivalent to `remove_after_transfer` + `remove_empty_directories` + `remove_empty_source_directory`.
111
111
  Take precedence over those.
112
112
  type: boolean
@@ -881,7 +881,7 @@ properties:
881
881
  xfer_max_retries:
882
882
  description: >-
883
883
  Maximum number of retries, for node API initiated transfers.
884
- Shall not exceed aspera.conf `transfer_manager_max_retries` (default 5).
884
+ Shall not exceed `aspera.conf` parameter `transfer_manager_max_retries` (default 5).
885
885
  type: integer
886
886
  x-agents:
887
887
  - node
@@ -8,20 +8,14 @@ module Aspera
8
8
  # Generate documentation from Schema, for Transfer Spec, or async Conf spec
9
9
  class SpecDoc
10
10
  class << self
11
- # First letter of agent name symbol
12
- def agent_to_short(agent_sym)
13
- agent_sym.to_sym.eql?(:direct) ? :a : agent_sym.to_s[0].to_sym
14
- end
15
-
16
- # @param formatter [Cli::Formatter] Formatter to use, methods: markdown, tick, check_row
11
+ # @param formatter [Cli::Formatter] Formatter to use, methods: markdown_text, tick, check_row
17
12
  # @param include_option [Boolean] `true` : include CLI options
18
13
  # @param agent_columns [Boolean] `true` : include agents columns
19
14
  # @param schema [Hash] The JSON spec
20
15
  # @return [Array] a table suitable to display in manual
21
16
  def man_table(formatter, include_option: false, agent_columns: true, schema: Spec::SCHEMA)
22
- col_local = agent_to_short(:direct)
23
17
  cols = %i[name type description]
24
- cols.insert(-2, *AGENT_LIST.map(&:last)) if agent_columns
18
+ cols.insert(-2, *Agent::Factory::ALL.values.map{ |i| i[:short]}.sort) if agent_columns
25
19
  rows = []
26
20
  schema['properties'].each do |name, info|
27
21
  rows.concat(man_table(formatter, include_option: include_option, agent_columns: agent_columns, schema: info).last.map{ |h| h.merge(name: "#{name}.#{h[:name]}")}) if info['type'].eql?('object') && info['properties']
@@ -35,25 +29,25 @@ module Aspera
35
29
  # Render Markdown formatting and split lines
36
30
  columns[:description] =
37
31
  info['description']
38
- .gsub(Markdown::FORMATS){formatter.markdown(Regexp.last_match)}
32
+ .gsub(Markdown::FORMATS){formatter.markdown_text(Regexp.last_match)}
39
33
  .split("\n") if info.key?('description')
40
34
  columns[:description].unshift("DEPRECATED: #{info['x-deprecation']}") if info.key?('x-deprecation')
41
35
  # Add flags for supported agents in doc
42
36
  agents = []
43
- AGENT_LIST.each do |agent_info|
44
- agents.push(agent_info.last) if info['x-agents'].nil? || info['x-agents'].include?(agent_info.first.to_s)
37
+ Agent::Factory::ALL.each_key do |sym|
38
+ agents.push(sym) if info['x-agents'].nil? || info['x-agents'].include?(sym.to_s)
45
39
  end
46
- Aspera.assert(agents.include?(col_local)){"#{name}: x-cli-option requires agent direct (or nil)"} if info['x-cli-option']
40
+ Aspera.assert(agents.include?(:direct)){"#{name}: x-cli-option requires agent direct (or nil)"} if info['x-cli-option']
47
41
  if agent_columns
48
- AGENT_LIST.each do |agent_info|
49
- columns[agent_info.last] = formatter.tick(agents.include?(agent_info.last))
42
+ Agent::Factory::ALL.each do |sym, names|
43
+ columns[names[:short]] = formatter.tick(agents.include?(sym))
50
44
  end
51
45
  else
52
- columns[:description].push("(#{agents.map(&:upcase).join(', ')})") unless agents.length.eql?(AGENT_LIST.length)
46
+ columns[:description].push("(#{agents.map{ |i| Agent::Factory::ALL[i][:short].to_s.upcase}.sort.join(', ')})") unless agents.length.eql?(Agent::Factory::ALL.length)
53
47
  end
54
48
  # Only keep lines that are usable in supported agents
55
49
  next false if agents.empty?
56
- columns[:description].push("Allowed values: #{info['enum'].map{ |v| formatter.markdown("`#{v}`")}.join(', ')}") if info.key?('enum')
50
+ columns[:description].push("Allowed values: #{info['enum'].map{ |v| formatter.markdown_text("`#{v}`")}.join(', ')}") if info.key?('enum')
57
51
  if include_option
58
52
  envvar_prefix = ''
59
53
  cli_option =
@@ -70,17 +64,13 @@ module Aspera
70
64
  "#{info['x-cli-option']}#{sep}#{"(#{conversion_tag})" if conversion_tag}#{arg_type}"
71
65
  end
72
66
  short = info.key?('x-cli-short') ? "(#{info['x-cli-short']})" : nil
73
- columns[:description].push("(#{'special:' if info['x-cli-special']}#{envvar_prefix}#{formatter.markdown("`#{cli_option}`")})#{short}") if cli_option
67
+ columns[:description].push("(#{'special:' if info['x-cli-special']}#{envvar_prefix}#{formatter.markdown_text("`#{cli_option}`")})#{short}") if cli_option
74
68
  end
75
69
  rows.push(formatter.check_row(columns))
76
70
  end
77
71
  [cols, rows.sort_by{ |i| i[:name]}]
78
72
  end
79
73
  end
80
- # Agents shown in manual for parameters (sub list)
81
- AGENT_LIST = Agent::Factory.instance.list.map do |agent_sym|
82
- [agent_sym, agent_sym.to_s.capitalize, agent_to_short(agent_sym)]
83
- end.sort_by(&:last).freeze
84
74
  end
85
75
  end
86
76
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'uri'
4
+ require 'base64'
4
5
  require 'aspera/assert'
5
6
  require 'aspera/rest'
6
7
  require 'aspera/temp_file_manager'
@@ -19,6 +20,13 @@ module Aspera
19
20
  case uri.scheme
20
21
  when 'http', 'https'
21
22
  return Rest.new(base_url: uri_to_read, redirect_max: 5).read(nil, headers: {'Accept' => '*/*'})
23
+ when 'data'
24
+ metadata, encoded_data = uri.opaque.split(',', 2)
25
+ if metadata.end_with?(';base64')
26
+ Base64.decode64(encoded_data)
27
+ else
28
+ URI.decode_www_form_component(encoded_data)
29
+ end
22
30
  when SCHEME_FILE, NilClass
23
31
  local_file_path = uri.path
24
32
  raise Error, 'URL shall have a path, check syntax' if local_file_path.nil?
@@ -35,12 +43,18 @@ module Aspera
35
43
  # require specific file scheme: the path part is "relative", or absolute if there are 4 slash
36
44
  raise "use format: #{SCHEME_FILE_PFX2}<path>" unless url.start_with?(SCHEME_FILE_PFX2)
37
45
  return File.expand_path(url[SCHEME_FILE_PFX2.length..-1])
46
+ elsif url.start_with?('data:')
47
+ # download to temp file
48
+ # auto-delete on exit
49
+ temp_file = TempFileManager.instance.new_file_path_global('uri_reader')
50
+ File.write(temp_file, read(url), binmode: true)
51
+ return temp_file
38
52
  else
39
53
  # download to temp file
40
54
  # auto-delete on exit
41
- sdk_archive_path = TempFileManager.instance.new_file_path_global(suffix: File.basename(url))
42
- Aspera::Rest.new(base_url: url, redirect_max: 3).call(operation: 'GET', save_to_file: sdk_archive_path)
43
- return sdk_archive_path
55
+ temp_file = TempFileManager.instance.new_file_path_global(suffix: File.basename(url))
56
+ Aspera::Rest.new(base_url: url, redirect_max: 3).call(operation: 'GET', save_to_file: temp_file)
57
+ return temp_file
44
58
  end
45
59
  end
46
60
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aspera-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.25.0.pre
4
+ version: 4.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Laurent Martin
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: chunky_png
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: csv
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -353,6 +367,7 @@ files:
353
367
  - lib/aspera/data/5
354
368
  - lib/aspera/data/6
355
369
  - lib/aspera/data_repository.rb
370
+ - lib/aspera/dot_container.rb
356
371
  - lib/aspera/environment.rb
357
372
  - lib/aspera/faspex_gw.rb
358
373
  - lib/aspera/faspex_postproc.rb
@@ -442,7 +457,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
442
457
  version: '0'
443
458
  requirements:
444
459
  - Read the manual for any requirement
445
- rubygems_version: 3.6.9
460
+ rubygems_version: 4.0.3
446
461
  specification_version: 4
447
462
  summary: 'Execute actions using command line on IBM Aspera Server products: Aspera
448
463
  on Cloud, Faspex, Shares, Node, Console, Orchestrator, High Speed Transfer Server'
metadata.gz.sig CHANGED
Binary file