aspera-cli 4.15.0 → 4.16.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 (80) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BUGS.md +29 -3
  4. data/CHANGELOG.md +292 -228
  5. data/CONTRIBUTING.md +69 -18
  6. data/README.md +1102 -952
  7. data/bin/ascli +13 -31
  8. data/bin/asession +3 -1
  9. data/examples/dascli +2 -2
  10. data/lib/aspera/aoc.rb +28 -33
  11. data/lib/aspera/ascmd.rb +3 -6
  12. data/lib/aspera/assert.rb +45 -0
  13. data/lib/aspera/cli/extended_value.rb +5 -5
  14. data/lib/aspera/cli/formatter.rb +26 -13
  15. data/lib/aspera/cli/hints.rb +4 -3
  16. data/lib/aspera/cli/main.rb +16 -3
  17. data/lib/aspera/cli/manager.rb +45 -36
  18. data/lib/aspera/cli/plugin.rb +20 -13
  19. data/lib/aspera/cli/plugins/aoc.rb +103 -73
  20. data/lib/aspera/cli/plugins/ats.rb +4 -3
  21. data/lib/aspera/cli/plugins/config.rb +114 -119
  22. data/lib/aspera/cli/plugins/cos.rb +2 -2
  23. data/lib/aspera/cli/plugins/faspex.rb +23 -19
  24. data/lib/aspera/cli/plugins/faspex5.rb +75 -43
  25. data/lib/aspera/cli/plugins/node.rb +28 -15
  26. data/lib/aspera/cli/plugins/orchestrator.rb +4 -2
  27. data/lib/aspera/cli/plugins/preview.rb +9 -7
  28. data/lib/aspera/cli/plugins/server.rb +6 -3
  29. data/lib/aspera/cli/plugins/shares.rb +30 -26
  30. data/lib/aspera/cli/sync_actions.rb +9 -9
  31. data/lib/aspera/cli/transfer_agent.rb +21 -14
  32. data/lib/aspera/cli/transfer_progress.rb +2 -3
  33. data/lib/aspera/cli/version.rb +1 -1
  34. data/lib/aspera/command_line_builder.rb +13 -11
  35. data/lib/aspera/cos_node.rb +3 -2
  36. data/lib/aspera/coverage.rb +22 -0
  37. data/lib/aspera/data_repository.rb +33 -2
  38. data/lib/aspera/environment.rb +4 -2
  39. data/lib/aspera/fasp/{agent_aspera.rb → agent_alpha.rb} +29 -39
  40. data/lib/aspera/fasp/agent_base.rb +17 -7
  41. data/lib/aspera/fasp/agent_direct.rb +88 -84
  42. data/lib/aspera/fasp/agent_httpgw.rb +4 -3
  43. data/lib/aspera/fasp/agent_node.rb +3 -2
  44. data/lib/aspera/fasp/agent_trsdk.rb +79 -37
  45. data/lib/aspera/fasp/installation.rb +51 -12
  46. data/lib/aspera/fasp/management.rb +11 -6
  47. data/lib/aspera/fasp/parameters.rb +53 -47
  48. data/lib/aspera/fasp/resume_policy.rb +7 -5
  49. data/lib/aspera/fasp/sync.rb +273 -0
  50. data/lib/aspera/fasp/transfer_spec.rb +10 -8
  51. data/lib/aspera/fasp/uri.rb +2 -2
  52. data/lib/aspera/faspex_gw.rb +11 -8
  53. data/lib/aspera/faspex_postproc.rb +6 -5
  54. data/lib/aspera/id_generator.rb +3 -1
  55. data/lib/aspera/json_rpc.rb +10 -8
  56. data/lib/aspera/keychain/encrypted_hash.rb +46 -11
  57. data/lib/aspera/keychain/macos_security.rb +15 -13
  58. data/lib/aspera/log.rb +4 -3
  59. data/lib/aspera/nagios.rb +7 -2
  60. data/lib/aspera/node.rb +17 -16
  61. data/lib/aspera/node_simulator.rb +214 -0
  62. data/lib/aspera/oauth.rb +22 -19
  63. data/lib/aspera/persistency_action_once.rb +13 -14
  64. data/lib/aspera/persistency_folder.rb +3 -2
  65. data/lib/aspera/preview/file_types.rb +53 -267
  66. data/lib/aspera/preview/generator.rb +7 -5
  67. data/lib/aspera/preview/terminal.rb +14 -5
  68. data/lib/aspera/preview/utils.rb +8 -7
  69. data/lib/aspera/proxy_auto_config.rb +6 -3
  70. data/lib/aspera/rest.rb +29 -13
  71. data/lib/aspera/rest_error_analyzer.rb +1 -0
  72. data/lib/aspera/rest_errors_aspera.rb +2 -0
  73. data/lib/aspera/secret_hider.rb +5 -2
  74. data/lib/aspera/ssh.rb +10 -8
  75. data/lib/aspera/temp_file_manager.rb +1 -1
  76. data/lib/aspera/web_server_simple.rb +2 -1
  77. data.tar.gz.sig +0 -0
  78. metadata +96 -45
  79. metadata.gz.sig +0 -0
  80. data/lib/aspera/sync.rb +0 -219
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'aspera/log'
4
4
  require 'singleton'
