rien 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41db30d7cf5c9e875f8d5a6d501d31a870f86db9c6ced2df28b653e3702eb3d2
4
- data.tar.gz: 8d80bc19aaebb6598ff34d31c14948974f69157d5d1c5c897d3c834a5ea11377
3
+ metadata.gz: '0094436a546c52a481feb6536ee79b3fa8927c8ec06e23c31b78fad3d24ecb8d'
4
+ data.tar.gz: a1de8fccd8397e1ba2494480e083ef9e0c8f5a7f19ddbe179f0e2ec3b2da6196
5
5
  SHA512:
6
- metadata.gz: eaf3df6e327068cd266cebbf20568458561b7e455380da5274d70dc488dfab3a0c2a5d52e0e4f112738f590df37a79bfbe86d3e72de81dc72fab2f0fa1a6c711
7
- data.tar.gz: a3d37be26849827cb354b13719b2c32ecd0cc747a9f7615dcebc073b688d9c47575af25b518ebaed24bde660d27d76f99a617141ec8c397e0048c089b7466d28
6
+ metadata.gz: f068ad7e92c3920d79bdf09079350eed7494f0046abd9d3b233bd2650b3606ea8b880eb2e79be16da7e5fb18c37b3b705a556cee46dfd9f72e004aaf503d3f7b
7
+ data.tar.gz: 21550da29e351feb4e6cbb43317d0cb7259fc12f3ab2bd48e032aa0848931afb810b94e663a3079af31a9c78cb9361b398579a9cbed3db1aab5615f10197b624
@@ -0,0 +1,102 @@
1
+ # Rien
2
+
3
+ Ruby IR Encoding Gem (Experimental)
4
+
5
+ # Example
6
+
7
+ ```
8
+ Usage: rien [options]
9
+ -e, --encode [FILE] Encode specific ruby file
10
+ -p, --pack [DIR] Pack ruby directory into encoded files
11
+ -o, --out [FILE/DIR] Indicate the output of the encoded file(s)
12
+ -u, --use-rienfile Use Rienfile to configure, override other options
13
+ -s, --silent-mode Suppress all prompts asking for user input
14
+ -t, --tmpdir [DIR] Select a temp directory to store intermediate results
15
+ ```
16
+
17
+ ## Encode Mode
18
+
19
+ Encode single ruby file
20
+
21
+ ```ruby
22
+ # hello.rb
23
+
24
+ puts "Hello Rien"
25
+ ```
26
+
27
+ ```
28
+ rien -e hello.rb -o encoded.rb
29
+
30
+ ruby encoded.rb # => Hello Rien
31
+ ```
32
+
33
+ ## Pack Mode
34
+
35
+ ### Compile all .rb files in the directory
36
+
37
+ ```
38
+ rien -p source -o output
39
+ ```
40
+
41
+ ### Use Rienfile to configure
42
+
43
+ When using `Rienfile` to configure, other options from CLI will be ignored
44
+
45
+ Put a `Rienfile` in your project directory
46
+
47
+ ```ruby
48
+ # source/Rienfile
49
+
50
+ Rien.configure do |config|
51
+ # The syntax is the same as glob used in class Dir
52
+ # [Optional] includes all files by default
53
+ config.includes = ["app/**/*", "lib/**/*"]
54
+ # [Optional] excludes nothing by default
55
+ config.excludes = ["**/*.py",
56
+ "lib/**/templates/**/*",
57
+ "**/init.rb"]
58
+
59
+ # [Optional] set to rien_output by default
60
+ config.output = "compiled"
61
+
62
+ # Rien will wait user to input in console when
63
+ # finding suspicious already compiled file
64
+ # set this to true to turn it off
65
+ # [Optional] set to false by default
66
+ config.silent = false
67
+
68
+ # [Optional] use Dir.tmpdir/rien by default
69
+ # aka. /tmp/rien for linux
70
+ config.tmpdir = "tmpdir/rien"
71
+
72
+ end
73
+ ```
74
+
75
+ and then
76
+
77
+ ```
78
+ rien -p source -u
79
+ ```
80
+ ### Files to be excluded
81
+
82
+ #### Read file and eval
83
+
84
+ Real world code from [redmine/config/initializers/00-core_plugins.rb
85
+ ](https://github.com/redmine/redmine/blob/master/config/initializers/00-core_plugins.rb#L14)
86
+
87
+ ```ruby
88
+ eval(File.read(initializer), binding, initializer)
89
+ ```
90
+
91
+ Compile `lib/plugins/**/init.rb` may lead to a such error in runtime
92
+ ```
93
+ init.rb:5:in `<main>': undefined local variable or method `config' for main:Object (NameError)
94
+ ```
95
+
96
+ Use `Rinefile` to exclude `lib/plugins/**/init.rb`
97
+
98
+ ### Temporary directory
99
+
100
+ Rien uses a `tmpdir` to store intermediate results and timestamps to distinguish them.
101
+
102
+ Check your `tmpdir` (`/tmp/rien` for linux by default) to clean unsuccessful build results.
data/bin/rien CHANGED
@@ -1,80 +1,5 @@
1
1
  #!/bin/ruby
2
2
 
3
- require 'optparse'
4
- require 'rien'
5
- require 'fileutils'
6
- require 'ruby-progressbar'
3
+ require "rien"
7
4
 
8
- options = {
9
- mode: :help,
10
- }
11
-
12
- parser = OptionParser.new do |opts|
13
- opts.banner = 'Usage: rien [options]'
14
- opts.on('-e', '--encode [FILE]', 'Encode specific ruby file', String) do |v|
15
- options[:mode] = :encode
16
- options[:file] = v
17
- options[:output] ||= "output.rb"
18
- end
19
-
20
- opts.on('-p', '--pack [DIR]', 'Pack ruby directory into encoded files', String) do |v|
21
- options[:mode] = :pack
22
- options[:file] = v
23
- options[:output] ||= "rien_output"
24
- end
25
-
26
- opts.on('-o' '--out [FILE/DIR]', 'Indicate the output of the encoded file(s)', String) do |v|
27
- options[:output] = v
28
- end
29
- end
30
-
31
- parser.parse!
32
-
33
- case options[:mode]
34
- when :encode
35
- encoder = Rien::Encoder.new
36
- bytes = encoder.encode_file(options[:file])
37
- generated_name = options[:output]
38
- # Check if end with .rb and no files generated existing
39
-
40
- File.open("#{generated_name}.rbc", 'wb') do |f|
41
- f.write bytes
42
- end
43
-
44
- File.open(generated_name, 'w') do |f|
45
- f.write encoder.bootstrap
46
- end
47
- when :pack
48
- source = options[:file]
49
- destination = options[:output]
50
- FileUtils.cp_r source, destination
51
- encoder = Rien::Encoder.new
52
-
53
- files = Dir.glob(File.join(destination, "**/*.rb"))
54
- progressbar = ProgressBar.create(:title => "Generating", :starting_at => 0, :total => files.length)
55
-
56
- files.each do |path|
57
- progressbar.log("Compiling: #{path}")
58
- begin
59
- bytes = encoder.encode_file(path)
60
- File.open("#{path}.rbc", 'wb') do |f|
61
- f.write bytes
62
- end
63
-
64
- # Replace file with bootstrap
65
- FileUtils.rm(path)
66
- File.open(path, 'w') do |f|
67
- f.write encoder.bootstrap
68
- end
69
-
70
- progressbar.increment
71
- rescue Exception
72
- # ignore
73
- progressbar.increment
74
- end
75
- end
76
- when :help
77
- puts parser
78
- else
79
- puts parser
80
- end
5
+ Rien::Cli.new.start
@@ -1,7 +1,13 @@
1
1
  require 'zlib'
2
2
 
3
+ require_relative 'rien/core_ext/string'
4
+
3
5
  require_relative 'rien/version'
4
6
  require_relative 'rien/const'
5
7
 
8
+ require_relative 'rien/configurable'
9
+
6
10
  require_relative 'rien/decoder'
7
11
  require_relative 'rien/encoder'
12
+
13
+ require_relative 'rien/cli'
@@ -0,0 +1,234 @@
1
+ require "optparse"
2
+ require "ruby-progressbar"
3
+ require "fileutils"
4
+
5
+ module Rien::CliHelper
6
+ class CliHelperStatus
7
+ attr_accessor :silent
8
+
9
+ def initialize
10
+ @silent = false
11
+ end
12
+ end
13
+
14
+ private def status
15
+ @status ||= CliHelperStatus.new
16
+ end
17
+
18
+ private def encoder
19
+ @encoder ||= Rien::Encoder.new
20
+ end
21
+
22
+ private def wait_user_on_encoded(path)
23
+ if path.match(".rbc") && !status.silent
24
+ print "\n#{path} maybe have already been encoded, continue? (a/y/n) ".yellow
25
+ user_input = STDIN.gets.chomp.downcase
26
+ if user_input == "a"
27
+ status.silent = true # skip all warnings
28
+ elsif user_input == "y"
29
+ # ignore
30
+ else
31
+ abort("Manually abort".red)
32
+ end
33
+ end
34
+ end
35
+
36
+ # Notice:
37
+ # this path must be relative path,
38
+ # or it would break after moving to another directory
39
+ private def encode(path)
40
+ wait_user_on_encoded(path)
41
+
42
+ begin
43
+ bytes = encoder.encode_file(path)
44
+ rescue Exception => e
45
+ abort "\nFailed to encode #{path}, reason:\n#{e.message}".red
46
+ end
47
+
48
+ bytes
49
+ end
50
+
51
+ private def export_single_encoded(source, output)
52
+ bytes = encode(source)
53
+
54
+ File.open("#{output}.rbc", "wb") do |f|
55
+ f.write bytes
56
+ end
57
+
58
+ File.open(output, "w") do |f|
59
+ f.write encoder.bootstrap
60
+ end
61
+ end
62
+
63
+ private def replace_with_encoded(path)
64
+ bytes = encode(path)
65
+
66
+ # Write encoded file
67
+ File.open("#{path}.rbc", "wb") do |f|
68
+ f.write bytes
69
+ end
70
+
71
+ # Replace file with bootstrap
72
+ FileUtils.rm(path)
73
+ File.open(path, "w") do |f|
74
+ f.write encoder.bootstrap
75
+ end
76
+ end
77
+
78
+ private def pack_files(paths)
79
+ progressbar = ProgressBar.create(:title => "Generating",
80
+ :starting_at => 0,
81
+ :length => 80,
82
+ :total => paths.length,
83
+ :smoothing => 0.6,
84
+ :format => "%t |%b>>%i| %p%% %a")
85
+
86
+ paths.each do |path|
87
+ progressbar.log("Compiling: #{path}")
88
+ replace_with_encoded(path) # Wirte encoded file and replace the orginal ruby source file with bootstrap
89
+ progressbar.increment
90
+ end
91
+ end
92
+
93
+ private def copy_dir(source, output)
94
+ FileUtils.mkdir_p output
95
+ FileUtils.cp_r File.join(source, "."), output
96
+ rescue Exception => e
97
+ abort("\nFailed to copy #{source} to #{output}, reason: #{e.message}".red)
98
+ end
99
+
100
+ private def move_dir(source, output)
101
+ FileUtils.mv "#{source}", output
102
+ rescue Exception => e
103
+ abort("\nFailed to move #{source} to #{output}, reason: #{e.message}".red)
104
+ end
105
+
106
+ private def pack_all_files_in_directory(source, output, tmpdir)
107
+ # Copy to temp workspace
108
+ time_stamp = Time.now.strftime("%Y%m%d%H%M%S")
109
+ temp_workspace = File.expand_path(time_stamp, tmpdir)
110
+ copy_dir(source, temp_workspace)
111
+
112
+ # Change to temp workspace
113
+ source_dir = File.absolute_path(File.dirname(source))
114
+ Dir.chdir(temp_workspace)
115
+
116
+ # Encode
117
+ files = Dir["./**/*.rb"] # pack all files
118
+ pack_files(files)
119
+
120
+ # Clean up
121
+ puts "Successed to compile and pack #{source} into #{output}\ntotal #{files.length} file(s)".green
122
+ Dir.chdir(source_dir)
123
+ move_dir(temp_workspace, output)
124
+ end
125
+
126
+ private def use_rienfile_to_pack(source)
127
+ # Eval Rienfile
128
+ begin
129
+ rienfile = File.expand_path("Rienfile", source)
130
+ load rienfile
131
+ rescue Exception => e
132
+ abort "\nFailed to load Rienfile, reason:\n#{e.message}".red
133
+ end
134
+
135
+ # Configure
136
+ status.silent = Rien.config.silent
137
+ output = Rien.config.output
138
+ tmpdir = Rien.config.tmpdir
139
+
140
+ # Copy to temp workspace
141
+ time_stamp = Time.now.strftime("%Y%m%d%H%M%S")
142
+ temp_workspace = File.expand_path(time_stamp, tmpdir)
143
+ copy_dir(source, temp_workspace)
144
+
145
+ # Change to temp workspace
146
+ source_dir = File.absolute_path(File.dirname(source))
147
+ Dir.chdir(temp_workspace)
148
+
149
+ # Encode
150
+ files = Rien.config.effective_paths
151
+ pack_files(files)
152
+
153
+ # Clean up
154
+ puts "Successed to compile and pack #{source} into #{output}\n" \
155
+ "using #{rienfile}\n" \
156
+ "total #{files.length} file(s)".green
157
+ Dir.chdir(source_dir)
158
+ move_dir(temp_workspace, output)
159
+ end
160
+ end
161
+
162
+ class Rien::Cli
163
+ include Rien::CliHelper
164
+
165
+ def initialize
166
+ @options = {
167
+ mode: :help,
168
+ }
169
+
170
+ @parser = OptionParser.new do |opts|
171
+ opts.banner = "Usage: rien [options]"
172
+ opts.on("-e", "--encode [FILE]", "Encode specific ruby file", String) do |v|
173
+ @options[:mode] = :encode
174
+ @options[:file] = v
175
+ @options[:output] ||= "output.rb"
176
+ end
177
+
178
+ opts.on("-p", "--pack [DIR]", "Pack ruby directory into encoded files", String) do |v|
179
+ @options[:mode] = :pack
180
+ @options[:file] = v
181
+ @options[:output] ||= "rien_output"
182
+ @options[:tmpdir] ||= "/tmp/rien"
183
+ end
184
+
185
+ opts.on("-o", "--out [FILE/DIR]", "Indicate the output of the encoded file(s)", String) do |v|
186
+ @options[:output] = v
187
+ end
188
+
189
+ opts.on("-u", "--use-rienfile", "Use Rienfile to configure, override other options", String) do
190
+ @options[:rienfile] = true
191
+ end
192
+
193
+ opts.on("-s", "--silent-mode", "Suppress all prompts asking for user input", String) do
194
+ @options[:silent] = true
195
+ end
196
+
197
+ opts.on("-t", "--tmpdir [DIR]", "Select a temp directory to store intermediate results", String) do |v|
198
+ @options[:tmpdir] = v
199
+ end
200
+ end
201
+ end
202
+
203
+ def start
204
+ @parser.parse!
205
+ case @options[:mode]
206
+ when :encode
207
+ source = @options[:file]
208
+ output = @options[:output]
209
+ status.silent = @options[:silent]
210
+
211
+ export_single_encoded(source, output)
212
+
213
+ puts "Successed to compile #{source} into #{output} and #{output}.rbc".green
214
+ when :pack
215
+ source = @options[:file]
216
+ abort("\nOnly directory can be packed".red) unless File.directory?(source)
217
+
218
+ use_rienfile = @options[:rienfile]
219
+ if use_rienfile # Ignore other options from CLI
220
+ use_rienfile_to_pack(source)
221
+ else # Use options from CLI
222
+ output = @options[:output]
223
+ tmpdir = @options[:tmpdir]
224
+ status.silent = @options[:silent]
225
+
226
+ pack_all_files_in_directory(source, output, tmpdir)
227
+ end
228
+ when :help
229
+ puts @parser
230
+ else
231
+ puts @parser
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,55 @@
1
+ require 'tmpdir'
2
+
3
+ module Rien::Configurable
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def config
10
+ @config ||= Configuration.new
11
+ end
12
+
13
+ def configure
14
+ yield(config)
15
+ end
16
+ end
17
+
18
+ class Configuration
19
+ attr_accessor :includes, :excludes, :output, :tmpdir, :silent
20
+
21
+ def initialize
22
+ @includes = ["**/*"] # include all paths by default
23
+ @output = "rien_output" # final result
24
+ @tmpdir = File.expand_path("rien", Dir.tmpdir) # store intermediate results
25
+ @silent = false # see cli.rb wait_user_on_encoded
26
+ end
27
+
28
+ def effective_paths
29
+ temp_paths = [] # store ruby files and directories
30
+ effective_paths = [] # only ruby files to be compiled
31
+
32
+ @includes.each do |path|
33
+ path = "./#{path}"
34
+ temp_paths += Dir[path]
35
+ end
36
+
37
+ unless excludes.nil?
38
+ @excludes.each do |path|
39
+ path = "./#{path}"
40
+ temp_paths -= Dir[path]
41
+ end
42
+ end
43
+
44
+ temp_paths.each do |path|
45
+ effective_paths.push(path) unless File.directory?(path) || path.match("Rienfile")
46
+ end
47
+
48
+ effective_paths
49
+ end
50
+ end
51
+ end
52
+
53
+ module Rien
54
+ include Rien::Configurable
55
+ end
@@ -0,0 +1,21 @@
1
+ class String
2
+ def colorize(color_code) # ANSI color code
3
+ "\e[#{color_code}m#{self}\e[0m"
4
+ end
5
+
6
+ def red
7
+ colorize(31)
8
+ end
9
+
10
+ def green
11
+ colorize(32)
12
+ end
13
+
14
+ def yellow
15
+ colorize(33)
16
+ end
17
+
18
+ def blue
19
+ colorize(34)
20
+ end
21
+ end
@@ -3,8 +3,9 @@ class Rien::Encoder
3
3
  @version = version
4
4
  end
5
5
 
6
- def encode(str)
7
- bytecode = RubyVM::InstructionSequence.compile(str, options: Rien::Const::COMPILE_OPTION)
6
+ def encode_file(path)
7
+ # RubyVM::InstructionSequence.compile(source, __FILE__, relative_path, options)
8
+ bytecode = RubyVM::InstructionSequence.compile(File.read(path), path, path, options: Rien::Const::COMPILE_OPTION)
8
9
  Zlib::Deflate.deflate(bytecode.to_binary)
9
10
  end
10
11
 
@@ -17,8 +18,4 @@ Rien::Decoder.eval("\#{__FILE__}.rbc")
17
18
  EOL
18
19
  end
19
20
 
20
- def encode_file(filepath)
21
- src = File.read(filepath)
22
- self.encode(src)
23
- end
24
21
  end
@@ -1,3 +1,3 @@
1
1
  module Rien
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rien
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - CodeRemixer
8
- autorequire:
9
- bindir:
10
- - bin
8
+ autorequire:
9
+ bindir: bin
11
10
  cert_chain: []
12
- date: 2019-08-24 00:00:00.000000000 Z
11
+ date: 2020-08-10 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: ruby-progressbar
@@ -34,19 +33,22 @@ extensions: []
34
33
  extra_rdoc_files: []
35
34
  files:
36
35
  - LICENSE
36
+ - README.md
37
37
  - bin/rien
38
38
  - lib/rien.rb
39
+ - lib/rien/cli.rb
40
+ - lib/rien/configurable.rb
39
41
  - lib/rien/const.rb
42
+ - lib/rien/core_ext/string.rb
40
43
  - lib/rien/decoder.rb
41
44
  - lib/rien/encoder.rb
42
45
  - lib/rien/version.rb
43
- - rien.gemspec
44
46
  homepage: https://github.com/coderemixer/rien
45
47
  licenses:
46
48
  - Apache-2.0
47
49
  metadata:
48
- issue_tracker: https://github.com/coderemixer/rien/issues
49
- post_install_message:
50
+ bug_tracker_uri: https://github.com/coderemixer/rien/issues
51
+ post_install_message:
50
52
  rdoc_options: []
51
53
  require_paths:
52
54
  - lib
@@ -54,15 +56,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
54
56
  requirements:
55
57
  - - ">="
56
58
  - !ruby/object:Gem::Version
57
- version: 2.4.5
59
+ version: 2.7.0
58
60
  required_rubygems_version: !ruby/object:Gem::Requirement
59
61
  requirements:
60
62
  - - ">="
61
63
  - !ruby/object:Gem::Version
62
64
  version: '0'
63
65
  requirements: []
64
- rubygems_version: 3.0.3
65
- signing_key:
66
+ rubygems_version: 3.1.2
67
+ signing_key:
66
68
  specification_version: 4
67
69
  summary: Ruby IR Encoding
68
70
  test_files: []
@@ -1,21 +0,0 @@
1
- require './lib/rien'
2
-
3
- Gem::Specification.new do |s|
4
- s.name = 'rien'
5
- s.version = Rien::VERSION
6
- s.required_ruby_version = '>=2.4.5'
7
- s.date = Time.now.strftime('%Y-%m-%d')
8
- s.summary = 'Ruby IR Encoding'
9
- s.description = 'Encode your Ruby code for distribution'
10
- s.authors = ['CodeRemixer']
11
- s.email = ['dsh0416@gmail.com']
12
- s.require_paths = ['lib']
13
- s.bindir = ['bin']
14
- s.executables = ['rien']
15
- s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|.resources)/}) } \
16
- - %w(README.md CODE_OF_CONDUCT.md CONTRIBUTING.md Gemfile Rakefile my_general.gemspec .gitignore .rspec .codeclimate.yml .rubocop.yml .travis.yml logo.png Rakefile Gemfile)
17
- s.homepage = 'https://github.com/coderemixer/rien'
18
- s.metadata = { 'issue_tracker' => 'https://github.com/coderemixer/rien/issues' }
19
- s.license = 'Apache-2.0'
20
- s.add_runtime_dependency 'ruby-progressbar', '~> 1.9'
21
- end