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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1711e27578931850f67a30057b13f315126fdcf28aeddd7cb585b6b0a651631
4
- data.tar.gz: 21e698cddf5834b086a90db3724882df09c37ed03476e0c60afcc8882e1cf2db
3
+ metadata.gz: f3baafd9472b824734be5f808a2618e87120ba9adb87ef3a5fa6e09685d0a12a
4
+ data.tar.gz: d54f510d068f819de8aae695e76abe3fe7f45642cc7f5574d44ccf1d39509856
5
5
  SHA512:
6
- metadata.gz: ce4f85bf76dbc96ceea24b63a4af130c6a623046e91507bafaf126743d67e1b461ae3f07b4224835a4cbf1ed8355622cde0f899164f1098f1014f2b1391d34c1
7
- data.tar.gz: 98910ccbd262ef3de617eba52f4ddca7ba5dbf93c63591f4085dbc859530ebd77b4a59c699f4a586194cbf1660750ffde6cb3c0a10aad692398ff0ed05634363
6
+ metadata.gz: df87112be9e15dcb0a9754d6baa12c520567a335c78cd582201ed76aaa190dd5c0e49faba2f4c18e3d7a7dff43cf2e9fca0fe79fc63f0fc9561e1849e207e8c6
7
+ data.tar.gz: '03887359a7e34df5f4ec3c8583cc93cb0bb7663941b1db3a7643923259f0cde76a4ea14e24ed404e579c54437c8b91bba25162f134189ba60ea8b45ac540bb67'
data/bin/replr CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require_relative '../lib/replr'
4
- Replr.new.start
4
+ Replr::REPLMaker.new.start
@@ -1,142 +1,2 @@
1
- require 'tmpdir'
2
- require 'open3'
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'
@@ -1,4 +1,4 @@
1
- FROM ruby:2.3.1-alpine
1
+ FROM ruby:%%VERSION%%alpine
2
2
  ADD Gemfile /app/
3
3
  RUN apk --update add --virtual build-dependencies ruby-dev build-base && \
4
4
  gem install bundler --no-ri --no-rdoc && \
@@ -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
@@ -0,0 +1,3 @@
1
+ #:nodoc:
2
+ module Replr
3
+ end
@@ -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
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.2.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-24 00:00:00.000000000 Z
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