5
+ require 'mime/types'
5
6
 
6
7
  module Aspera
7
8
  module Preview
@@ -11,266 +12,41 @@ module Aspera
11
12
  # values for conversion_type : input format
12
13
  CONVERSION_TYPES = %i[image office pdf plaintext video].freeze
13
14
 
14
- # define how files are processed based on mime type
15
+ # special cases for mime types
15
16
  # spellchecker:disable
16
17
  SUPPORTED_MIME_TYPES = {
17
- 'application/json' => :plaintext,
18
- 'application/mac-binhex40' => :office,
19
- 'application/msword' => :office,
20
- 'application/pdf' => :pdf,
21
- 'application/postscript' => :image,
22
- 'application/rtf' => :office,
23
- 'application/vnd.3gpp.pic-bw-small' => :image,
24
- 'application/vnd.hp-hpgl' => :image,
25
- 'application/vnd.hp-pcl' => :image,
26
- 'application/vnd.lotus-wordpro' => :office,
27
- 'application/vnd.mobius.msl' => :image,
28
- 'application/vnd.mophun.certificate' => :image,
29
- 'application/vnd.ms-excel' => :office,
30
- 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => :office,
31
- 'application/vnd.ms-excel.sheet.macroenabled.12' => :office,
32
- 'application/vnd.ms-excel.template.macroenabled.12' => :office,
33
- 'application/vnd.ms-powerpoint' => :office,
34
- 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => :office,
35
- 'application/vnd.ms-powerpoint.template.macroenabled.12' => :office,
36
- 'application/vnd.ms-word.document.macroenabled.12' => :office,
37
- 'application/vnd.ms-word.template.macroenabled.12' => :office,
38
- 'application/vnd.ms-works' => :office,
39
- 'application/vnd.oasis.opendocument.chart' => :office,
40
- 'application/vnd.oasis.opendocument.formula' => :office,
41
- 'application/vnd.oasis.opendocument.graphics' => :office,
42
- 'application/vnd.oasis.opendocument.graphics-template' => :office,
43
- 'application/vnd.oasis.opendocument.presentation' => :office,
44
- 'application/vnd.oasis.opendocument.presentation-template' => :office,
45
- 'application/vnd.oasis.opendocument.spreadsheet' => :office,
46
- 'application/vnd.oasis.opendocument.spreadsheet-template' => :office,
47
- 'application/vnd.oasis.opendocument.text' => :office,
48
- 'application/vnd.oasis.opendocument.text-template' => :office,
49
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => :office,
50
- 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => :office,
51
- 'application/vnd.openxmlformats-officedocument.presentationml.template' => :office,
52
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => :office,
53
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => :office,
54
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => :office,
55
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => :office,
56
- 'application/vnd.palm' => :office,
57
- 'application/vnd.sun.xml.calc' => :office,
58
- 'application/vnd.sun.xml.calc.template' => :office,
59
- 'application/vnd.sun.xml.draw' => :office,
60
- 'application/vnd.sun.xml.draw.template' => :office,
61
- 'application/vnd.sun.xml.impress' => :office,
62
- 'application/vnd.sun.xml.impress.template' => :office,
63
- 'application/vnd.sun.xml.math' => :office,
64
- 'application/vnd.sun.xml.writer' => :office,
65
- 'application/vnd.sun.xml.writer.template' => :office,
66
- 'application/vnd.wordperfect' => :office,
67
- 'application/x-abiword' => :office,
68
- 'application/x-director' => :image,
69
- 'application/x-font-type1' => :image,
70
- 'application/x-msmetafile' => :image,
71
- 'application/x-mspublisher' => :office,
72
- 'application/x-xfig' => :image,
73
- 'audio/ogg' => :video,
74
- 'font/ttf' => :image,
75
- 'image/bmp' => :image,
76
- 'image/cgm' => :image,
77
- 'image/gif' => :image,
78
- 'image/jpeg' => :image,
79
- 'image/png' => :image,
80
- 'image/sgi' => :image,
81
- 'image/svg+xml' => :image,
82
- 'image/tiff' => :image,
83
- 'image/vnd.adobe.photoshop' => :image,
84
- 'image/vnd.djvu' => :image,
85
- 'image/vnd.dxf' => :office,
86
- 'image/vnd.fpx' => :image,
87
- 'image/vnd.ms-photo' => :image,
88
- 'image/vnd.wap.wbmp' => :image,
89
- 'image/webp' => :image,
90
- 'image/x-cmx' => :office,
91
- 'image/x-freehand' => :office,
92
- 'image/x-icon' => :image,
93
- 'image/x-mrsid-image' => :image,
94
- 'image/x-pcx' => :image,
95
- 'image/x-pict' => :office,
96
- 'image/x-portable-anymap' => :image,
97
- 'image/x-portable-bitmap' => :image,
98
- 'image/x-portable-graymap' => :image,
99
- 'image/x-portable-pixmap' => :image,
100
- 'image/x-rgb' => :image,
101
- 'image/x-tga' => :image,
102
- 'image/x-xbitmap' => :image,
103
- 'image/x-xpixmap' => :image,
104
- 'image/x-xwindowdump' => :image,
105
- 'text/csv' => :office,
106
- 'text/html' => :office,
107
- 'text/plain' => :plaintext,
108
- 'text/troff' => :image,
109
- 'video/h261' => :video,
110
- 'video/h263' => :video,
111
- 'video/h264' => :video,
112
- 'video/mp4' => :video,
113
- 'video/mpeg' => :video,
114
- 'video/quicktime' => :video,
115
- 'video/x-flv' => :video,
116
- 'video/x-m4v' => :video,
117
- 'video/x-matroska' => :video,
118
- 'video/x-mng' => :image,
119
- 'video/x-ms-wmv' => :video,
120
- 'video/x-msvideo' => :video}.freeze
18
+ 'application/json' => :plaintext,
19
+ 'text/plain' => :plaintext,
20
+ 'application/pdf' => :pdf,
21
+ 'audio/ogg' => :video,
22
+ 'application/mxf' => :video,
23
+ 'application/mac-binhex40' => :office,
24
+ 'application/msword' => :office,
25
+ 'application/rtf' => :office,
26
+ 'application/x-abiword' => :office,
27
+ 'application/x-mspublisher' => :office,
28
+ 'image/vnd.dxf' => :office,
29
+ 'image/x-cmx' => :office,
30
+ 'image/x-freehand' => :office,
31
+ 'image/x-pict' => :office,
32
+ 'text/csv' => :office,
33
+ 'text/html' => :office,
34
+ 'application/dicom' => :image,
35
+ 'application/postscript' => :image,
36
+ 'application/vnd.3gpp.pic-bw-small' => :image,
37
+ 'application/vnd.hp-hpgl' => :image,
38
+ 'application/vnd.hp-pcl' => :image,
39
+ 'application/vnd.mobius.msl' => :image,
40
+ 'application/vnd.mophun.certificate' => :image,
41
+ 'application/x-director' => :image,
42
+ 'application/x-font-type1' => :image,
43
+ 'application/x-msmetafile' => :image,
44
+ 'application/x-xfig' => :image,
45
+ 'font/ttf' => :image,
46
+ 'text/troff' => :image,
47
+ 'video/x-mng' => :image}.freeze
121
48
 
122
- # this is a way to add support for extensions that are otherwise not known by node api (mime type)
123
- SUPPORTED_EXTENSIONS = {
124
- 'aai' => :image,
125
- 'art' => :image,
126
- 'arw' => :image,
127
- 'avs' => :image,
128
- 'bmp2' => :image,
129
- 'bmp3' => :image,
130
- 'bpg' => :image,
131
- 'cals' => :image,
132
- 'cdr' => :office,
133
- 'cin' => :image,
134
- 'clipboard' => :image,
135
- 'cmyk' => :image,
136
- 'cmyka' => :image,
137
- 'cr2' => :image,
138
- 'crw' => :image,
139
- 'cur' => :image,
140
- 'cut' => :image,
141
- 'cwk' => :office,
142
- 'dbf' => :office,
143
- 'dcm' => :image,
144
- 'dcx' => :image,
145
- 'dds' => :image,
146
- 'dib' => :image,
147
- 'dif' => :office,
148
- 'divx' => :video,
149
- 'dng' => :image,
150
- 'docx' => :office,
151
- 'dpx' => :image,
152
- 'epdf' => :image,
153
- 'epi' => :image,
154
- 'eps2' => :image,
155
- 'eps3' => :image,
156
- 'epsf' => :image,
157
- 'epsi' => :image,
158
- 'ept' => :image,
159
- 'exr' => :image,
160
- 'fax' => :image,
161
- 'fb2' => :office,
162
- 'fits' => :image,
163
- 'fodg' => :office,
164
- 'fodp' => :office,
165
- 'fods' => :office,
166
- 'fodt' => :office,
167
- 'gplt' => :image,
168
- 'gray' => :image,
169
- 'hdr' => :image,
170
- 'hpw' => :office,
171
- 'hrz' => :image,
172
- 'info' => :image,
173
- 'inline' => :image,
174
- 'j2c' => :image,
175
- 'j2k' => :image,
176
- 'jbig' => :image,
177
- 'jng' => :image,
178
- 'jp2' => :image,
179
- 'jpt' => :image,
180
- 'jxr' => :image,
181
- 'key' => :office,
182
- 'log' => :plaintext,
183
- 'mat' => :image,
184
- 'mcw' => :office,
185
- 'met' => :office,
186
- 'miff' => :image,
187
- 'mml' => :office,
188
- 'mono' => :image,
189
- 'mpr' => :image,
190
- 'mrsid' => :image,
191
- 'mrw' => :image,
192
- 'mtv' => :image,
193
- 'mvg' => :image,
194
- 'mw' => :office,
195
- 'mwd' => :office,
196
- 'mxf' => :video,
197
- 'nef' => :image,
198
- 'numbers' => :office,
199
- 'orf' => :image,
200
- 'otb' => :image,
201
- 'p7' => :image,
202
- 'pages' => :office,
203
- 'palm' => :image,
204
- 'pam' => :image,
205
- 'pcd' => :image,
206
- 'pcds' => :image,
207
- 'pdf' => :pdf,
208
- 'pef' => :image,
209
- 'picon' => :image,
210
- 'pict' => :image,
211
- 'pix' => :image,
212
- 'pm' => :office,
213
- 'pm6' => :office,
214
- 'pmd' => :office,
215
- 'png00' => :image,
216
- 'png24' => :image,
217
- 'png32' => :image,
218
- 'png48' => :image,
219
- 'png64' => :image,
220
- 'png8' => :image,
221
- 'ps2' => :image,
222
- 'ps3' => :image,
223
- 'ptif' => :image,
224
- 'pwp' => :image,
225
- 'rad' => :image,
226
- 'raf' => :image,
227
- 'rfg' => :image,
228
- 'rgba' => :image,
229
- 'rla' => :image,
230
- 'rle' => :image,
231
- 'sct' => :image,
232
- 'sfw' => :image,
233
- 'sgf' => :office,
234
- 'sgv' => :office,
235
- 'slk' => :office,
236
- 'sparse-color' => :image,
237
- 'sun' => :image,
238
- 'svm' => :office,
239
- 'sylk' => :office,
240
- 'tim' => :image,
241
- 'txt' => :plaintext,
242
- 'uil' => :image,
243
- 'uof' => :office,
244
- 'uop' => :office,
245
- 'uos' => :office,
246
- 'uot' => :office,
247
- 'uyvy' => :image,
248
- 'vds' => :office,
249
- 'vdx' => :office,
250
- 'vicar' => :image,
251
- 'viff' => :image,
252
- 'vsdx' => :office,
253
- 'webm' => :video,
254
- 'wb2' => :office,
255
- 'wk1' => :office,
256
- 'wk3' => :office,
257
- 'wn' => :office,
258
- 'wpg' => :image,
259
- 'wq1' => :office,
260
- 'wq2' => :office,
261
- 'x' => :image,
262
- 'x3f' => :image,
263
- 'xcf' => :image,
264
- 'xlk' => :office,
265
- 'xlsx' => :office,
266
- 'xls' => :office,
267
- 'ycbcr' => :image,
268
- 'ycbcra' => :image,
269
- 'yuv' => :image,
270
- 'zabw' => :office}.freeze
271
- # spellchecker:enable
272
-
273
- private_constant :SUPPORTED_MIME_TYPES, :SUPPORTED_EXTENSIONS
49
+ private_constant :SUPPORTED_MIME_TYPES
274
50
 
275
51
  # @attr use_mimemagic [bool] true to use mimemagic to determine real mime type based on file content
276
52
  attr_accessor :use_mimemagic
@@ -279,8 +55,18 @@ module Aspera
279
55
  @use_mimemagic = false
280
56
  end
281
57
 
58
+ # @param mimetype [String] mime type
59
+ # @return file type, one of enum CONVERSION_TYPES
60
+ def mime_to_type(mimetype)
61
+ return SUPPORTED_MIME_TYPES[mimetype] if SUPPORTED_MIME_TYPES.key?(mimetype)
62
+ return :office if mimetype.start_with?('application/vnd.')
63
+ return :video if mimetype.start_with?('video/')
64
+ return :image if mimetype.start_with?('image/')
65
+ return nil
66
+ end
67
+
282
68
  # use mime magic to find mime type based on file content (magic numbers)
283
- def mime_from_file(filepath)
69
+ def file_to_mime(filepath)
284
70
  # moved here, as `mimemagic` can cause installation issues
285
71
  require 'mimemagic'
286
72
  require 'mimemagic/version'
@@ -288,7 +74,7 @@ module Aspera
288
74
  # check magic number inside file (empty string if not found)
289
75
  detected_mime = MimeMagic.by_magic(File.open(filepath)).to_s
290
76
  # check extension only
291
- if !SUPPORTED_MIME_TYPES.key?(detected_mime)
77
+ if mime_to_type(detected_mime).nil?
292
78
  Log.log.debug{"no conversion for #{detected_mime}, trying extension"}
293
79
  detected_mime = MimeMagic.by_extension(File.extname(filepath)).to_s
294
80
  end
@@ -298,18 +84,18 @@ module Aspera
298
84
  end
299
85
 
300
86
  # @param filepath [String] full path to file
301
- # @param mimetype [String] provided by node api
87
+ # @param mimetype [String] provided by node API
302
88
  # @return file type, one of enum CONVERSION_TYPES
303
89
  # @raise [RuntimeError] if no conversion type found
304
90
  def conversion_type(filepath, mimetype)
305
91
  Log.log.debug{"conversion_type(#{filepath},m=#{mimetype},t=#{@use_mimemagic})"}
306
92
  # 1- get type from provided mime type, using local mapping
307
- conversion_type = SUPPORTED_MIME_TYPES[mimetype] if !mimetype.nil?
93
+ conversion_type = mime_to_type(mimetype) if !mimetype.nil?
308
94
  # 2- else, from computed mime type (if available)
309
95
  if conversion_type.nil? && @use_mimemagic
310
- detected_mime = mime_from_file(filepath)
96
+ detected_mime = file_to_mime(filepath)
311
97
  if !detected_mime.nil?
