replr 0.2.0 → 0.3.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/bin/replr +1 -1
- data/lib/replr.rb +2 -142
- data/lib/{Dockerfile → replr/Dockerfile.template} +1 -1
- data/lib/replr/argument_processor.rb +55 -0
- data/lib/replr/base.rb +3 -0
- data/lib/replr/process_runner.rb +48 -0
- data/lib/replr/repl_maker.rb +114 -0
- data/lib/{replr-bootstrap.rb → replr/replr-bootstrap.rb} +0 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3baafd9472b824734be5f808a2618e87120ba9adb87ef3a5fa6e09685d0a12a
|
4
|
+
data.tar.gz: d54f510d068f819de8aae695e76abe3fe7f45642cc7f5574d44ccf1d39509856
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df87112be9e15dcb0a9754d6baa12c520567a335c78cd582201ed76aaa190dd5c0e49faba2f4c18e3d7a7dff43cf2e9fca0fe79fc63f0fc9561e1849e207e8c6
|
7
|
+
data.tar.gz: '03887359a7e34df5f4ec3c8583cc93cb0bb7663941b1db3a7643923259f0cde76a4ea14e24ed404e579c54437c8b91bba25162f134189ba60ea8b45ac540bb67'
|
data/bin/replr
CHANGED
data/lib/replr.rb
CHANGED
@@ -1,142 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
# :nodoc:
|
5
|
-
class Replr
|
6
|
-
attr_reader :arguments, :workdir, :docker_image_tag
|
7
|
-
|
8
|
-
def start
|
9
|
-
@arguments = ARGV.map { |argument| argument.downcase.strip }
|
10
|
-
|
11
|
-
check_docker!
|
12
|
-
check_argument_length!
|
13
|
-
check_arguments!
|
14
|
-
|
15
|
-
@workdir = Dir.mktmpdir
|
16
|
-
@docker_image_tag = "replr/ruby-#{libraries.join('-')}"
|
17
|
-
|
18
|
-
process_arguments
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def process_arguments
|
24
|
-
if arguments[0] == 'prune'
|
25
|
-
execute_prune_command
|
26
|
-
else
|
27
|
-
copy_library_file
|
28
|
-
copy_docker_file
|
29
|
-
initialize_docker_repl
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def check_argument_length!
|
34
|
-
if arguments.empty?
|
35
|
-
puts_usage
|
36
|
-
exit
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def check_arguments!
|
41
|
-
unless ['ruby', 'prune'].include? arguments[0]
|
42
|
-
puts_error 'Only supports ruby as a stack right now'
|
43
|
-
puts_usage
|
44
|
-
exit
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def puts_usage
|
49
|
-
puts_error "\nUsage: replr <stack> <libraries...>\n\n"
|
50
|
-
puts_error "A single line REPL for your favorite languages & libraries\n\n"
|
51
|
-
puts_error "\t<stack> is now only 'ruby'"
|
52
|
-
puts_error "\t<libraries...> is a space separated list of libraries for the stack\n\n"
|
53
|
-
puts_error "More commands:\n\n\treplr prune to delete all replr docker images (this saves space)"
|
54
|
-
end
|
55
|
-
|
56
|
-
def execute_prune_command
|
57
|
-
prune_command = %q(docker images -a | grep "replr/" | awk '{print $3}' | xargs docker rmi)
|
58
|
-
system(prune_command)
|
59
|
-
end
|
60
|
-
|
61
|
-
def check_docker!
|
62
|
-
unless system('which docker >/dev/null')
|
63
|
-
puts_error 'Needs docker installed & in path to work.'
|
64
|
-
exit
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def puts_error(string)
|
69
|
-
STDERR.puts(string)
|
70
|
-
end
|
71
|
-
|
72
|
-
def copy_library_file
|
73
|
-
Dir.chdir(workdir) do
|
74
|
-
File.open('Gemfile', 'w') do |f|
|
75
|
-
f.write(library_file_with(libraries))
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def copy_docker_file
|
81
|
-
docker_file = "#{__dir__}/Dockerfile"
|
82
|
-
bootstrap_file = "#{__dir__}/replr-bootstrap.rb"
|
83
|
-
FileUtils.cp(docker_file, workdir)
|
84
|
-
FileUtils.cp(bootstrap_file, workdir)
|
85
|
-
end
|
86
|
-
|
87
|
-
def libraries
|
88
|
-
arguments[1..-1]
|
89
|
-
end
|
90
|
-
|
91
|
-
def library_file_with(libraries)
|
92
|
-
gemfile = "source 'https://rubygems.org/'\n"
|
93
|
-
libraries.each do |library|
|
94
|
-
gemfile << "gem '#{library}'\n"
|
95
|
-
end
|
96
|
-
gemfile
|
97
|
-
end
|
98
|
-
|
99
|
-
def initialize_docker_repl
|
100
|
-
Dir.chdir(workdir) do
|
101
|
-
build_command = "docker build -t #{docker_image_tag} ."
|
102
|
-
run_command = "docker run --rm -it #{docker_image_tag}"
|
103
|
-
matching = Regexp.union([/upgrading/i, /installing/i, /gem/i])
|
104
|
-
not_matching = Regexp.union([/step/i])
|
105
|
-
execute_filtered_process(build_command, matching,
|
106
|
-
not_matching) do |stderr, process_thread|
|
107
|
-
execute_command_if_not_stderr(run_command, stderr, process_thread)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Runs *command* and only prints those lines that match
|
113
|
-
# *matching_regex* and doesn't match *not_matching_regex*. After
|
114
|
-
# execution, it passes *stderr* and the waiting *process_thread*
|
115
|
-
# to a block.
|
116
|
-
def execute_filtered_process(command, matching_regex,
|
117
|
-
not_matching_regex, &_block)
|
118
|
-
Open3.popen3(command) do |_stdin, stdout, stderr, process_thread|
|
119
|
-
stdout.each_line do |outline|
|
120
|
-
if outline.match(matching_regex) &&
|
121
|
-
!outline.match(not_matching_regex)
|
122
|
-
puts outline
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Yield to block to process next set of commands or handle stderr
|
127
|
-
yield(stderr, process_thread)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# Executes *new_command* if the previous *process_thread* had a
|
132
|
-
# non-zero return. Otherwise prints out *stderr* of the previous
|
133
|
-
# process to *STDERR*
|
134
|
-
def execute_command_if_not_stderr(new_command, stderr, process_thread)
|
135
|
-
outerror = stderr.read.chomp
|
136
|
-
if process_thread.value.to_i.zero?
|
137
|
-
system(new_command)
|
138
|
-
else
|
139
|
-
STDERR.puts outerror
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
1
|
+
require_relative 'replr/base'
|
2
|
+
require_relative 'replr/repl_maker'
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative '../replr'
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
module Replr
|
5
|
+
# Processes command-line arguments
|
6
|
+
class ArgumentProcessor
|
7
|
+
COMMANDS = ['prune']
|
8
|
+
STACKS = ['ruby']
|
9
|
+
|
10
|
+
attr_reader :arguments
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@arguments = ARGV.map { |argument| argument.downcase.strip }
|
14
|
+
check_argument_length!
|
15
|
+
check_arguments!
|
16
|
+
end
|
17
|
+
|
18
|
+
def check_argument_length!
|
19
|
+
if arguments.empty?
|
20
|
+
puts_usage
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def check_arguments!
|
26
|
+
valid_stack = STACKS.detect do |stack|
|
27
|
+
arguments[0].match(/^#{stack}:?.*?/)
|
28
|
+
end
|
29
|
+
valid_command = COMMANDS.detect do |command|
|
30
|
+
arguments[0] == command
|
31
|
+
end
|
32
|
+
|
33
|
+
unless valid_stack or valid_command
|
34
|
+
puts_error "First argument must be either be a command:
|
35
|
+
\t#{COMMANDS.join(' ')}
|
36
|
+
or one of a supported stack:
|
37
|
+
\t#{STACKS.join(' ')}"
|
38
|
+
puts_usage
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def puts_usage
|
44
|
+
puts_error "\nUsage: replr <stack> <libraries...>\n\n"
|
45
|
+
puts_error "A single line REPL for your favorite languages & libraries\n\n"
|
46
|
+
puts_error "\t<stack> is now only 'ruby'"
|
47
|
+
puts_error "\t<libraries...> is a space separated list of libraries for the stack\n\n"
|
48
|
+
puts_error "More commands:\n\n\treplr prune to delete all replr docker images (this saves space)"
|
49
|
+
end
|
50
|
+
|
51
|
+
def puts_error(string)
|
52
|
+
STDERR.puts(string)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/replr/base.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative '../replr'
|
2
|
+
|
3
|
+
module Replr
|
4
|
+
# Executes and manages processes
|
5
|
+
class ProcessRunner
|
6
|
+
# Executes command using system. Use this when you have no
|
7
|
+
# need for a return value
|
8
|
+
def execute_command(command)
|
9
|
+
system(command)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Checks whether process exists using `which`
|
13
|
+
def process_exists?(process)
|
14
|
+
system("which #{process} >/dev/null")
|
15
|
+
end
|
16
|
+
|
17
|
+
# Runs *command* and only prints those lines that match
|
18
|
+
# *matching_regex* and doesn't match *not_matching_regex*. After
|
19
|
+
# execution, it passes *stderr* and the waiting *process_thread*
|
20
|
+
# to a block.
|
21
|
+
def execute_filtered_process(command, matching_regex,
|
22
|
+
not_matching_regex, &_block)
|
23
|
+
Open3.popen3(command) do |_stdin, stdout, stderr, process_thread|
|
24
|
+
stdout.each_line do |outline|
|
25
|
+
if outline.match(matching_regex) &&
|
26
|
+
!outline.match(not_matching_regex)
|
27
|
+
puts outline
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Yield to block to process next set of commands or handle stderr
|
32
|
+
yield(stderr, process_thread)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Executes *new_command* if the previous *process_thread* had a
|
37
|
+
# non-zero return. Otherwise prints out *stderr* of the previous
|
38
|
+
# process to *STDERR*
|
39
|
+
def execute_command_if_not_stderr(new_command, stderr, process_thread)
|
40
|
+
outerror = stderr.read.chomp
|
41
|
+
if process_thread.value.to_i.zero?
|
42
|
+
system(new_command)
|
43
|
+
else
|
44
|
+
STDERR.puts outerror
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require_relative '../replr'
|
2
|
+
require_relative 'argument_processor'
|
3
|
+
require_relative 'process_runner'
|
4
|
+
|
5
|
+
require 'tmpdir'
|
6
|
+
require 'open3'
|
7
|
+
|
8
|
+
# :nodoc:
|
9
|
+
module Replr
|
10
|
+
# Creates a REPL using template Dockerfiles & libraries
|
11
|
+
class REPLMaker
|
12
|
+
attr_reader :argument_processor, :process_runner
|
13
|
+
attr_reader :stack, :libraries, :workdir
|
14
|
+
|
15
|
+
def start
|
16
|
+
@argument_processor = Replr::ArgumentProcessor.new
|
17
|
+
@process_runner = Replr::ProcessRunner.new
|
18
|
+
|
19
|
+
@stack = argument_processor.arguments[0]
|
20
|
+
@libraries = argument_processor.arguments[1..-1].sort!
|
21
|
+
@workdir = Dir.mktmpdir
|
22
|
+
|
23
|
+
check_docker!
|
24
|
+
execute_processsed_arguments!
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def check_docker!
|
30
|
+
unless process_runner.process_exists?('docker')
|
31
|
+
puts_error 'Needs docker installed & in path to work.'
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def execute_processsed_arguments!
|
37
|
+
if argument_processor.arguments[0] == 'prune'
|
38
|
+
execute_prune_command
|
39
|
+
else
|
40
|
+
copy_library_file
|
41
|
+
copy_initialization_files
|
42
|
+
initialize_docker_repl
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def execute_prune_command
|
47
|
+
prune_command = %q(docker images -a | grep "replr/" | awk '{print $3}' | xargs docker rmi)
|
48
|
+
process_runner.execute_command(prune_command)
|
49
|
+
end
|
50
|
+
|
51
|
+
def puts_error(string)
|
52
|
+
STDERR.puts(string)
|
53
|
+
end
|
54
|
+
|
55
|
+
def copy_library_file
|
56
|
+
Dir.chdir(workdir) do
|
57
|
+
File.open('Gemfile', 'w') do |f|
|
58
|
+
f.write(library_file_with(libraries))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def copy_initialization_files
|
64
|
+
create_docker_file
|
65
|
+
bootstrap_file = "#{__dir__}/replr-bootstrap.rb"
|
66
|
+
FileUtils.cp(bootstrap_file, workdir)
|
67
|
+
end
|
68
|
+
|
69
|
+
def create_docker_file
|
70
|
+
_stack, version = stack.split(':')
|
71
|
+
docker_file_template = "#{__dir__}/Dockerfile.template"
|
72
|
+
docker_file_contents = File.read(docker_file_template)
|
73
|
+
docker_file_contents.gsub!('%%VERSION%%', version ? "#{version}-" : '')
|
74
|
+
File.open(File.join(workdir, 'Dockerfile'), 'w') do |file|
|
75
|
+
file.puts docker_file_contents
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def library_file_with(libraries)
|
80
|
+
gemfile = "source 'https://rubygems.org/'\n"
|
81
|
+
libraries.each do |library|
|
82
|
+
if library.include?(':')
|
83
|
+
library, version = library.split(':')
|
84
|
+
gemfile << "gem '#{library}', '#{version}'\n"
|
85
|
+
else
|
86
|
+
gemfile << "gem '#{library}'\n"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
gemfile
|
90
|
+
end
|
91
|
+
|
92
|
+
def initialize_docker_repl
|
93
|
+
Dir.chdir(workdir) do
|
94
|
+
build_command = "docker build -t #{docker_image_tag} ."
|
95
|
+
run_command = "docker run --rm -it #{docker_image_tag}"
|
96
|
+
matching = Regexp.union([/upgrading/i, /installing/i, /gem/i])
|
97
|
+
not_matching = Regexp.union([/step/i])
|
98
|
+
process_runner.execute_filtered_process(build_command, matching,
|
99
|
+
not_matching) do |stderr, process_thread|
|
100
|
+
process_runner.execute_command_if_not_stderr(run_command, stderr, process_thread)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def docker_image_tag
|
106
|
+
normalized_library_string = libraries.map do |library|
|
107
|
+
library.gsub(':', '-v')
|
108
|
+
end.join('-')
|
109
|
+
normalized_stack_string = stack.gsub(':', '-v')
|
110
|
+
|
111
|
+
"replr/#{normalized_stack_string}-#{normalized_library_string}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: replr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vishnu Gopal
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: vg@vishnugopal.com
|
@@ -19,9 +19,13 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- Gemfile
|
21
21
|
- bin/replr
|
22
|
-
- lib/Dockerfile
|
23
|
-
- lib/replr-bootstrap.rb
|
24
22
|
- lib/replr.rb
|
23
|
+
- lib/replr/Dockerfile.template
|
24
|
+
- lib/replr/argument_processor.rb
|
25
|
+
- lib/replr/base.rb
|
26
|
+
- lib/replr/process_runner.rb
|
27
|
+
- lib/replr/repl_maker.rb
|
28
|
+
- lib/replr/replr-bootstrap.rb
|
25
29
|
homepage: https://github.com/vishnugopal/replr
|
26
30
|
licenses:
|
27
31
|
- MIT
|