Add interactive mode
This commit is contained in:
		| @@ -1,17 +1,21 @@ | ||||
| #!/usr/bin/env ruby | ||||
|  | ||||
| require "base64" | ||||
| require "io/console" | ||||
| require "optparse" | ||||
| require "socket" | ||||
|  | ||||
| usage_output = "USAGE:\n    github-fast-env SCRIPT_PATH [options]" | ||||
|  | ||||
| $options = {:verbose => false} | ||||
| $options = {:verbose => false, :interactive => false} | ||||
| OptionParser.new do |options| | ||||
| 	options.banner = usage_output | ||||
| 	options.on("-v", "--verbose", "Show verbose output") do | ||||
| 		$options[:verbose] = true | ||||
| 	end | ||||
| 	options.on("-i", "--interactive", "Run an interactive session using a pseudoterminal") do | ||||
| 		$options[:interactive] = true | ||||
| 	end | ||||
| end.parse! | ||||
|  | ||||
| if not ARGV or ARGV.empty? | ||||
| @@ -34,9 +38,13 @@ control_socket_path = "/tmp/github-fast-envd.sock" | ||||
|  | ||||
| $control_socket = UNIXSocket.new(control_socket_path) | ||||
|  | ||||
| $original_stdin = $stdin.dup | ||||
| $original_stdout = $stdout.dup | ||||
| $origianl_stderr = $stderr.dup | ||||
|  | ||||
| def log(level, message) | ||||
| 	if level == "error" or $options[:verbose] | ||||
| 		$stderr.puts "[github-fast-env] #{level}: #{message}" | ||||
| 		$origianl_stderr.puts "[github-fast-env] #{level}: #{message}" | ||||
| 	end | ||||
| end | ||||
|  | ||||
| @@ -89,7 +97,12 @@ end | ||||
| log "info", "connected to control socket" | ||||
|  | ||||
| encoded_script_path = Base64.encode64(script_path).delete("\n") | ||||
| $control_socket.puts "new v1 named-pipes #{encoded_script_path}" | ||||
|  | ||||
| if $options[:interactive] | ||||
| 	$control_socket.puts "new v1 pseudoterminal #{encoded_script_path}" | ||||
| else | ||||
| 	$control_socket.puts "new v1 named-pipes #{encoded_script_path}" | ||||
| end | ||||
|  | ||||
| pipes = {"stdin" => nil, "stdout" => nil, "stderr" => nil} | ||||
|  | ||||
| @@ -115,10 +128,27 @@ while true | ||||
| 		pipes["stderr"] = File::open("#{pipe_base_path}.stderr", "r") | ||||
| 		pipes["stderr"].sync = true | ||||
|  | ||||
| 		read_ios = [$control_socket, $stdin, pipes["stdout"], pipes["stderr"]] | ||||
|  | ||||
| 		log "info", "connected via named pipes" | ||||
| 	elsif command == "pseudoterminal" | ||||
| 		log "error", "not yet implemented" | ||||
| 		exit 1 | ||||
| 		if arguments.empty? | ||||
| 			log "error", "malformed response" | ||||
| 			exit 1 | ||||
| 		end | ||||
|  | ||||
| 		pseudoterminal_path = Base64.decode64(arguments[0]) | ||||
|  | ||||
| 		log "info", "connecting to pseudoterminal at #{pseudoterminal_path}" | ||||
|  | ||||
| 		pseudoterminal_io = File::open(pseudoterminal_path, File::RDWR | File::NOCTTY) | ||||
|  | ||||
| 		pipes["stdin"] = pseudoterminal_io | ||||
| 		pipes["stdout"] = pseudoterminal_io | ||||
|  | ||||
| 		read_ios = [$control_socket, $stdin, pipes["stdout"]] | ||||
|  | ||||
| 		log "info", "connected via pseudoterminal" | ||||
| 	else | ||||
| 		log "error", "malformed response" | ||||
| 		exit 1 | ||||
| @@ -128,8 +158,6 @@ end | ||||
| log "info", "ready" | ||||
| $control_socket.puts "ready" | ||||
|  | ||||
| read_ios = [$control_socket, $stdin, pipes["stdout"], pipes["stderr"]] | ||||
|  | ||||
| exit_code = "unknown" | ||||
|  | ||||
| while read_ios.include?($control_socket) or read_ios.include?(pipes["stdout"]) or read_ios.include?(pipes["stderr"]) | ||||
| @@ -165,7 +193,7 @@ while read_ios.include?($control_socket) or read_ios.include?(pipes["stdout"]) o | ||||
| 				log "warn", "received input from unknown stream" | ||||
| 			end | ||||
| 		rescue EOFError | ||||
| 			log "trace", "closing stream" | ||||
| 			log "trace", "closing stream #{ready_read_io}" | ||||
| 			ready_read_io.close | ||||
| 		end | ||||
| 	end | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #!/usr/bin/env ruby | ||||
|  | ||||
| require "base64" | ||||
| require "io/console" | ||||
| require "socket" | ||||
|  | ||||
| #require "/data/github/current/config/environment" | ||||
| @@ -116,6 +117,35 @@ def set_up_named_pipes(control_socket, connection_id) | ||||
| 	$stderr.reopen(stderr) | ||||
| end | ||||
|  | ||||
| def set_up_pseudoterminal(control_socket) | ||||
| 	require "pty" | ||||
|  | ||||
| 	master, client = PTY.open | ||||
| 	master.raw! | ||||
|  | ||||
| 	File.chmod 0600, client.path | ||||
|  | ||||
| 	client_path = Base64.encode64(client.path).delete("\n") | ||||
| 	client.close | ||||
|  | ||||
| 	control_socket.puts "pseudoterminal #{client_path}" | ||||
|  | ||||
| 	$stderr.puts "  set up pseudoterminal" | ||||
|  | ||||
| 	control_socket.puts "ready" | ||||
|  | ||||
| 	response = control_socket.readline.strip | ||||
|  | ||||
| 	if response != "ready" | ||||
| 		raise ClientError.new "invalid command" | ||||
| 		Kernel.exit! | ||||
| 	end | ||||
|  | ||||
| 	$stdin.reopen(master) | ||||
| 	$stdout.reopen(master) | ||||
| 	$stderr.reopen(master) | ||||
| end | ||||
|  | ||||
| while true | ||||
| 	control_socket = control_server.accept | ||||
| 	$stderr.puts "- new connection" | ||||
| @@ -157,7 +187,7 @@ while true | ||||
| 			if mode == "named-pipes" | ||||
| 				set_up_named_pipes(control_socket, connection_id) | ||||
| 			else | ||||
| 				raise ClientError.new "not yet implemented" | ||||
| 				set_up_pseudoterminal(control_socket) | ||||
| 			end | ||||
|  | ||||
| 			original_stderr.puts "  executing script " + script_path | ||||
|   | ||||
		Reference in New Issue
	
	Block a user