rubyment 0.7.25752540 → 0.7.25761093
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/lib/rubyment.rb +637 -24
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84fd074da46f8f1ef6ed16cac3d8585c66167edf
|
4
|
+
data.tar.gz: 631c77f863b75a6243f83ca966fa192d03577878
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4310b2d48cca557ead98af608cddcfa1d180b871040855fc19629752e2934d5fc00c4b75044dfff261447b02b24e4fb75e00bd71cb4011e009373324af68a608
|
7
|
+
data.tar.gz: beca4169679bf3924ed30f874519ea6d7b40f8546c627ccfbcbd7d0ff16a1f51e049f3a4a2351b0f3fa424c56a5a58f74a340f63a20ff5c58dee1a80944863d1
|
data/lib/rubyment.rb
CHANGED
@@ -92,7 +92,49 @@ class Object
|
|
92
92
|
end
|
93
93
|
|
94
94
|
|
95
|
-
|
95
|
+
=begin
|
96
|
+
Turns any Ruby object into a composite.
|
97
|
+
|
98
|
+
Examples:
|
99
|
+
|
100
|
+
1.as_container(:components_only).entries
|
101
|
+
# => []
|
102
|
+
|
103
|
+
1.as_container.entries
|
104
|
+
# => [1]
|
105
|
+
|
106
|
+
"hello".as_container.entries
|
107
|
+
# => ["hello"]
|
108
|
+
|
109
|
+
[1, 2, 3].as_container().entries
|
110
|
+
# => [1, 2, 3]
|
111
|
+
|
112
|
+
[1, 2, 3].as_container(:components_only).entries
|
113
|
+
# => [1, 2, 3]
|
114
|
+
|
115
|
+
# Take the first element of the operation on the object a:
|
116
|
+
# a.as_container.entries - a.as_container(:only_components).entries
|
117
|
+
# to find what's the non composite component of a:
|
118
|
+
|
119
|
+
a = [ 1, 2, 3 ] ; a.as_container.entries - a.as_container(:only_components).entries
|
120
|
+
# => []
|
121
|
+
|
122
|
+
a = "str" ; a.as_container.entries - a.as_container(:only_components).entries
|
123
|
+
# => ["str"]
|
124
|
+
|
125
|
+
=end
|
126
|
+
def as_container components_only=nil, method_name=:map
|
127
|
+
self.respond_to?(method_name) && (
|
128
|
+
self.send method_name
|
129
|
+
) || (!components_only) && (
|
130
|
+
[self].send method_name
|
131
|
+
) || (
|
132
|
+
[].send method_name
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
end # of class Object
|
96
138
|
|
97
139
|
|
98
140
|
=begin
|
@@ -903,9 +945,10 @@ module RubymentInternalModule
|
|
903
945
|
However, it's not sequencial, and therefore not
|
904
946
|
used for versioning.
|
905
947
|
=end
|
906
|
-
def rubyment_file_sha256
|
948
|
+
def rubyment_file_sha256 file=nil
|
907
949
|
require 'openssl'
|
908
|
-
(
|
950
|
+
file = containerize(file).first.nne __FILE__
|
951
|
+
(Digest::SHA256.hexdigest File.read file)
|
909
952
|
end
|
910
953
|
|
911
954
|
|
@@ -948,6 +991,89 @@ module RubymentInternalModule
|
|
948
991
|
end # of RubymentInternalModule
|
949
992
|
|
950
993
|
|
994
|
+
=begin
|
995
|
+
# begin_documentation
|
996
|
+
|
997
|
+
This module offers generic functions to help
|
998
|
+
achieving certain programming patterns.
|
999
|
+
|
1000
|
+
# end_documentation
|
1001
|
+
=end
|
1002
|
+
module RubymentPatternsModule
|
1003
|
+
|
1004
|
+
|
1005
|
+
=begin
|
1006
|
+
Turns any_object into a composite, and
|
1007
|
+
returns it in an array with its two parts:
|
1008
|
+
the leaf, and its children (another
|
1009
|
+
container)
|
1010
|
+
|
1011
|
+
Note that if an object can be decomposed
|
1012
|
+
by duck_type_method (:map) by default,
|
1013
|
+
it stays in the leaf, otherwise it is
|
1014
|
+
components are returned in the children.
|
1015
|
+
So expect always a nil for the leaf or
|
1016
|
+
[] for children components.
|
1017
|
+
|
1018
|
+
Decompose an object is useful, for example,
|
1019
|
+
to write a recursive function in functional
|
1020
|
+
style. Normally a recursive function will
|
1021
|
+
require a test to check if it is the base
|
1022
|
+
(leaf) case, otherwise will iterate through
|
1023
|
+
children and call recursively the function.
|
1024
|
+
With this, no test is needed. Since the "map"
|
1025
|
+
call is not defined for every object, it won't
|
1026
|
+
go infinite. Also, it won't throw an exception,
|
1027
|
+
because the children is a container (empty,
|
1028
|
+
when the leaf is defined):
|
1029
|
+
|
1030
|
+
def rec leaf_or_children
|
1031
|
+
l, c = object__decompose leaf_or_children
|
1032
|
+
c.map { |children| rec leaf_or_children }
|
1033
|
+
do_something_with_leaf l # must be already in
|
1034
|
+
# a functional/fault
|
1035
|
+
# tolerant style
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
Examples:
|
1039
|
+
|
1040
|
+
l, c = object__decompose [ "a", "b", "c"]
|
1041
|
+
# => [nil, ["a", "b", "c"]]
|
1042
|
+
|
1043
|
+
l, c = object__decompose "string"
|
1044
|
+
# => ["string", []]
|
1045
|
+
|
1046
|
+
l, c = object__decompose ["a", "b", "c"], :bytes
|
1047
|
+
# => [["a", "b", "c"], []]
|
1048
|
+
|
1049
|
+
l, c = object__decompose "string", :bytes
|
1050
|
+
# => [nil, [115, 116, 114, 105, 110, 103]]
|
1051
|
+
|
1052
|
+
|
1053
|
+
=end
|
1054
|
+
def object__decompose any_object, duck_type_method=:map
|
1055
|
+
|
1056
|
+
children = bled {
|
1057
|
+
any_object.as_container(:only_components, duck_type_method).entries
|
1058
|
+
}.first.call.first || []
|
1059
|
+
|
1060
|
+
leaf = bled([any_object]) {
|
1061
|
+
(
|
1062
|
+
any_object.as_container(nil, duck_type_method).entries -
|
1063
|
+
children
|
1064
|
+
).first
|
1065
|
+
}.first.call.first
|
1066
|
+
|
1067
|
+
[
|
1068
|
+
leaf,
|
1069
|
+
children,
|
1070
|
+
]
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
|
1074
|
+
end # of RubymentPatternsModule
|
1075
|
+
|
1076
|
+
|
951
1077
|
=begin
|
952
1078
|
# begin_documentation
|
953
1079
|
|
@@ -1070,9 +1196,271 @@ module RubymentInvocationModule
|
|
1070
1196
|
end
|
1071
1197
|
|
1072
1198
|
|
1199
|
+
=begin
|
1200
|
+
Just a convenience for typing less. Calls
|
1201
|
+
the block inside a bled, which is a function
|
1202
|
+
which captures and returns exceptions and
|
1203
|
+
runtime errors in a functional way, instead
|
1204
|
+
of Ruby's way.
|
1205
|
+
|
1206
|
+
Examples:
|
1207
|
+
|
1208
|
+
bled_call {:return_value }
|
1209
|
+
# => [:return_value, nil, nil]
|
1210
|
+
|
1211
|
+
bled_call { UndefinedStuff }
|
1212
|
+
# => [nil,
|
1213
|
+
# ...
|
1214
|
+
# nil],
|
1215
|
+
# NameError],
|
1216
|
+
# #<NameError: uninitialized constant #<Class:#<Rubyment:0x000000035adcc0>>::UndefinedStuff>]
|
1217
|
+
|
1218
|
+
|
1219
|
+
bled_call [:return_value_on_error] { UndefinedStuff }
|
1220
|
+
# => [:return_value_on_error,
|
1221
|
+
# [nil,
|
1222
|
+
# "message{\nuninitialized constant #<Class:#<Rubyment:0x0000000308e078>>::UndefinedStuff\
|
1223
|
+
|
1224
|
+
=end
|
1225
|
+
def bled_call *args, &block
|
1226
|
+
b = bled *args, &block
|
1227
|
+
b.first.call
|
1228
|
+
end
|
1229
|
+
|
1230
|
+
|
1231
|
+
=begin
|
1232
|
+
Generates a string that can be given to system (or any other
|
1233
|
+
command line executor) to execute a binary in memory (Ie,
|
1234
|
+
a file is generated having as contents a given string).
|
1235
|
+
If not file path is given a default one in /tmp will be
|
1236
|
+
generated (using the digest sha256 of the file (truncated
|
1237
|
+
at 96 chars, by now).
|
1238
|
+
Arguments can be given in an array (they will be escaped
|
1239
|
+
with Shellwords.join) or String (no escape apply)
|
1240
|
+
|
1241
|
+
Examples:
|
1242
|
+
|
1243
|
+
# write the contents of /bin/ls to a temporary file and offers
|
1244
|
+
# a command to execute it:
|
1245
|
+
system_command__exec_via_file [ [nil, File.read("/bin/ls") ] , ["-l", "-h"] ]
|
1246
|
+
# => "/tmp/rubyment.file.a90ba058c747458330ba26b5e2a744f4fc57f92f9d0c9112b1cb2f76c66c4ba0 -l -h"
|
1247
|
+
|
1248
|
+
system_command__exec_via_file [ ["/tmp/my_ls", File.read("/bin/ls") ] , ["-l", "-h"] ]
|
1249
|
+
# => "/tmp/my_ls -l -h"
|
1250
|
+
|
1251
|
+
system_command__exec_via_file [ ["/tmp/my_ls", File.read("/bin/ls") ] , "-l -h" ]
|
1252
|
+
# => "/tmp/my_ls -l -h"
|
1253
|
+
|
1254
|
+
|
1255
|
+
=end
|
1256
|
+
def system_command__exec_via_file exec_via_file
|
1257
|
+
args = exec_via_file
|
1258
|
+
|
1259
|
+
binary_or_script_blob,
|
1260
|
+
args_to_binary_or_blob,
|
1261
|
+
reserved = containerize(args)
|
1262
|
+
|
1263
|
+
file_path_src,
|
1264
|
+
string_src,
|
1265
|
+
reserved = containerize(binary_or_script_blob)
|
1266
|
+
|
1267
|
+
require 'openssl'
|
1268
|
+
string_src_sha256 = string_truncate [
|
1269
|
+
Digest::SHA256.hexdigest(string_src.to_s),
|
1270
|
+
96,
|
1271
|
+
]
|
1272
|
+
default_path_for_string_src = "/tmp/rubyment.file.#{string_src_sha256}"
|
1273
|
+
|
1274
|
+
actual_file_path,
|
1275
|
+
old_contents,
|
1276
|
+
reserved = file_string__experimental [
|
1277
|
+
file_path_src.nne(default_path_for_string_src),
|
1278
|
+
string_src,
|
1279
|
+
]
|
1280
|
+
|
1281
|
+
bled_call {
|
1282
|
+
require 'fileutils'
|
1283
|
+
FileUtils.chmod "+x", actual_file_path
|
1284
|
+
}
|
1285
|
+
require "shellwords"
|
1286
|
+
escaped_args_as_str = (
|
1287
|
+
bled_call [ args_to_binary_or_blob ] {
|
1288
|
+
Shellwords.join args_to_binary_or_blob
|
1289
|
+
}
|
1290
|
+
).first.to_s
|
1291
|
+
string__recursive_join [
|
1292
|
+
" ",
|
1293
|
+
actual_file_path,
|
1294
|
+
escaped_args_as_str,
|
1295
|
+
]
|
1296
|
+
end # of system_command__exec_via_file
|
1297
|
+
|
1298
|
+
|
1299
|
+
=begin
|
1300
|
+
"Rubyfy" a system's executable binary string/blob/memory chunk.
|
1301
|
+
Ruby gems won't distribute binaries other than Ruby executables
|
1302
|
+
(no whims, it is just their mechanisms of handling binaries with
|
1303
|
+
multiple versions in the system, they solved only for Ruby case).
|
1304
|
+
|
1305
|
+
With this function, a binary string can be given (in a file_string
|
1306
|
+
definition/structure; ie as second element), and a ruby code
|
1307
|
+
(which normally relies on Rubyment) will be generated to wrap
|
1308
|
+
that binary in a ruby code. A temporary file (not for the ruby
|
1309
|
+
code, but for storing the binary memory chunk/string is by
|
1310
|
+
default generated at /tmp/ dir; however it can set if given
|
1311
|
+
as the first element of that file_string.
|
1312
|
+
|
1313
|
+
Examples:
|
1314
|
+
|
1315
|
+
ruby_code__from_binary [nil, File.read("/bin/ls") ] # long output
|
1316
|
+
# => "#!/usr/bin/env ruby\n# Autogenerated on 2018.12.21_16:45:11\nrequire 'base64'\nblob_base64 = \"f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAoElAAAAAAABAAAAAAAAAADjnAQAA\\nAAAAAAAAAEAAOAAJAEAAHQAcAAYAAAA
|
1317
|
+
|
1318
|
+
# this version is good for self development: include this current .rb file, which contains function not yet in the gem package:
|
1319
|
+
ruby_code__from_binary [nil, File.read("/bin/ls") ], [ nil, :include_this_file ] # long output
|
1320
|
+
# => "#!/usr/bin/env ruby\n# Autogenerated on 2018.12.21_16:45:11\nrequire 'base64'\nblob_base64 = \"f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAoElAAAAAAABAAAAAAAAAADjnAQAA\\nAAAAAAAAAEAAOAAJAEAAHQAcAAYAAAA
|
1321
|
+
|
1322
|
+
ruby_code__from_binary ["/tmp/temporary_ls", File.read("/bin/ls") ] # long output
|
1323
|
+
# => "#!/usr/bin/env ruby\n# Autogenerated on 2018.12.21_16:50:37\nrequire \"rubyment\"\nrequire 'base64'\nblob_base64 =
|
1324
|
+
|
1325
|
+
system_command__exec_via_file [ [ nil, (ruby_code__from_binary [nil, File.read("/bin/ls") ]) ] ]
|
1326
|
+
# => "/tmp/rubyment.file.1e7f29e90deb6ba33b3e2e21540c77c56fca5995bb88141b572481f322290cad"
|
1327
|
+
|
1328
|
+
# this version is good for self development: include this current .rb file, which contains function not yet in the gem package:
|
1329
|
+
system_command__exec_via_file [ [ nil, (ruby_code__from_binary [nil, File.read("/bin/ls") ], [ nil, :include_this_file ]) ] ]
|
1330
|
+
|
1331
|
+
# or even:
|
1332
|
+
# this version is good for self development: include this current .rb file
|
1333
|
+
system_command__exec_via_file [ [ nil, (ruby_code__from_binary [nil, File.read("/bin/ls") ], [ nil, :include_this_file ]) ] , "-l" ]
|
1334
|
+
|
1335
|
+
|
1336
|
+
=end
|
1337
|
+
def ruby_code__from_binary binary_or_script_blob, requirements=nil
|
1338
|
+
require 'base64'
|
1339
|
+
temporary_file_path,
|
1340
|
+
blob_string = containerize(binary_or_script_blob)
|
1341
|
+
blob_base64 = Base64.encode64 blob_string
|
1342
|
+
|
1343
|
+
required_gems,
|
1344
|
+
load_current,
|
1345
|
+
object_creator,
|
1346
|
+
memory_exec_function,
|
1347
|
+
reserved = containerize(requirements)
|
1348
|
+
|
1349
|
+
memory_exec_function = memory_exec_function.nne(
|
1350
|
+
"system_command__exec_via_file"
|
1351
|
+
)
|
1352
|
+
|
1353
|
+
object_creator = object_creator.nne(
|
1354
|
+
"#{self.class}.new"
|
1355
|
+
)
|
1356
|
+
|
1357
|
+
memory_exec_function_call = string__recursive_join [
|
1358
|
+
".",
|
1359
|
+
object_creator,
|
1360
|
+
memory_exec_function,
|
1361
|
+
]
|
1362
|
+
|
1363
|
+
|
1364
|
+
required_gem,
|
1365
|
+
*only_one_currently_supported,
|
1366
|
+
reserved = containerize(required_gem)
|
1367
|
+
|
1368
|
+
required_gem = required_gem.nne "rubyment"
|
1369
|
+
load_current &&= "load #{__FILE__.inspect}"
|
1370
|
+
|
1371
|
+
code =<<-ENDHEREDOC
|
1372
|
+
#!/usr/bin/env ruby
|
1373
|
+
# Autogenerated on #{time__now_strftime_default}
|
1374
|
+
require #{required_gem.inspect}
|
1375
|
+
#{load_current}
|
1376
|
+
require 'base64'
|
1377
|
+
blob_base64 = #{blob_base64.inspect}
|
1378
|
+
system #{memory_exec_function_call} [
|
1379
|
+
[
|
1380
|
+
#{temporary_file_path.inspect},
|
1381
|
+
Base64.decode64(blob_base64),
|
1382
|
+
],
|
1383
|
+
ARGV,
|
1384
|
+
]
|
1385
|
+
ENDHEREDOC
|
1386
|
+
end # of ruby_code__from_binary
|
1387
|
+
|
1388
|
+
|
1073
1389
|
end # of RubymentInvocationModule
|
1074
1390
|
|
1075
1391
|
|
1392
|
+
=begin
|
1393
|
+
# begin_documentation
|
1394
|
+
|
1395
|
+
This module offers functions to generate or
|
1396
|
+
deploy gem packages.
|
1397
|
+
|
1398
|
+
As of now, there are many similar functions
|
1399
|
+
directly coded in RubymentModule; they will
|
1400
|
+
be moved here upon proper maintenance/cleanup
|
1401
|
+
|
1402
|
+
# end_documentation
|
1403
|
+
=end
|
1404
|
+
module RubymentGemGenerationModule
|
1405
|
+
|
1406
|
+
|
1407
|
+
=begin
|
1408
|
+
Gem files by default can distribute only Ruby files.
|
1409
|
+
This function implements the work needed to convert
|
1410
|
+
and automatize the generation of ruby executables out
|
1411
|
+
of non ruby binaries
|
1412
|
+
=end
|
1413
|
+
def gem_deploy__non_ruby_binaries args
|
1414
|
+
gem_name,
|
1415
|
+
gem_non_ruby_executables,
|
1416
|
+
gem_executables, # same as gem_bin_executables
|
1417
|
+
reserved = args
|
1418
|
+
|
1419
|
+
new_executables = gem_non_ruby_executables.map { |gem_non_ruby_executable|
|
1420
|
+
|
1421
|
+
new_gem_executable = string__recursive_join [
|
1422
|
+
"/",
|
1423
|
+
"bin",
|
1424
|
+
File.basename(gem_non_ruby_executable),
|
1425
|
+
]
|
1426
|
+
|
1427
|
+
new_gem_executable_contents = ruby_code__from_binary(
|
1428
|
+
[
|
1429
|
+
nil,
|
1430
|
+
File.read(gem_non_ruby_executable),
|
1431
|
+
],
|
1432
|
+
[
|
1433
|
+
gem_name,
|
1434
|
+
],
|
1435
|
+
)
|
1436
|
+
|
1437
|
+
# write file
|
1438
|
+
file_string__experimental [
|
1439
|
+
new_gem_executable,
|
1440
|
+
new_gem_executable_contents,
|
1441
|
+
]
|
1442
|
+
|
1443
|
+
bled_call {
|
1444
|
+
require 'fileutils'
|
1445
|
+
FileUtils.chmod "+x", new_gem_executable
|
1446
|
+
}
|
1447
|
+
|
1448
|
+
File.basename(new_gem_executable)
|
1449
|
+
|
1450
|
+
} # of gem_non_ruby_executables.map
|
1451
|
+
|
1452
|
+
gem_executables = gem_executables.nne([]).concat new_executables
|
1453
|
+
|
1454
|
+
[
|
1455
|
+
gem_executables,
|
1456
|
+
]
|
1457
|
+
|
1458
|
+
end # of gem_deploy_non_ruby_binaries
|
1459
|
+
|
1460
|
+
|
1461
|
+
end # of RubymentGemGenerationModule
|
1462
|
+
|
1463
|
+
|
1076
1464
|
=begin
|
1077
1465
|
# begin_documentation
|
1078
1466
|
This module receives functions that are being worked on.
|
@@ -2915,6 +3303,166 @@ trying to get the interface compatible with
|
|
2915
3303
|
end
|
2916
3304
|
|
2917
3305
|
|
3306
|
+
=begin
|
3307
|
+
Takes a file_string definition as input and output
|
3308
|
+
a new one.
|
3309
|
+
|
3310
|
+
A file_string definition is an image of a file on
|
3311
|
+
a string. Each time this function is called, the
|
3312
|
+
image is written to the disk (if set), and the previous
|
3313
|
+
file_contents is loaded into the string.
|
3314
|
+
|
3315
|
+
The first element of file_string is a file_path, existing
|
3316
|
+
or not.
|
3317
|
+
|
3318
|
+
the returned file_string has the same first element, and
|
3319
|
+
the second is either:
|
3320
|
+
. unexisting file_path
|
3321
|
+
. a string having the file path contents, in the case it is a file_path
|
3322
|
+
. a list of file_strings, one per each file inside a directory, in
|
3323
|
+
the case file_path is a directory.
|
3324
|
+
|
3325
|
+
This function, after generating the file_string to be returned,
|
3326
|
+
will write file_path accordingly to the second parameter. If :
|
3327
|
+
. a string: will write the string to the file_path (if file_path
|
3328
|
+
is not a directory, otherwise does nothing).
|
3329
|
+
. a list of file_strings / nil: will call recursively this function
|
3330
|
+
for each of the file_string inside, and will create file_path as
|
3331
|
+
directory (if still does not exist).
|
3332
|
+
|
3333
|
+
There is yet a third element in a file_string, mode (as in "rw+",
|
3334
|
+
and not as in permissions), used as parameter for file write.
|
3335
|
+
Check https://ruby-doc.org/core-2.3.1/IO.html#method-c-new
|
3336
|
+
|
3337
|
+
|
3338
|
+
This function does not have semantics to be called from
|
3339
|
+
the command line in its full interface, because
|
3340
|
+
it differentiates nil from ""
|
3341
|
+
|
3342
|
+
Planned improvements: permissions, shallow cat of a dir.
|
3343
|
+
|
3344
|
+
Examples:
|
3345
|
+
|
3346
|
+
# -- case: touch (non existing path and empty string)
|
3347
|
+
file_string__experimental ["non_existing_path", ""]
|
3348
|
+
|
3349
|
+
# -- case: echo > (existing or not path (can't be a dir) and non empty string)
|
3350
|
+
file_string__experimental ["existing_or_not_path__file", "contents of file"]
|
3351
|
+
|
3352
|
+
# -- case: echo >> (existing path (no dir) and non empty string, "a" mode)
|
3353
|
+
file_string__experimental ["existing_or_not_path__file", "contents of file", "a"]
|
3354
|
+
|
3355
|
+
# -- case: cat (path exists, (dir or file) otherwise becomes mkdir, nil string -- it is a recursive cat in the case of directories )
|
3356
|
+
file_string__experimental ["existing_path"]
|
3357
|
+
|
3358
|
+
# --- case: mkdir (or mkdir -p with only one argument): (non existing filepath, no string)
|
3359
|
+
file_string__experimental ["non_existing_path"]
|
3360
|
+
|
3361
|
+
# -- case: mkdir -p (non existing filepath, no string)
|
3362
|
+
file_string__experimental ["a/b/c/d"]
|
3363
|
+
|
3364
|
+
|
3365
|
+
=end
|
3366
|
+
def file_string__experimental file_string
|
3367
|
+
args = file_string
|
3368
|
+
|
3369
|
+
file_path,
|
3370
|
+
string_or_file_strings,
|
3371
|
+
mode,
|
3372
|
+
reserved = containerize(args)
|
3373
|
+
|
3374
|
+
|
3375
|
+
# if file_path is a directory, calls recursively this
|
3376
|
+
# function, retrieving the file_string representation
|
3377
|
+
# for each entry in a subdirectory:
|
3378
|
+
file_strings_entries = File.directory?(file_path) && (
|
3379
|
+
Dir.new(file_path).entries
|
3380
|
+
).nne([]).map { |file_path_entry|
|
3381
|
+
next_file_path = [file_path, file_path_entry].join("/")
|
3382
|
+
# To avoid infinite recursion, we need to check if
|
3383
|
+
# the next file path is not something like the
|
3384
|
+
# parent with "/./" at the end.
|
3385
|
+
# It is not simple to normalize file paths:
|
3386
|
+
# https://stackoverflow.com/a/53884097/533510
|
3387
|
+
# It makes more difficult the fact that the next
|
3388
|
+
# may not yet exist (although the parent must exist).
|
3389
|
+
# But the parent has to exist. And, if the next
|
3390
|
+
# and the parent are the same, then both exist. In
|
3391
|
+
# that case, we case compare if both have the
|
3392
|
+
# same inode.
|
3393
|
+
|
3394
|
+
inodes = [
|
3395
|
+
[
|
3396
|
+
File.stat(file_path).ino,
|
3397
|
+
File.stat(File.dirname file_path).ino,
|
3398
|
+
],
|
3399
|
+
:index,
|
3400
|
+
(
|
3401
|
+
bled_call { File.stat(next_file_path).ino }
|
3402
|
+
).first,
|
3403
|
+
]
|
3404
|
+
|
3405
|
+
skip = invoke__basic_sender_array(inodes)
|
3406
|
+
skip.negate_me &&
|
3407
|
+
# recursive call
|
3408
|
+
send(__method__, [next_file_path]) ||
|
3409
|
+
nil
|
3410
|
+
}.compact
|
3411
|
+
|
3412
|
+
# what is considered to be a file_path's contents?
|
3413
|
+
# this value will be the string_or_file_strings of
|
3414
|
+
# the returned value
|
3415
|
+
file_contents =
|
3416
|
+
# first case: it's a directory, thus its contents.
|
3417
|
+
file_strings_entries || (
|
3418
|
+
# second case: plain file, thus its contents as string
|
3419
|
+
bled_call {
|
3420
|
+
File.read(file_path)
|
3421
|
+
}
|
3422
|
+
# third case: non existing file (nil returned)
|
3423
|
+
).first
|
3424
|
+
|
3425
|
+
string,
|
3426
|
+
file_strings = object__decompose string_or_file_strings
|
3427
|
+
|
3428
|
+
# let's just write file_path accordingly
|
3429
|
+
# to string_or_file_strings, regardless of file_contents
|
3430
|
+
|
3431
|
+
require 'fileutils'
|
3432
|
+
bled_call {
|
3433
|
+
string && (
|
3434
|
+
# for write matters:
|
3435
|
+
# if string, then file_path is a file...
|
3436
|
+
FileUtils.mkdir_p File.dirname file_path
|
3437
|
+
File.write file_path, string, mode: mode
|
3438
|
+
) || (
|
3439
|
+
# otherwise file_path is a directory...
|
3440
|
+
FileUtils.mkdir_p file_path
|
3441
|
+
)
|
3442
|
+
}
|
3443
|
+
|
3444
|
+
|
3445
|
+
# if string_or_file_strings is a a list of file_strings
|
3446
|
+
# so file_path is interpreted to be written as a
|
3447
|
+
# directory
|
3448
|
+
file_strings = file_strings.map { |next_file_string|
|
3449
|
+
next_file_string = next_file_string.as_container
|
3450
|
+
# prepend file_path:
|
3451
|
+
next_file_string[0] = [
|
3452
|
+
file_path,
|
3453
|
+
next_file_string[0].to_s,
|
3454
|
+
].join("/")
|
3455
|
+
|
3456
|
+
send __method__, next_file_string # recursive call
|
3457
|
+
}
|
3458
|
+
|
3459
|
+
[
|
3460
|
+
file_path,
|
3461
|
+
file_contents,
|
3462
|
+
]
|
3463
|
+
end # of file_string__experimental
|
3464
|
+
|
3465
|
+
|
2918
3466
|
end # of RubymentExperimentModule
|
2919
3467
|
|
2920
3468
|
|
@@ -3179,6 +3727,33 @@ module RubymentMaintainedModule
|
|
3179
3727
|
=begin
|
3180
3728
|
# documentation_begin
|
3181
3729
|
# short_desc = "generates a block which may return exceptions instead of raising them."
|
3730
|
+
examples = [
|
3731
|
+
"
|
3732
|
+
(bled [] { :bled_returns }).first.call
|
3733
|
+
# => [:bled_returns, nil, nil]
|
3734
|
+
",
|
3735
|
+
"
|
3736
|
+
(bled { :bled_returns }).first.call
|
3737
|
+
# => [:bled_returns, nil, nil]
|
3738
|
+
",
|
3739
|
+
'
|
3740
|
+
(bled { X }).first.call
|
3741
|
+
=> [nil,
|
3742
|
+
[nil,
|
3743
|
+
# ...
|
3744
|
+
# ["uninitialized constant #<Class:#<Rubyment:0x000000035adcc0>>::X", nil],
|
3745
|
+
# NameError],
|
3746
|
+
# #<NameError: uninitialized constant #<Class:#<Rubyment:0x000000035adcc0>>::X>]
|
3747
|
+
',
|
3748
|
+
'
|
3749
|
+
(bled ["X is not undefined" ] { X }).first.call
|
3750
|
+
# => ["X is not undefined",
|
3751
|
+
# [nil,
|
3752
|
+
# "message{\
|
3753
|
+
',
|
3754
|
+
|
3755
|
+
]
|
3756
|
+
|
3182
3757
|
@memory[:documentation].push = {
|
3183
3758
|
:function => :bled,
|
3184
3759
|
:short_desc => short_desc,
|
@@ -4066,6 +4641,17 @@ end
|
|
4066
4641
|
this module from a file without stopping the process (#autoreload).
|
4067
4642
|
- some function to redesign part of Ruby API arguably misdesigned,
|
4068
4643
|
like #arrays__zip
|
4644
|
+
- functional exception handling (#bled_call and #bled)
|
4645
|
+
- certain programming patterns, like turning any ruby object in
|
4646
|
+
an effective composite pattern (#as_container, #object__decompose)
|
4647
|
+
- ... or a imaging of two system resources, like a file and a
|
4648
|
+
memory chunk (string), in a simplified interface that can
|
4649
|
+
abstract away many functions (file_string__experimental).
|
4650
|
+
- some functions to run a binary directly from a binary blob/memory
|
4651
|
+
chunk, or to convert that memory chunk in to an executable ruby
|
4652
|
+
script (#system_command__exec_via_file, #ruby_code__from_binary), so
|
4653
|
+
it can be deployed as a binary in a gem package
|
4654
|
+
(#gem_deploy__non_ruby_binaries).
|
4069
4655
|
|
4070
4656
|
|
4071
4657
|
Rubyment functions must respect the open/closed principle
|
@@ -4104,7 +4690,9 @@ module RubymentModule
|
|
4104
4690
|
include RubymentStringsModule
|
4105
4691
|
include RubymentArraysModule
|
4106
4692
|
include RubymentInternalModule
|
4693
|
+
include RubymentPatternsModule
|
4107
4694
|
include RubymentInvocationModule
|
4695
|
+
include RubymentGemGenerationModule
|
4108
4696
|
include RubymentExperimentModule
|
4109
4697
|
include RubymentMaintainedModule
|
4110
4698
|
include RubymentDeprecatedModule
|
@@ -5816,6 +6404,7 @@ module RubymentModule
|
|
5816
6404
|
gem_bin_contents,
|
5817
6405
|
gem_bin_executables,
|
5818
6406
|
gem_dependencies,
|
6407
|
+
gem_non_ruby_executables,
|
5819
6408
|
reserved = args
|
5820
6409
|
|
5821
6410
|
debug = @memory[:debug]
|
@@ -5833,6 +6422,14 @@ module RubymentModule
|
|
5833
6422
|
debug && (stderr.puts "gem_dependencies=#{gem_dependencies}")
|
5834
6423
|
debug && (stderr.puts "gem_dependencies_str=#{gem_dependencies_str.inspect}")
|
5835
6424
|
|
6425
|
+
gem_bin_executables,
|
6426
|
+
reserved = gem_deploy__non_ruby_binaries [
|
6427
|
+
gem_name,
|
6428
|
+
gem_non_ruby_executables,
|
6429
|
+
gem_bin_executables,
|
6430
|
+
]
|
6431
|
+
#
|
6432
|
+
|
5836
6433
|
contents =<<-ENDHEREDOC
|
5837
6434
|
Gem::Specification.new do |s|
|
5838
6435
|
s.name = '#{gem_name}'
|
@@ -5893,22 +6490,28 @@ end
|
|
5893
6490
|
major_version = memory[:major_version]
|
5894
6491
|
|
5895
6492
|
gem_name,
|
5896
|
-
|
5897
|
-
|
5898
|
-
|
5899
|
-
|
5900
|
-
|
5901
|
-
|
5902
|
-
|
5903
|
-
|
5904
|
-
|
5905
|
-
|
5906
|
-
|
5907
|
-
|
5908
|
-
|
5909
|
-
|
5910
|
-
|
5911
|
-
|
6493
|
+
gem_version,
|
6494
|
+
gem_dir,
|
6495
|
+
gem_ext,
|
6496
|
+
gem_hifen,
|
6497
|
+
gem_date,
|
6498
|
+
gem_summary,
|
6499
|
+
gem_description,
|
6500
|
+
gem_authors,
|
6501
|
+
gem_email,
|
6502
|
+
gem_files,
|
6503
|
+
gem_homepage,
|
6504
|
+
gem_license,
|
6505
|
+
gem_validate_class,
|
6506
|
+
gem_validate_class_args,
|
6507
|
+
gem_validate_class_method,
|
6508
|
+
gem_is_current_file,
|
6509
|
+
gem_bin_generate,
|
6510
|
+
gem_bin_contents,
|
6511
|
+
gem_executables,
|
6512
|
+
gem_dependencies,
|
6513
|
+
gem_non_ruby_executables,
|
6514
|
+
reserved = args
|
5912
6515
|
|
5913
6516
|
gem_name ||= "rubyment"
|
5914
6517
|
gem_version ||= (version [])
|
@@ -5928,20 +6531,28 @@ end
|
|
5928
6531
|
gem_validate_class ||= self.class.to_s
|
5929
6532
|
gem_validate_class_args ||= {:invoke => ["p", "installed and validated"] }
|
5930
6533
|
gem_validate_class_method ||= "new"
|
5931
|
-
gem_is_current_file
|
6534
|
+
gem_is_current_file ||= __FILE__ # this enables the possibility of building
|
5932
6535
|
# a gem for the calling file itself, but be aware that lib/gem_file.rb
|
5933
6536
|
# is supposed to be overriden later.
|
5934
|
-
gem_bin_generate
|
5935
|
-
gem_bin_contents
|
6537
|
+
gem_bin_generate ||= "bin/#{gem_name}" # generate a bin file
|
6538
|
+
gem_bin_contents ||=<<-ENDHEREDOC
|
5936
6539
|
#!/usr/bin/env ruby
|
5937
6540
|
require '#{gem_name}'
|
5938
6541
|
#{gem_validate_class}.new({:invoke => ARGV})
|
5939
6542
|
ENDHEREDOC
|
5940
|
-
gem_executables
|
5941
|
-
gem_dependencies
|
6543
|
+
gem_executables ||= [ gem_bin_generate && "#{gem_name}" ]
|
6544
|
+
gem_dependencies ||= [
|
5942
6545
|
# use the format, for gems with semantic versioning
|
5943
6546
|
# ["gems", "~> 0"],
|
5944
6547
|
]
|
6548
|
+
gem_non_ruby_executables ||= [
|
6549
|
+
# gem normally can only deploy non_ruby execs.
|
6550
|
+
# each file in this array will be escapsulated
|
6551
|
+
# as a ruby script that calls that file instead.
|
6552
|
+
# that ruby script will be placed in the
|
6553
|
+
# bin/ dir, and added to gem_executables
|
6554
|
+
|
6555
|
+
]
|
5945
6556
|
|
5946
6557
|
[
|
5947
6558
|
gem_name,
|
@@ -5965,6 +6576,7 @@ require '#{gem_name}'
|
|
5965
6576
|
gem_bin_contents,
|
5966
6577
|
gem_executables,
|
5967
6578
|
gem_dependencies,
|
6579
|
+
gem_non_ruby_executables,
|
5968
6580
|
]
|
5969
6581
|
end
|
5970
6582
|
|
@@ -6531,6 +7143,7 @@ require '#{gem_name}'
|
|
6531
7143
|
|
6532
7144
|
# test file_backup (just like a copy)
|
6533
7145
|
def test__file_backup args=ARGV
|
7146
|
+
require 'fileutils'
|
6534
7147
|
dest_dir, filename, append, prepend, file_contents, user, pw, keep_new = args
|
6535
7148
|
filename ||= "testing-" + Time.now.hash.abs.to_s + ""
|
6536
7149
|
dest_dir ||= "/tmp/"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.25761093
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribamar Santarosa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: a gem for keeping Rubyment, a set of ruby helpers
|
14
14
|
email: ribamar@gmail.com
|