reflex-packager 0.1.5 → 0.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/release-gem.yml +10 -1
- data/.github/workflows/test.yml +9 -0
- data/ChangeLog.md +7 -0
- data/VERSION +1 -1
- data/bin/reflex +19 -4
- data/lib/reflex/packager/cli.rb +29 -22
- data/lib/reflex/packager/config.rb +6 -2
- data/lib/reflex/packager/macos.rb +2 -0
- data/lib/reflex/packager/profile.rb +36 -11
- data/lib/reflex/packager/templates/macos/main.mm.erb +3 -13
- data/reflex-packager.gemspec +4 -4
- data/test/helper.rb +4 -2
- data/test/test_packager_cli.rb +2 -2
- data/test/test_packager_macos.rb +2 -3
- metadata +10 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10cd5f3004ed2ad53e97c3192fdd570c278a55fffec18e95362a9ba103d73157
|
|
4
|
+
data.tar.gz: 5a944112ad9c122f14273acc46f871c866499f81ee9bbac9fc77a08cc23ab2c2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40515957ed04d11936455f04f6256c37bca7f92d999d72b2e7d39d7e60c3bc5aff26d90be6ce5e5693c33274a1dc28bbcded01ea2684ee957dcbe258e1bac0d4
|
|
7
|
+
data.tar.gz: 45ed0fa02849953d1efee9e9d4f4da15fc1d270b753dcff949d6ebc89d6c84c4621b62d3f535df034627d7fedf8d31f23c2aeb960ed6d60461a3a4da8aa79430
|
|
@@ -26,8 +26,17 @@ jobs:
|
|
|
26
26
|
- name: setup dependencies
|
|
27
27
|
run: "ruby -I.github/workflows -rutils -e 'setup_dependencies'"
|
|
28
28
|
|
|
29
|
+
- name: packages
|
|
30
|
+
run: bundle exec rake packages
|
|
31
|
+
|
|
32
|
+
- name: setup zig
|
|
33
|
+
if: github.event.repository.name == 'reflex-terminal'
|
|
34
|
+
uses: mlugg/setup-zig@v2
|
|
35
|
+
with:
|
|
36
|
+
version: 0.16.0
|
|
37
|
+
|
|
29
38
|
- name: test
|
|
30
|
-
run: bundle exec rake
|
|
39
|
+
run: bundle exec rake test
|
|
31
40
|
|
|
32
41
|
- name: create gem
|
|
33
42
|
id: gem
|
data/.github/workflows/test.yml
CHANGED
|
@@ -27,6 +27,15 @@ jobs:
|
|
|
27
27
|
- name: packages
|
|
28
28
|
run: bundle exec rake verbose packages
|
|
29
29
|
|
|
30
|
+
- name: setup zig
|
|
31
|
+
if: github.event.repository.name == 'reflex-terminal'
|
|
32
|
+
uses: mlugg/setup-zig@v2
|
|
33
|
+
with:
|
|
34
|
+
version: 0.16.0
|
|
35
|
+
|
|
36
|
+
- name: vendor
|
|
37
|
+
run: bundle exec rake vendor
|
|
38
|
+
|
|
30
39
|
- name: lib
|
|
31
40
|
run: bundle exec rake verbose lib
|
|
32
41
|
|
data/ChangeLog.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# reflex-packager ChangeLog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## [v0.2.0] - 2026-08-04
|
|
5
|
+
|
|
6
|
+
- [BREAKING] Replace Profile#template with a templates Hash
|
|
7
|
+
- Add boot script support to Profile
|
|
8
|
+
- Add command field to Profile for the CLI display name
|
|
9
|
+
|
|
10
|
+
|
|
4
11
|
## [v0.1.5] - 2026-06-23
|
|
5
12
|
|
|
6
13
|
- Update dependencies
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.2.0
|
data/bin/reflex
CHANGED
|
@@ -11,12 +11,27 @@ profile = Reflex::Packager::Profile.new(
|
|
|
11
11
|
libraries: %w[Xot Rucy Rays Reflex],
|
|
12
12
|
extensions: %w[rays_ext reflex_ext],
|
|
13
13
|
config_files: %w[reflex.yml reflex.yaml],
|
|
14
|
-
|
|
14
|
+
templates: {'main.rb': <<~MAIN, 'reflex.yml': <<~CONFIG})
|
|
15
15
|
require 'reflex'
|
|
16
16
|
|
|
17
|
-
Reflex.
|
|
18
|
-
|
|
17
|
+
view = Reflex::View.new
|
|
18
|
+
def view.on_draw(e)
|
|
19
|
+
e.painter.font nil, 48
|
|
20
|
+
e.painter.text 'hello, world!', 100, 100
|
|
19
21
|
end
|
|
20
|
-
|
|
22
|
+
|
|
23
|
+
win = Reflex::Window.new
|
|
24
|
+
win.title = '{{name}}'
|
|
25
|
+
win.frame = [100, 100, 400, 300]
|
|
26
|
+
win.add view
|
|
27
|
+
win.show
|
|
28
|
+
|
|
29
|
+
Reflex.start
|
|
30
|
+
MAIN
|
|
31
|
+
name: {{name}}
|
|
32
|
+
version: 1.0.0
|
|
33
|
+
#bundle_id: org.xord.reflex.example.{{name_id}}
|
|
34
|
+
#icon: icon.png
|
|
35
|
+
CONFIG
|
|
21
36
|
|
|
22
37
|
Reflex::Packager::CLI.new(profile).run ARGV.dup
|
data/lib/reflex/packager/cli.rb
CHANGED
|
@@ -40,42 +40,39 @@ module Reflex
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def create(argv)
|
|
43
|
-
argv, = parse argv, "Usage: #{@profile.
|
|
43
|
+
argv, = parse argv, "Usage: #{@profile.command} new NAME"
|
|
44
44
|
|
|
45
45
|
name = argv.shift
|
|
46
46
|
raise Error, 'project name required' unless name
|
|
47
47
|
raise Error, "'#{name}' already exists" if File.exist? name
|
|
48
48
|
|
|
49
49
|
FileUtils.mkdir_p name
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
#bundle_id: com.example.#{name.downcase.gsub(/[^a-z0-9]+/, '')}
|
|
55
|
-
#version: 1.0.0
|
|
56
|
-
#icon: icon.png
|
|
57
|
-
END
|
|
50
|
+
@profile.templates.each do |path, content|
|
|
51
|
+
File.write File.join(name, path.to_s), gsub_template(content, name)
|
|
52
|
+
end
|
|
53
|
+
|
|
58
54
|
puts "Created #{name}/"
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
hints = [
|
|
56
|
+
["cd #{name} && ruby #{@profile.templates.keys.first}", "run the application"],
|
|
57
|
+
["cd #{name} && #{@profile.command} package .", "package as an application"]
|
|
58
|
+
]
|
|
59
|
+
max = hints.map {|cmd,| cmd.length}.max
|
|
60
|
+
hints.each {|cmd, desc| puts " #{cmd.ljust max} # #{desc}"}
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
def package(argv)
|
|
64
|
-
profile
|
|
65
|
-
argv, params = parse argv, "Usage: #{profile.
|
|
64
|
+
profile = @profile
|
|
65
|
+
argv, params = parse argv, "Usage: #{profile.command} package [options] [DIR]" do
|
|
66
66
|
on '--platform PLATFORM', 'target platform (default: macos)'
|
|
67
|
-
on '--config PATH',
|
|
68
|
-
|
|
69
|
-
on '--
|
|
70
|
-
on '--verbose', 'verbose output'
|
|
67
|
+
on '--config PATH', "config file path (default: DIR/#{profile.config_files.first})"
|
|
68
|
+
on '--generate-only', 'generate project files but do not build'
|
|
69
|
+
on '--verbose', 'verbose output'
|
|
71
70
|
end
|
|
72
71
|
|
|
73
72
|
dir = argv.shift || '.'
|
|
74
73
|
platform = (params[:platform] || 'macos').to_sym
|
|
75
|
-
klass = PLATFORMS[platform]
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
config = Config.load @profile, dir, params[:config]
|
|
74
|
+
klass = PLATFORMS[platform] || raise(Error, "unknown platform: '#{platform}'")
|
|
75
|
+
config = Config.load profile, dir, params[:config]
|
|
79
76
|
klass.new(config, verbose: params[:verbose])
|
|
80
77
|
.package generate_only: params[:'generate-only']
|
|
81
78
|
end
|
|
@@ -84,7 +81,7 @@ module Reflex
|
|
|
84
81
|
|
|
85
82
|
def usage()
|
|
86
83
|
<<~END
|
|
87
|
-
Usage: #{@profile.
|
|
84
|
+
Usage: #{@profile.command} <command> [options]
|
|
88
85
|
|
|
89
86
|
Commands:
|
|
90
87
|
new NAME create a new application project
|
|
@@ -105,6 +102,16 @@ module Reflex
|
|
|
105
102
|
return argv, params
|
|
106
103
|
end
|
|
107
104
|
|
|
105
|
+
def gsub_template(str, name)
|
|
106
|
+
{
|
|
107
|
+
name: name,
|
|
108
|
+
name_id: Config.name2id(name)
|
|
109
|
+
}.each do |from, to|
|
|
110
|
+
str = str.gsub "{{#{from}}}", to
|
|
111
|
+
end
|
|
112
|
+
str
|
|
113
|
+
end
|
|
114
|
+
|
|
108
115
|
end# CLI
|
|
109
116
|
|
|
110
117
|
|
|
@@ -21,7 +21,7 @@ module Reflex
|
|
|
21
21
|
name: name,
|
|
22
22
|
bundle_id: hash[:bundle_id] || default_bundle_id(profile, name),
|
|
23
23
|
version: '0.1.0',
|
|
24
|
-
main:
|
|
24
|
+
main: profile.main,
|
|
25
25
|
icon: nil,
|
|
26
26
|
files: nil,
|
|
27
27
|
pods: {
|
|
@@ -88,8 +88,12 @@ module Reflex
|
|
|
88
88
|
|
|
89
89
|
private
|
|
90
90
|
|
|
91
|
+
def self.name2id(name)
|
|
92
|
+
name.downcase.gsub(/[^a-z0-9\-]+/, '')
|
|
93
|
+
end
|
|
94
|
+
|
|
91
95
|
def self.default_bundle_id(profile, name)
|
|
92
|
-
id = name
|
|
96
|
+
id = name2id name
|
|
93
97
|
if id.empty?
|
|
94
98
|
raise Error, "cannot derive a bundle_id from name '#{name}', " +
|
|
95
99
|
"set 'bundle_id' in #{profile.config_files.first}"
|
|
@@ -130,6 +130,8 @@ module Reflex
|
|
|
130
130
|
FileUtils.mkdir_p File.dirname(dest)
|
|
131
131
|
FileUtils.cp_r File.join(config.dir, file), dest
|
|
132
132
|
end
|
|
133
|
+
File.write File.join(dir, profile.boot_main), profile.boot if
|
|
134
|
+
profile.boot_main && profile.boot
|
|
133
135
|
end
|
|
134
136
|
|
|
135
137
|
def generate_icon()
|
|
@@ -13,20 +13,45 @@ module Reflex
|
|
|
13
13
|
#
|
|
14
14
|
class Profile
|
|
15
15
|
|
|
16
|
-
# @param [String]
|
|
17
|
-
# @param [String]
|
|
18
|
-
# @param [String]
|
|
19
|
-
# @param [Array<String>]
|
|
20
|
-
# @param [Array<String>]
|
|
21
|
-
# @param [Array<String>]
|
|
22
|
-
# @param [String]
|
|
16
|
+
# @param [String] pod umbrella pod name (e.g. 'Reflex')
|
|
17
|
+
# @param [String] git umbrella pod git repository
|
|
18
|
+
# @param [String] version umbrella pod version (for the tag)
|
|
19
|
+
# @param [Array<String>] libraries ruby lib bundles to add to load path
|
|
20
|
+
# @param [Array<String>] extensions native exts to register (Init_<name>)
|
|
21
|
+
# @param [Array<String>] config_files config file names, preferred first
|
|
22
|
+
# @param [Hash{String=>String}] templates 'new' scaffold files ({filename => content})
|
|
23
|
+
# @param [String, nil] command CLI command name (default: pod_key)
|
|
24
|
+
# @param [String, nil] boot boot script overrides config main (default: nil)
|
|
23
25
|
#
|
|
24
|
-
def initialize(
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
def initialize(
|
|
27
|
+
pod:, git:, version:, libraries:, extensions:, config_files:, templates:,
|
|
28
|
+
command: nil, boot: nil)
|
|
29
|
+
|
|
30
|
+
@pod = pod
|
|
31
|
+
@git = git
|
|
32
|
+
@version = version
|
|
33
|
+
@libraries = libraries
|
|
34
|
+
@extensions = extensions
|
|
35
|
+
@config_files = config_files
|
|
36
|
+
@templates = templates
|
|
37
|
+
@command = command
|
|
38
|
+
@boot = boot
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
attr_reader :pod, :git, :version, :libraries, :extensions, :config_files,
|
|
42
|
+
:templates, :boot
|
|
43
|
+
|
|
44
|
+
def command()
|
|
45
|
+
@command || pod_key
|
|
27
46
|
end
|
|
28
47
|
|
|
29
|
-
|
|
48
|
+
def main()
|
|
49
|
+
templates.keys.first
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def boot_main()
|
|
53
|
+
@boot ? '__reflex_main__.rb' : nil
|
|
54
|
+
end
|
|
30
55
|
|
|
31
56
|
def pod_key()
|
|
32
57
|
pod.downcase.to_sym
|
|
@@ -16,28 +16,18 @@ main (int argc, const char* argv[])
|
|
|
16
16
|
{
|
|
17
17
|
@autoreleasepool
|
|
18
18
|
{
|
|
19
|
-
NSString* appDir =
|
|
20
|
-
[NSBundle.mainBundle.resourcePath stringByAppendingPathComponent:@"app"];
|
|
21
|
-
|
|
22
|
-
// the application loads images by paths relative to the script
|
|
19
|
+
NSString* appDir = [NSBundle.mainBundle.resourcePath stringByAppendingPathComponent:@"app"];
|
|
23
20
|
[NSFileManager.defaultManager changeCurrentDirectoryPath:appDir];
|
|
24
21
|
|
|
25
22
|
<%- extensions.each do |ext| -%>
|
|
26
23
|
[CRuby addExtension:@"<%= ext %>" init:^{Init_<%= ext %>();}];
|
|
27
24
|
<%- end -%>
|
|
28
25
|
|
|
29
|
-
for (NSString* lib in @[<%= libraries.map {
|
|
26
|
+
for (NSString* lib in @[<%= libraries.map {"@\"#{_1}\""}.join ', ' %>])
|
|
30
27
|
[CRuby addLibrary:lib bundle:NSBundle.mainBundle];
|
|
31
28
|
|
|
32
|
-
NSString* main = [appDir stringByAppendingPathComponent:@"<%= config.main %>"];
|
|
33
|
-
|
|
34
|
-
// add the script directory to the load path so that apps split
|
|
35
|
-
// into multiple files can require each other
|
|
36
29
|
[CRuby evaluate:[NSString stringWithFormat:@"$LOAD_PATH.unshift '%@'", appDir]];
|
|
37
|
-
|
|
38
|
-
// the script calls Reflex.start, which runs [NSApp run] and blocks
|
|
39
|
-
// here until the application quits
|
|
40
|
-
[CRuby start:main];
|
|
30
|
+
[CRuby start:[appDir stringByAppendingPathComponent:@"<%= profile.boot_main || config.main %>"]];
|
|
41
31
|
}
|
|
42
32
|
return 0;
|
|
43
33
|
}
|
data/reflex-packager.gemspec
CHANGED
|
@@ -25,10 +25,10 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
s.platform = Gem::Platform::RUBY
|
|
26
26
|
s.required_ruby_version = '>= 3.0.0'
|
|
27
27
|
|
|
28
|
-
s.add_dependency 'xot', '~> 0.
|
|
29
|
-
s.add_dependency 'rucy', '~> 0.
|
|
30
|
-
s.add_dependency 'rays', '~> 0.
|
|
31
|
-
s.add_dependency 'reflexion', '~> 0.
|
|
28
|
+
s.add_dependency 'xot', '~> 0.4.0'
|
|
29
|
+
s.add_dependency 'rucy', '~> 0.4.0'
|
|
30
|
+
s.add_dependency 'rays', '~> 0.4.0'
|
|
31
|
+
s.add_dependency 'reflexion', '~> 0.6.0'
|
|
32
32
|
|
|
33
33
|
s.files = `git ls-files`.split $/
|
|
34
34
|
s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
|
data/test/helper.rb
CHANGED
|
@@ -19,10 +19,12 @@ TEST_PROFILE = Reflex::Packager::Profile.new(
|
|
|
19
19
|
libraries: %w[Xot Rucy Rays Reflex],
|
|
20
20
|
extensions: %w[rays_ext reflex_ext],
|
|
21
21
|
config_files: %w[reflex.yml reflex.yaml],
|
|
22
|
-
|
|
22
|
+
templates: {'main.rb': <<~MAIN, 'reflex.yml': <<~CONFIG})
|
|
23
23
|
require 'reflex'
|
|
24
24
|
|
|
25
25
|
Reflex.start do
|
|
26
26
|
Reflex::Window.new(title: '{{name}}', frame: [100, 100, 400, 300]).show
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
MAIN
|
|
29
|
+
name: myapp
|
|
30
|
+
CONFIG
|
data/test/test_packager_cli.rb
CHANGED
|
@@ -40,8 +40,8 @@ class TestPackagerCLI < Test::Unit::TestCase
|
|
|
40
40
|
def test_new()
|
|
41
41
|
tmpdir do
|
|
42
42
|
capture {cli.create ['myapp']}
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
assert_true File.file?('myapp/main.rb')
|
|
44
|
+
assert_true File.file?('myapp/reflex.yml')
|
|
45
45
|
|
|
46
46
|
main = File.read('myapp/main.rb')
|
|
47
47
|
assert_include main, "require 'reflex'"
|
data/test/test_packager_macos.rb
CHANGED
|
@@ -160,13 +160,12 @@ class TestPackagerMacOS < Test::Unit::TestCase
|
|
|
160
160
|
packager "main: app.rb", files: %w[app.rb] do |pkg, dir|
|
|
161
161
|
pkg.generate
|
|
162
162
|
str = read dir, 'src/main.mm'
|
|
163
|
-
assert_include str, '@"app
|
|
163
|
+
assert_include str, '@"app"' # the bundled app dir
|
|
164
164
|
assert_include str, 'Init_reflex_ext' # native ext registered
|
|
165
165
|
assert_include str, 'Init_rays_ext'
|
|
166
166
|
assert_include str, '@"Reflex"' # library bundle added
|
|
167
167
|
assert_include str, 'changeCurrentDirectoryPath' # cwd set to app dir
|
|
168
|
-
assert_include str, '@"app"'
|
|
169
|
-
assert_include str, '[CRuby start:main]'
|
|
168
|
+
assert_include str, '@"app.rb"' # the entry script
|
|
170
169
|
end
|
|
171
170
|
end
|
|
172
171
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: reflex-packager
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- xordog
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: xot
|
|
@@ -16,56 +16,56 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
19
|
+
version: 0.4.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
26
|
+
version: 0.4.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rucy
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 0.
|
|
33
|
+
version: 0.4.0
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 0.
|
|
40
|
+
version: 0.4.0
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rays
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.
|
|
47
|
+
version: 0.4.0
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.
|
|
54
|
+
version: 0.4.0
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: reflexion
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 0.
|
|
61
|
+
version: 0.6.0
|
|
62
62
|
type: :runtime
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 0.
|
|
68
|
+
version: 0.6.0
|
|
69
69
|
description: CLI tool to package Reflex applications as native macOS application bundles.
|
|
70
70
|
email: xordog@gmail.com
|
|
71
71
|
executables:
|