mirror of
https://github.com/git-learning-game/oh-my-git.git
synced 2024-12-22 20:32:38 +01:00
Start working on a better shell mechanism for Windows
It uses a Perl script to keep a bash session open, which attaches to a port the game keeps open. This avoids having to start a new Git bash for each command, improving the execution speed by a factor of 3-4.
This commit is contained in:
parent
2a82b617be
commit
53c249d059
8 changed files with 145 additions and 15 deletions
|
@ -20,6 +20,8 @@ func _ready():
|
|||
get_tree().set_auto_accept_quit(false)
|
||||
else:
|
||||
game.toggle_music()
|
||||
|
||||
start_remote_shell()
|
||||
|
||||
global_shell = Shell.new()
|
||||
|
||||
|
@ -33,7 +35,26 @@ func _ready():
|
|||
copy_script_to_game_env("hint")
|
||||
|
||||
load_state()
|
||||
|
||||
|
||||
func start_remote_shell():
|
||||
var user_dir = ProjectSettings.globalize_path("user://")
|
||||
var script_content = helpers.read_file("res://scripts/net-test")
|
||||
var target_filename = user_dir + "net-test"
|
||||
var target_file = File.new()
|
||||
target_file.open(target_filename, File.WRITE)
|
||||
target_file.store_string(script_content)
|
||||
target_file.close()
|
||||
helpers.exec_async(_perl_executable(), [target_filename])
|
||||
|
||||
func _perl_executable():
|
||||
if OS.get_name() == "Windows":
|
||||
return "dependencies/windows/git/usr/bin/perl.exe"
|
||||
else:
|
||||
return "perl"
|
||||
|
||||
func shell_received(text):
|
||||
print(text)
|
||||
|
||||
func _notification(what):
|
||||
if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
|
||||
#get_tree().quit() # default behavio
|
||||
|
@ -99,3 +120,7 @@ func toggle_music():
|
|||
music.volume_db -= 100
|
||||
else:
|
||||
music.volume_db += 100
|
||||
|
||||
|
||||
func shell_test(command):
|
||||
return $ShellServer.send(command)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://scenes/game.gd" type="Script" id=1]
|
||||
[ext_resource path="res://music/gigantic-greasy-giraffe.ogg" type="AudioStream" id=2]
|
||||
[ext_resource path="res://scenes/tcp_server_shell.tscn" type="PackedScene" id=3]
|
||||
|
||||
[node name="Node" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
|
@ -10,3 +11,6 @@ script = ExtResource( 1 )
|
|||
stream = ExtResource( 2 )
|
||||
volume_db = -15.0
|
||||
autoplay = true
|
||||
|
||||
[node name="ShellServer" parent="." instance=ExtResource( 3 )]
|
||||
port = 6666
|
||||
|
|
|
@ -35,6 +35,9 @@ func exec(command, args=[], crash_on_fail=true):
|
|||
|
||||
return {"output": output, "exit_code": exit_code}
|
||||
|
||||
func exec_async(command, args=[]):
|
||||
OS.execute(command, args, false)
|
||||
|
||||
# Return the contents of a file. If no fallback_string is provided, crash when
|
||||
# the file doesn't exist.
|
||||
func read_file(path, fallback_string=null):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
extends Node
|
||||
|
||||
signal data_received(string)
|
||||
signal new_connection
|
||||
|
||||
export var port: int
|
||||
|
||||
|
@ -21,21 +22,24 @@ func _process(_delta):
|
|||
helpers.crash("Dropping active connection")
|
||||
_c = _s.take_connection()
|
||||
_connected = true
|
||||
emit_signal("new_connection")
|
||||
print("connected!")
|
||||
|
||||
if _connected:
|
||||
if _c.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
_connected = false
|
||||
print("disconnected")
|
||||
var available = _c.get_available_bytes()
|
||||
while available > 0:
|
||||
var data = _c.get_utf8_string(available)
|
||||
emit_signal("data_received", data)
|
||||
available = _c.get_available_bytes()
|
||||
# var available = _c.get_available_bytes()
|
||||
# while available > 0:
|
||||
# var data = _c.get_utf8_string(available)
|
||||
# emit_signal("data_received", data)
|
||||
# available = _c.get_available_bytes()
|
||||
|
||||
func send(text):
|
||||
if _connected:
|
||||
text += "\n"
|
||||
_c.put_data(text.to_utf8())
|
||||
_c.put_utf8_string(text)
|
||||
var response = _c.get_utf8_string()
|
||||
emit_signal("data_received", response)
|
||||
else:
|
||||
helpers.crash("Trying to send data on closed connection")
|
||||
|
|
50
scenes/tcp_server_shell.gd
Normal file
50
scenes/tcp_server_shell.gd
Normal file
|
@ -0,0 +1,50 @@
|
|||
extends Node
|
||||
|
||||
signal data_received(string)
|
||||
signal new_connection
|
||||
|
||||
export var port: int
|
||||
|
||||
var _s = TCP_Server.new()
|
||||
var _c
|
||||
var _connected = false
|
||||
|
||||
func _ready():
|
||||
start()
|
||||
|
||||
func start():
|
||||
_s.listen(port)
|
||||
|
||||
func _process(_delta):
|
||||
if _s.is_connection_available():
|
||||
if _connected:
|
||||
_c.disconnect_from_host()
|
||||
helpers.crash("Dropping active connection")
|
||||
_c = _s.take_connection()
|
||||
_connected = true
|
||||
emit_signal("new_connection")
|
||||
print("connected!")
|
||||
|
||||
if _connected:
|
||||
if _c.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
_connected = false
|
||||
print("disconnected")
|
||||
# var available = _c.get_available_bytes()
|
||||
# while available > 0:
|
||||
# var data = _c.get_utf8_string(available)
|
||||
# emit_signal("data_received", data)
|
||||
# available = _c.get_available_bytes()
|
||||
|
||||
func send(text):
|
||||
if _connected:
|
||||
_c.put_utf8_string(text)
|
||||
var response = _c.get_utf8_string()
|
||||
var exit_code = _c.get_u32()
|
||||
|
||||
var shell_command = ShellCommand.new()
|
||||
shell_command.command = text
|
||||
shell_command.output = response
|
||||
shell_command.exit_code = exit_code
|
||||
return shell_command
|
||||
else:
|
||||
helpers.crash("Trying to send data on closed connection")
|
6
scenes/tcp_server_shell.tscn
Normal file
6
scenes/tcp_server_shell.tscn
Normal file
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://scenes/tcp_server_shell.gd" type="Script" id=1]
|
||||
|
||||
[node name="TCPServerShell" type="Node"]
|
||||
script = ExtResource( 1 )
|
|
@ -85,8 +85,9 @@ func send_command(command):
|
|||
editor_regex.compile("^(vim?|gedit|emacs|kate|nano|code) ")
|
||||
command = editor_regex.sub(command, "fake-editor ")
|
||||
|
||||
var cmd = repository.shell.run_async(command, false)
|
||||
yield(cmd, "done")
|
||||
# var cmd = repository.shell.run_async(command, false)
|
||||
# yield(cmd, "done")
|
||||
var cmd = game.shell_test(command)
|
||||
call_deferred("command_done", cmd)
|
||||
|
||||
func command_done(cmd):
|
||||
|
|
|
@ -1,24 +1,61 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use IPC::Open2;
|
||||
use IO::Socket;
|
||||
|
||||
my $pid = open2(my $out, my $in, 'bash');
|
||||
|
||||
$socket = IO::Socket::INET->new(PeerAddr => "127.0.0.1",
|
||||
PeerPort => 6666,
|
||||
Proto => "tcp",
|
||||
Type => SOCK_STREAM);
|
||||
|
||||
$s = "Hey äöü!";
|
||||
|
||||
my $send_length = pack("L", length($s));
|
||||
$socket->send($send_length);
|
||||
$socket->send($s);
|
||||
#$s = "Hey äöü!";
|
||||
#
|
||||
#my $send_length = pack("L", length($s));
|
||||
#$socket->send($send_length);
|
||||
#$socket->send($s);
|
||||
|
||||
while(true) {
|
||||
#STDOUT->flush();
|
||||
my $len;
|
||||
$socket->recv($len, 4);
|
||||
my $actual_len = unpack("L", $len);
|
||||
if ($actual_len == 0) {
|
||||
print("not connected");
|
||||
exit;
|
||||
}
|
||||
print("still connected");
|
||||
my $s2;
|
||||
$socket->recv($s2, ord($len));
|
||||
|
||||
print($s2);
|
||||
STDOUT->flush();
|
||||
|
||||
#$s = `bash -c '$s2' 2>&1`;
|
||||
|
||||
$s = "";
|
||||
$command = $s2 . "\necho MAGIC\n";
|
||||
print $in $command;
|
||||
|
||||
inner_while: while (true) {
|
||||
$line = <$out>;
|
||||
if ($line eq "MAGIC\n") {
|
||||
STDOUT->flush();
|
||||
last inner_while;
|
||||
}
|
||||
$s = $s . $line;
|
||||
}
|
||||
print "got complete output";
|
||||
print $s;
|
||||
|
||||
print length($s);
|
||||
STDOUT->flush();
|
||||
my $send_length = pack("L", length($s));
|
||||
$socket->send($send_length);
|
||||
$socket->send($s);
|
||||
|
||||
my $exit_code = pack("L", 0);
|
||||
$socket->send($exit_code);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue