storazzo 0.0.5 → 0.0.6
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.
- checksums.yaml +4 -4
- data/bin/ricdisk-magic.rb +395 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06f3ee99606822e20e1d8410578fd8194b416f9ccdcc4cf2a17d1b7a44e09d45
|
4
|
+
data.tar.gz: c92b3712561fb31e049052f35ffe500800b5dab6537eb0cb8f2313e898b2558d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c05485035eee8f1092a8c8c05a765f3d1492233ec22b8bf3539ad82bc6ded2cc46cbaacb49bb86539fdea6ee48c8a99c491a6daab1f0b3f6d408af48f610669
|
7
|
+
data.tar.gz: 79c252ed51045da677895a8c5e891de78e7490354212eaa4a93594914734ee66eff0423e643aecb3d476b5d8c2367f6900bd625a21e7bbc9f0cf0a3a790397ed
|
@@ -0,0 +1,395 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#require 'google/protobuf'
|
4
|
+
#require_relative '../etc/protos/out/ricdisk_pb'
|
5
|
+
require 'yaml'
|
6
|
+
require 'socket'
|
7
|
+
require 'optparse' # http://ruby.about.com/od/advancedruby/a/optionparser.htm
|
8
|
+
require 'storazzo'
|
9
|
+
# required to have methods wiothout self.
|
10
|
+
extend Storazzo::Colors
|
11
|
+
|
12
|
+
if RUBY_VERSION.split('.')[0] == 1
|
13
|
+
puts "Refusing to launch a script form Ruby 1. Sorry Ric, its 2020 damn it!"
|
14
|
+
exit 2020
|
15
|
+
end
|
16
|
+
|
17
|
+
$PROG_VER = '0.3'
|
18
|
+
$DEBUG = false
|
19
|
+
|
20
|
+
HISTORY = <<-BIG_LONG_MULTILINE
|
21
|
+
2022-07-11 v0.3 Ported from private files in GIC into storazzo (open source on gitHub) and cleaned up italian and libs
|
22
|
+
2022-07-DD v0.2 Some private stuff on GIC
|
23
|
+
BIG_LONG_MULTILINE
|
24
|
+
|
25
|
+
=begin
|
26
|
+
|
27
|
+
############################################################
|
28
|
+
@author: Riccardo Carlesso
|
29
|
+
@email: riccardo.carlesso@gmail.com
|
30
|
+
@maturity: development
|
31
|
+
@language: Ruby
|
32
|
+
@synopsis: Brief Description here
|
33
|
+
@tags: development, rcarlesso, test
|
34
|
+
@description: See description
|
35
|
+
############################################################
|
36
|
+
|
37
|
+
=end
|
38
|
+
|
39
|
+
|
40
|
+
$myconf = {
|
41
|
+
:app_name => "RicDisk Magic should be sth like #{$0}",
|
42
|
+
:description => "
|
43
|
+
This program is loosely inspired to ricdisk-magic.sh but its much better.
|
44
|
+
Idea di base: trovare tutti le directory con file ricdisk e da esso estrarre info e magari METTERE info.
|
45
|
+
Il tutto condito con un bel protobuf e un'entita che metto in Lib.
|
46
|
+
".strip.gsub(/^\s+/, "").gsub(/\s+$/, ""),
|
47
|
+
# TODO move to some class default
|
48
|
+
:media_dirs => %w{ /media/riccardo/ /Volumes/ /mnt/ ~/git/storazzo/test/ /sobenme/giusto/per/imparare/ad/ammutolire/gli/errori/ },
|
49
|
+
:mount_types => %w{ vfat ntfs },
|
50
|
+
}
|
51
|
+
$stats_file = "ricdisk_stats_v11.rds"
|
52
|
+
$gcs_bucket = 'palladius'
|
53
|
+
|
54
|
+
# This template from scripta.rb. from 2.1.0 removed aby ric gem dependency.
|
55
|
+
# 2022-04-26 2.1.1 Added more colors
|
56
|
+
# 2022-04-26 2.1.0 Historical momemnt: removed gem 'ric' dependency
|
57
|
+
$TEMPLATE_VER = '2.1.1'
|
58
|
+
|
59
|
+
# copied from https://dev.to/ayushn21/how-to-generate-yaml-from-ruby-objects-without-type-annotations-4fli
|
60
|
+
module Hashify
|
61
|
+
# Classes that include this module can exclude certain
|
62
|
+
# instance variable from its hash representation by overriding
|
63
|
+
# this method
|
64
|
+
def ivars_excluded_from_hash
|
65
|
+
[ 'this_doesnt_exist' ]
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_hash
|
69
|
+
hash = {}
|
70
|
+
excluded_ivars = ivars_excluded_from_hash
|
71
|
+
|
72
|
+
# Iterate over all the instance variables and store their
|
73
|
+
# names and values in a hash
|
74
|
+
instance_variables.each do |var|
|
75
|
+
next if excluded_ivars.include? var.to_s
|
76
|
+
|
77
|
+
value = instance_variable_get(var)
|
78
|
+
value = value.map(&:to_hash) if value.is_a? Array
|
79
|
+
|
80
|
+
hash[var.to_s.delete("@")] = value
|
81
|
+
end
|
82
|
+
|
83
|
+
return hash
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_yaml
|
87
|
+
to_hash.to_yaml
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# TODO move to lib/ric_disk/
|
92
|
+
class RicDisk
|
93
|
+
VERSION = "1.0"
|
94
|
+
include Hashify
|
95
|
+
extend Storazzo::Colors
|
96
|
+
|
97
|
+
|
98
|
+
# todo substitute wqith protobuf..
|
99
|
+
attr_accessor :name, :description, :ricdisk_file, :local_mountpoint, :wr
|
100
|
+
|
101
|
+
def self.interesting_mount_points(opts={})
|
102
|
+
#https://unix.stackexchange.com/questions/177014/showing-only-interesting-mount-points-filtering-non-interesting-types
|
103
|
+
`mount | grep -Ev 'type (proc|sysfs|tmpfs|devpts|debugfs|rpc_pipefs|nfsd|securityfs|fusectl|devtmpfs) '`.split(/\n+/)
|
104
|
+
end
|
105
|
+
|
106
|
+
def initialize(path, ricdisk_file)
|
107
|
+
@local_mountpoint = path
|
108
|
+
@description = "This is an automated RicDisk description from v.#{VERSION}. Riccardo feel free to edit away with characteristicshs of this device.. Created on #{Time.now}'"
|
109
|
+
@ricdisk_version = VERSION
|
110
|
+
@ricdisk_file = ricdisk_file
|
111
|
+
#@questo_non_esiste = :sobenme
|
112
|
+
@label = path.split("/").last
|
113
|
+
@name = path.split("/").last
|
114
|
+
@wr = File.writable?("#{path}/#{ricdisk_file}" ) # .writeable?
|
115
|
+
@tags = 'ricdisk'
|
116
|
+
find_info_from_mount(path)
|
117
|
+
find_info_from_df()
|
118
|
+
end
|
119
|
+
|
120
|
+
def ricdisk_absolute_path
|
121
|
+
@local_mountpoint + "/" + @ricdisk_file
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_tag(tag)
|
125
|
+
@tags += ", #{tag}"
|
126
|
+
end
|
127
|
+
|
128
|
+
# might have other things in the future...
|
129
|
+
def find_info_from_mount(path)
|
130
|
+
mount_table_lines = interesting_mount_points()
|
131
|
+
mount_line = nil
|
132
|
+
mount_table_lines.each do |line|
|
133
|
+
next if line =~ /^map /
|
134
|
+
dev, on, mount_path, mode = line.split(/ /)
|
135
|
+
if mount_path==path
|
136
|
+
mount_line = line
|
137
|
+
else
|
138
|
+
@info_from_mount = false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
@info_from_mount = ! (mount_line.nil?)
|
142
|
+
if @info_from_mount
|
143
|
+
#@mount_line = mount_line
|
144
|
+
@description += "\nMount line:\n" + mount_line
|
145
|
+
@remote_mountpoint = mount_line.split(/ /)[0]
|
146
|
+
@fstype = mount_line.split(/ /)[3].gsub(/[\(,]/, '')
|
147
|
+
add_tag(:synology) if @remote_mountpoint.match('1.0.1.10')
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def find_info_from_df()
|
152
|
+
path = @local_mountpoint
|
153
|
+
df_info = `df -h "#{path}"`
|
154
|
+
@df_info = df_info
|
155
|
+
lines = df_info.split(/\n+/)
|
156
|
+
raise "I need exactly TWO lines! Or no info is served here..." unless lines.size == 2
|
157
|
+
mount, @size_readable, used_size, avail_size, @disk_utilization, other = lines[1].split(/\s+/) # second line..
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
def self.sbrodola_ricdisk(subdir)
|
163
|
+
# given a path, if .ricdisk exists i do stuff with it..
|
164
|
+
disk_info = nil
|
165
|
+
unless self.ok_dir?(subdir)
|
166
|
+
puts("Nothing for me here. Existing")
|
167
|
+
return
|
168
|
+
end
|
169
|
+
if File.exists?( "#{subdir}/.ricdisk") and File.empty?( "#{subdir}/.ricdisk")
|
170
|
+
deb("Interesting1. Empty file! Now I write YAML with it.")
|
171
|
+
disk_info = RicDisk.new(subdir, '.ricdisk')
|
172
|
+
#puts(x)
|
173
|
+
#puts(yellow x.to_yaml)
|
174
|
+
end
|
175
|
+
if File.exists?( "#{subdir}/.ricdisk.yaml") and File.empty?( "#{subdir}/.ricdisk.yaml")
|
176
|
+
deb("Interesting2. Empty file! TODO write YAML with it.")
|
177
|
+
disk_info = RicDisk.new(subdir, '.ricdisk.yaml')
|
178
|
+
# todo write
|
179
|
+
#puts(x)
|
180
|
+
puts(yellow disk_info.to_yaml)
|
181
|
+
end
|
182
|
+
if disk_info
|
183
|
+
if File.empty?(disk_info.ricdisk_absolute_path) and (disk_info.wr)
|
184
|
+
puts(green("yay, we can now write the file '#{disk_info.ricdisk_absolute_path}' (which is R/W, I just checked!) with proper YAML content.."))
|
185
|
+
ret = File.write(disk_info.ricdisk_absolute_path, disk_info.to_yaml)
|
186
|
+
puts("Written file! ret=#{ret}")
|
187
|
+
else
|
188
|
+
puts(red("Nope, qualcosa non va.. #{File.empty?(disk_info.ricdisk_absolute_path)}"))
|
189
|
+
puts("File size: #{File.size(disk_info.ricdisk_absolute_path)}")
|
190
|
+
end
|
191
|
+
end
|
192
|
+
if File.exists?( "#{subdir}/.ricdisk") and ! File.empty?( "#{subdir}/.ricdisk")
|
193
|
+
puts("Config File found with old-style name: '#{subdir}/.ricdisk' !")
|
194
|
+
#puts(white `cat "#{subdir}/.ricdisk"`)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# separiamo cosi usiamo meglio...
|
199
|
+
def self.ok_dir?(subdir)
|
200
|
+
File.exists?( "#{subdir}/.ricdisk") or File.exists?( "#{subdir}/.ricdisk.yaml")
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.obsolescence_seconds file_path
|
204
|
+
creation_time = File.stat(file_path).ctime
|
205
|
+
deb("[obsolescence_seconds] File #{file_path}: #{creation_time} - #{(Time.now - creation_time)} seconds ago")
|
206
|
+
(Time.now - creation_time).to_i
|
207
|
+
end
|
208
|
+
def self.obsolescence_days(file_path)
|
209
|
+
return obsolescence_seconds(file_path) / 86400
|
210
|
+
end
|
211
|
+
|
212
|
+
def self.backquote_execute(cmd)
|
213
|
+
# executed a command wrapped by dryrun though
|
214
|
+
return "DRYRUN backquote_execute(#{cmd})" if $opts[:dryrun]
|
215
|
+
`#{cmd}`
|
216
|
+
end
|
217
|
+
|
218
|
+
def self.upload_to_gcs(file, opts={})
|
219
|
+
deb("upload_to_gcs(#{file}). TODO(ricc) after breafast upload to GCS : #{file}")
|
220
|
+
mount_name = file.split('/')[-2]
|
221
|
+
filename = "#{mount_name}-#{File.basename file}"
|
222
|
+
hostname = Socket.gethostname[/^[^.]+/]
|
223
|
+
command = "gsutil cp '#{file}' gs://#{$gcs_bucket}/backup/ricdisk-magic/#{ hostname }-#{filename}"
|
224
|
+
deb("Command: #{command}")
|
225
|
+
ret = backquote_execute(command)
|
226
|
+
# if $opts[:debug] do
|
227
|
+
# puts "+ Current list of files:"
|
228
|
+
# ret = backquote_execute("gsutil ls -al gs://#{$gcs_bucket}/backup/ricdisk-magic/")
|
229
|
+
# puts ret
|
230
|
+
# end
|
231
|
+
ret
|
232
|
+
end
|
233
|
+
|
234
|
+
# Create RDS file.
|
235
|
+
def self.calculate_stats_files(dir, opts={})
|
236
|
+
opts_upload_to_gcs = opts.fetch :upload_to_gcs, true
|
237
|
+
full_file_path = "#{dir}/#{$stats_file}"
|
238
|
+
|
239
|
+
puts("calculate_stats_files(#{white dir}): #{white full_file_path}")
|
240
|
+
puts "TEST1 DIR EXISTS: #{dir} -> #{Dir.directory? dir}"
|
241
|
+
Dir.chdir(dir)
|
242
|
+
if File.exists?(full_file_path) and ($opts[:force] == false)
|
243
|
+
puts "File '#{$stats_file}' exists already." # - now should see if its too old, like more than 1 week old"
|
244
|
+
# TODO check for file time...
|
245
|
+
print "Lines found: #{yellow `wc -l "#{full_file_path}" `.chomp }. File obsolescence (days): #{yellow obsolescence_days(full_file_path)}."
|
246
|
+
if obsolescence_days(full_file_path) > 7
|
247
|
+
puts("*** ACHTUNG *** FIle is pretty old. You might consider rotating: #{yellow "mv #{full_file_path} #{full_file_path}_old"}. Or invoke with --force")
|
248
|
+
end
|
249
|
+
upload_to_gcs(full_file_path) if opts_upload_to_gcs
|
250
|
+
else
|
251
|
+
puts "Crunching data stats from '#{dir}' into '#{$stats_file}' ... please bear with me.. [maybe file didnt exist, maybe $opts[:force] is true]"
|
252
|
+
command = "find . -print0 | xargs -0 stats-with-md5.rb --no-color | tee '#{full_file_path}'"
|
253
|
+
puts("[#{`pwd`.chomp}] Executing: #{azure command}")
|
254
|
+
ret = backquote_execute command
|
255
|
+
puts "Done. #{ret.split("\n").count} files processed."
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.find_active_dirs(base_dirs=nil, also_mountpoints=true)
|
260
|
+
base_dirs = $myconf[:media_dirs] if base_dirs.nil?
|
261
|
+
active_dirs = []
|
262
|
+
base_dirs.each do |ugly_dir|
|
263
|
+
# https://stackoverflow.com/questions/1899072/getting-a-list-of-folders-in-a-directory#:~:text=Dir.chdir(%27/destination_directory%27)%0ADir.glob(%27*%27).select%20%7B%7Cf%7C%20File.directory%3F%20f%7D
|
264
|
+
dir = File.expand_path(ugly_dir)
|
265
|
+
begin
|
266
|
+
x=[]
|
267
|
+
# puts "TEST2 DIR EXISTS: #{dir} -> #{Dir.exists?(dir)}"
|
268
|
+
unless Dir.exists?(dir)
|
269
|
+
deb "Dir doesnt exist, skipping: #{dir}"
|
270
|
+
next
|
271
|
+
end
|
272
|
+
Dir.chdir(dir)
|
273
|
+
x = Dir.glob('*').select {|f| File.directory? f}
|
274
|
+
subdirs = x.map{|subdir| "#{dir}#{subdir}"}
|
275
|
+
subdirs.each{|subdir|
|
276
|
+
#puts `ls -al "#{subdir}"`
|
277
|
+
active_dirs << subdir if self.ok_dir?(subdir)
|
278
|
+
}
|
279
|
+
#puts(white x)
|
280
|
+
rescue Exception => e # optionally: `rescue Exception => ex`
|
281
|
+
puts "Exception: '#{e}'"
|
282
|
+
ensure # will always get executed
|
283
|
+
#deb 'Always gets executed.'
|
284
|
+
#x = []
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
if also_mountpoints
|
289
|
+
=begin
|
290
|
+
Example output from mount:
|
291
|
+
|
292
|
+
devfs on /dev (devfs, local, nobrowse)
|
293
|
+
/dev/disk3s6 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse)
|
294
|
+
/dev/disk3s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse)
|
295
|
+
/dev/disk3s4 on /System/Volumes/Update (apfs, local, journaled, nobrowse)
|
296
|
+
/dev/disk1s2 on /System/Volumes/xarts (apfs, local, noexec, journaled, noatime, nobrowse)
|
297
|
+
/dev/disk1s1 on /System/Volumes/iSCPreboot (apfs, local, journaled, nobrowse)
|
298
|
+
/dev/disk1s3 on /System/Volumes/Hardware (apfs, local, journaled, nobrowse)
|
299
|
+
/dev/disk3s5 on /System/Volumes/Data (apfs, local, journaled, nobrowse, protect)
|
300
|
+
map auto_home on /System/Volumes/Data/home (autofs, automounted, nobrowse)
|
301
|
+
//riccardo@1.0.1.10/video on /Volumes/video (afpfs, nodev, nosuid, mounted by ricc)
|
302
|
+
//riccardo@1.0.1.10/photo on /Volumes/photo (afpfs, nodev, nosuid, mounted by ricc)
|
303
|
+
=end
|
304
|
+
# add directories from current mountpoints...
|
305
|
+
mount_table_lines = interesting_mount_points()
|
306
|
+
mount_table_lines.each{|line|
|
307
|
+
next if line =~ /^map /
|
308
|
+
dev, on, path, mode = line.split(/ /)
|
309
|
+
#puts line
|
310
|
+
#deb yellow(path)
|
311
|
+
active_dirs << path if self.ok_dir?(path)
|
312
|
+
}
|
313
|
+
end
|
314
|
+
active_dirs.uniq!
|
315
|
+
puts("find_active_dirs(): found dirs " + green(active_dirs))
|
316
|
+
return active_dirs
|
317
|
+
end
|
318
|
+
|
319
|
+
|
320
|
+
end
|
321
|
+
|
322
|
+
def usage(comment=nil)
|
323
|
+
puts white($optparse.banner)
|
324
|
+
puts($optparse.summarize)
|
325
|
+
puts("Description: " + gray($myconf[:description]))
|
326
|
+
puts red(comment) if comment
|
327
|
+
#puts "Description: #{ $myconf[:description] }"
|
328
|
+
exit 13
|
329
|
+
end
|
330
|
+
|
331
|
+
# include it in main if you want a custome one
|
332
|
+
def init() # see lib_autoinit in lib/util.rb
|
333
|
+
$opts = {}
|
334
|
+
# setting defaults
|
335
|
+
$opts[:verbose] = false
|
336
|
+
$opts[:dryrun] = false
|
337
|
+
$opts[:debug] = false
|
338
|
+
$opts[:force] = false
|
339
|
+
|
340
|
+
$optparse = OptionParser.new do |opts|
|
341
|
+
opts.banner = "#{$0} v.#{$PROG_VER}\n Usage: #{File.basename $0} [options] file1 file2 ..."
|
342
|
+
opts.on( '-d', '--debug', 'enables debug (DFLT=false)' ) { $opts[:debug] = true ; $DEBUG = true }
|
343
|
+
opts.on( '-f', '--force', 'force stuff (DFLT=false)' ) { $opts[:force] = true }
|
344
|
+
opts.on( '-h', '--help', 'Display this screen' ) { usage }
|
345
|
+
#opts.on( '-j', '--jabba', 'Activates my Jabber powerful CLI' ) { $opts[:jabba] = true }
|
346
|
+
opts.on( '-n', '--dryrun', "Don't really execute code" ) { $opts[:dryrun] = true }
|
347
|
+
opts.on( '-l', '--logfile FILE', 'Write log to FILE' ) {|file| $opts[:logfile] = file }
|
348
|
+
opts.on( '-v', '--verbose', 'Output more information' ) { $opts[:verbose] = true}
|
349
|
+
end
|
350
|
+
$optparse.parse!
|
351
|
+
end
|
352
|
+
|
353
|
+
def real_program
|
354
|
+
deb("Hello world from a templated '#{yellow $0 }'")
|
355
|
+
deb "+ Options are: #{gray $opts}"
|
356
|
+
deb "+ Depured args: #{azure ARGV}"
|
357
|
+
deb "+ Script-specifig super-cool conf: #{green $prog_conf_d}"
|
358
|
+
deb "+ Your configuration: #{purple $myconf.inspect}"
|
359
|
+
|
360
|
+
# Your code goes here...
|
361
|
+
puts white("Hello world from #{$myconf[:app_name]}!")
|
362
|
+
puts "Description: '''#{white $myconf[:description] }'''"
|
363
|
+
|
364
|
+
if ARGV == [] # empty -> ALL
|
365
|
+
dirs = RicDisk.find_active_dirs()
|
366
|
+
dirs.each {|dir|
|
367
|
+
RicDisk.sbrodola_ricdisk(dir)
|
368
|
+
RicDisk.calculate_stats_files(dir) # dir is inutile
|
369
|
+
} # TODO refactor in option sbrodola_afterwards=true. :)
|
370
|
+
else
|
371
|
+
deb "I consider ARGV come la lista di directories da parsare :)"
|
372
|
+
dirs = RicDisk.find_active_dirs()
|
373
|
+
ARGV.each{ |dir|
|
374
|
+
dir = File.expand_path(dir)
|
375
|
+
if dirs.include?(dir)
|
376
|
+
deb "Legit dir: #{green dir}"
|
377
|
+
RicDisk.sbrodola_ricdisk(dir)
|
378
|
+
RicDisk.calculate_stats_files(dir) # dir is inutile
|
379
|
+
else
|
380
|
+
deb "Figghiu ri buttana: doesnt exist #{red dir}"
|
381
|
+
end
|
382
|
+
}
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
def main(filename)
|
387
|
+
deb "I'm called by #{white filename}"
|
388
|
+
deb "HISTORY: #{gray HISTORY}"
|
389
|
+
#deb "To remove this shit, just set $DEBUG=false :)"
|
390
|
+
init # Enable this to have command line parsing capabilities!
|
391
|
+
#warn "[warn] template v#{$TEMPLATE_VER }: proviamo il warn che magari depreca il DEB"
|
392
|
+
real_program
|
393
|
+
end
|
394
|
+
|
395
|
+
main(__FILE__)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: storazzo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Riccardo Carlesso
|
@@ -10,12 +10,14 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2022-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: A simple
|
13
|
+
description: A simple gem to manage your external hard drives and extract MD5 and
|
14
|
+
common stuff from them.
|
14
15
|
email: name dot surname at popular Google-owned Mail
|
15
16
|
executables: []
|
16
17
|
extensions: []
|
17
18
|
extra_rdoc_files: []
|
18
19
|
files:
|
20
|
+
- bin/ricdisk-magic.rb
|
19
21
|
- lib/storazzo.rb
|
20
22
|
- lib/storazzo/colors.rb
|
21
23
|
- lib/storazzo/translator.rb
|