312
- conversion_type = SUPPORTED_MIME_TYPES[detected_mime]
98
+ conversion_type = mime_to_type(detected_mime)
313
99
  if !mimetype.nil?
314
100
  if mimetype.eql?(detected_mime)
315
101
  Log.log.debug('matching mime type per magic number')
@@ -321,10 +107,10 @@ module Aspera
321
107
  end
322
108
  end
323
109
  # 3- else, from extensions, using local mapping
324
- extension = File.extname(filepath.downcase)[1..-1]
325
- conversion_type = SUPPORTED_EXTENSIONS[extension] if conversion_type.nil?
326
- raise "no conversion type found for extension #{extension}" if conversion_type.nil?
327
- Log.log.debug{"conversion_type(#{extension}): #{conversion_type.class.name} [#{conversion_type}]"}
110
+ mime_by_ext = MIME::Types.of(File.basename(filepath)).first
111
+ conversion_type = mime_to_type(mime_by_ext.to_s) if conversion_type.nil? && !mime_by_ext.nil?
112
+ raise "no conversion type found for #{File.basename(filepath)}" if conversion_type.nil?
113
+ Log.log.trace1{"conversion_type(#{File.basename(filepath)}): #{conversion_type.class.name} [#{conversion_type}]"}
328
114
  return conversion_type
329
115
  end
330
116
  end
@@ -8,6 +8,8 @@ require 'open3'
8
8
  require 'aspera/preview/options'
9
9
  require 'aspera/preview/utils'
10
10
  require 'aspera/preview/file_types'
11
+ require 'aspera/log'
12
+ require 'aspera/assert'
11
13
 
12
14
  module Aspera
13
15
  module Preview
@@ -52,7 +54,7 @@ module Aspera
52
54
  end
53
55
  @processing_method = @processing_method.to_sym
54
56
  Log.log.debug{"method: #{@processing_method}"}
55
- raise "no processing know for #{conversion_type} -> #{@preview_format_sym}" unless respond_to?(@processing_method, true)
57
+ assert(respond_to?(@processing_method, true)){"no processing know for #{conversion_type} -> #{@preview_format_sym}"}
56
58
  end
57
59
 
58
60
  # create preview as specified in constructor
@@ -86,7 +88,7 @@ module Aspera
86
88
  # @param total_count of parts
87
89
  # @param index of part (start at 1)
88
90
  def get_offset(duration, start_offset, total_count, index)
89
- raise 'duration must be Float' unless duration.is_a?(Float)
91
+ assert_type(duration, Float){'duration'}
90
92
  return start_offset + ((index - 1) * (duration - start_offset) / total_count)
91
93
  end
92
94
 
@@ -149,10 +151,10 @@ module Aspera
149
151
  # do a simple re-encoding
150
152
  def convert_video_to_mp4_using_reencode
151
153
  options = @options.reencode_ffmpeg
152
- raise 'reencode_ffmpeg must be a Hash' unless options.is_a?(Hash)
154
+ assert_type(options, Hash){'reencode_ffmpeg'}
153
155
  options.each do |k, v|
154
- raise "Key not supported: #{k}. Use keys: #{FFMPEG_OPTIONS_LIST.join(',')}" unless FFMPEG_OPTIONS_LIST.include?(k)
155
- raise "Value for #{k} must be Array" unless v.is_a?(Array)
156
+ assert_values(k, FFMPEG_OPTIONS_LIST){'key'}
157
+ assert_type(v, Array){k}
156
158
  end
157
159
  Utils.ffmpeg(
158
160
  in_f: @source_file_path,
@@ -2,7 +2,6 @@
2
2
 
3
3
  # cspell:words Magick MAGICKCORE ITERM mintty winsize termcap
4
4
 
5
- require 'rmagick' # https://rmagick.github.io/index.html
6
5
  require 'rainbow'
7
6
  require 'io/console'
8
7
  module Aspera
@@ -10,8 +9,6 @@ module Aspera
10
9
  # Display a picture in the terminal, either using coloured characters or iTerm2
11
10
  class Terminal
12
11
  # Rainbow only supports 8-bit colors
13
- # quantum depth is 8 or 16, see: `convert xc: -format "%q" info:`
14
- SHIFT_FOR_8_BIT = Magick::MAGICKCORE_QUANTUM_DEPTH - 8
15
12
  # env vars to detect terminal type
16
13
  TERM_ENV_VARS = %w[TERM_PROGRAM LC_TERMINAL].freeze
17
14
  # terminal names that support iTerm2 image display
@@ -19,7 +16,7 @@ module Aspera
19
16
  # TODO: retrieve terminal font ratio using some termcap ?
20
17
  # ratio = font height / font width
21
18
  DEFAULT_FONT_RATIO = 32.0 / 14.0
22
- private_constant :SHIFT_FOR_8_BIT, :TERM_ENV_VARS, :ITERM_NAMES, :DEFAULT_FONT_RATIO
19
+ private_constant :TERM_ENV_VARS, :ITERM_NAMES, :DEFAULT_FONT_RATIO
23
20
  class << self
24
21
  # @return [String] the image as text, or the iTerm2 escape sequence
25
22
  # @param blob [String] the image as a binary string
@@ -29,6 +26,16 @@ module Aspera
29
26
  # @param font_ratio [Float] ratio = font height / font width
30
27
  def build(blob, reserve: 3, text: false, double: true, font_ratio: DEFAULT_FONT_RATIO)
31
28
  return iterm_display_image(blob) if iterm_supported? && !text
29
+ begin
30
+ # do not require statically, as the package is optional
31
+ require 'rmagick' # https://rmagick.github.io/index.html
32
+ rescue LoadError => e
33
+ Log.log.error('Install missing gem: gem install rmagick')
34
+ # fallback to iterm, if supported
35
+ return iterm_display_image(blob) if iterm_supported?
36
+ Log.log.error('Cant display picture.')
37
+ raise e
38
+ end
32
39
  image = Magick::ImageList.new.from_blob(blob)
33
40
  (term_rows, term_columns) = IO.console.winsize
34
41
  term_rows -= reserve
@@ -36,11 +43,13 @@ module Aspera
36
43
  fit_term_ratio = [term_rows / image.rows.to_f, term_columns / image.columns.to_f].min
37
44
  height_ratio = double ? 2.0 : 1.0
38
45
  image = image.scale((image.columns * fit_term_ratio * font_ratio).to_i, (image.rows * fit_term_ratio * height_ratio).to_i)
46
+ # quantum depth is 8 or 16, see: `convert xc: -format "%q" info:`
47
+ shift_for_8_bit = Magick::MAGICKCORE_QUANTUM_DEPTH - 8
39
48
  # get all pixel colors, adjusted for Rainbow
40
49
  pixel_colors = []
41
50
  image.each_pixel do |pixel, col, row|
42
51
  pixel_rgb = [pixel.red, pixel.green, pixel.blue]
43
- pixel_rgb = pixel_rgb.map { |color| color >> SHIFT_FOR_8_BIT } unless SHIFT_FOR_8_BIT.eql?(0)
52
+ pixel_rgb = pixel_rgb.map { |color| color >> shift_for_8_bit } unless shift_for_8_bit.eql?(0)
44
53
  # init 2-dim array
45
54
  pixel_colors[row] ||= []
46
55
  pixel_colors[row][col] = pixel_rgb
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # cspell:ignore ffprobe optipng unoconv
4
+ require 'aspera/log'
5
+ require 'aspera/assert'
4
6
  require 'English'
5
7
  require 'tmpdir'
6
8
  require 'fileutils'
7
- require 'aspera/log'
8
9
  require 'open3'
9
10
 
10
11
  module Aspera
@@ -31,7 +32,7 @@ module Aspera
31
32
  tools_to_check.delete(:unoconv) if skip_types.include?(:office)
32
33
  # Check for binaries
33
34
  tools_to_check.each do |command_sym|
34
- external_command(command_sym, ['-h'], log_error: false)
35
+ external_command(command_sym, ['-h'], check_code: false)
35
36
  rescue Errno::ENOENT => e
36
37
  raise "missing #{command_sym} binary: #{e}"
37
38
  rescue
@@ -42,13 +43,13 @@ module Aspera
42
43
  # execute external command
43
44
  # one could use "system", but we would need to redirect stdout/err
44
45
  # @return true if su
45
- def external_command(command_sym, command_args, log_error: true)
46
- raise "unexpected command #{command_sym}" unless EXTERNAL_TOOLS.include?(command_sym)
46
+ def external_command(command_sym, command_args, check_code: true)
47
+ assert_values(command_sym, EXTERNAL_TOOLS){'command'}
47
48
  # build command line, and quote special characters
48
49
  command_line = command_args.clone.unshift(command_sym).map{|i| shell_quote(i.to_s)}.join(' ')
49
50
  Log.log.debug{"cmd=#{command_line}".blue}
50
51
  stdout, stderr, status = Open3.capture3(command_line)
51
- if log_error && !status.success?
52
+ if check_code && !status.success?
52
53
  Log.log.error{"status: #{status}"}
53
54
  Log.log.error{"stdout: #{stdout}"}
54
55
  Log.log.error{"stderr: #{stderr}"}
@@ -58,7 +59,7 @@ module Aspera
58
59
  end
59
60
 
60
61
  def ffmpeg(a)
61
- raise 'error: hash expected' unless a.is_a?(Hash)
62
+ assert_type(a, Hash)
62
63
  # input_file,input_args,output_file,output_args
63
64
  a[:gl_p] ||= [
64
65
  '-y', # overwrite output without asking
@@ -66,7 +67,7 @@ module Aspera
66
67
  ]
67
68
  a[:in_p] ||= []
68
69
  a[:out_p] ||= []
69
- raise "wrong params (#{a.keys.sort})" unless %i[gl_p in_f in_p out_f out_p].eql?(a.keys.sort)
70
+ assert(%i[gl_p in_f in_p out_f out_p].eql?(a.keys.sort)){"wrong params (#{a.keys.sort})"}
70
71
  external_command(:ffmpeg, [a[:gl_p], a[:in_p], '-i', a[:in_f], a[:out_p], a[:out_f]].flatten)
71
72
  end
72
73
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'aspera/log'
4
+ require 'aspera/assert'
3
5
  require 'uri'
4
6
  require 'resolv'
5
7
 
@@ -9,7 +11,7 @@ module URI
9
11
  alias_method :find_proxy_orig, :find_proxy
10
12
  class << self
11
13
  def register_proxy_finder
12
- raise 'mandatory block missing' unless Kernel.block_given?
14
+ assert(block_given?)
13
15
  # overload the method in URI : call user's provided block and fallback to original method
14
16
  define_method(:find_proxy) {|env_vars=ENV| yield(to_s) || find_proxy_orig(env_vars)}
15
17
  end
@@ -107,11 +109,12 @@ END_OF_JAVASCRIPT
107
109
  parts = item.strip.split
108
110
  case parts.shift
109
111
  when 'DIRECT'
110
- raise 'DIRECT has no param' unless parts.empty?
112
+ assert(parts.empty?){'DIRECT has no param'}
111
113
  Log.log.debug('ignoring proxy DIRECT')
112
114
  when 'PROXY'
113
115
  addr_port = parts.shift
114
- raise 'PROXY shall have one param' unless addr_port.is_a?(String) && parts.empty?
116
+ assert_type(addr_port, String)
117
+ assert(parts.empty?){'PROXY shall have one param'}
115
118
  begin
116
119
  # PAC proxy addresses are <host>:<port>
117
120
  if /:[0-9]+$/.match?(addr_port)