Move exec, crash, and file IO to "helpers" autoload node

This commit is contained in:
Sebastian Morr 2020-09-29 14:53:00 +02:00
parent 685af0ede6
commit 44214d2fdf
8 changed files with 77 additions and 74 deletions

54
game.gd
View file

@ -2,7 +2,6 @@ extends Node
var tmp_prefix = _tmp_prefix()
var global_shell
var debug_file_io = false
var fake_editor
var _file = "user://savegame.json"
@ -38,41 +37,16 @@ func load_state() -> bool:
state[key] = new_state[key]
savegame.close()
return true
func copy_file_to_game_env(filename):
# Copy fake-editor to tmp directory (because the original might be in a .pck file).
var file_outside = tmp_prefix + filename
var file_inside = "/tmp/"+filename
var content = game.read_file("res://scripts/"+filename, "")
if content.empty():
push_error(filename + " could not be read.")
write_file(file_outside, content)
var content = helpers.read_file("res://scripts/"+filename)
helpers.write_file(file_outside, content)
global_shell.run("chmod u+x " + file_inside)
return file_inside
func read_file(path, fallback_string):
if debug_file_io:
print("reading " + path)
var file = File.new()
var open_status = file.open(path, File.READ)
if open_status == OK:
var content = file.get_as_text()
file.close()
return content
else:
return fallback_string
func write_file(path, content):
if debug_file_io:
print("writing " + path)
var file = File.new()
file.open(path, File.WRITE)
file.store_string(content)
file.close()
return true
func _tmp_prefix():
var os = OS.get_name()
if os == "X11":
@ -80,26 +54,6 @@ func _tmp_prefix():
elif os == "Windows":
# For some reason, this command outputs a space in the end? We remove it.
# Also, Godot's default is to use forward slashes for everything.
return exec("echo", ["%TEMP%"]).replacen("\\", "/").replace(" \n", "/")
return helpers.exec("echo", ["%TEMP%"]).replacen("\\", "/").replace(" \n", "/")
else:
push_error("Unsupported OS")
get_tree().quit()
# Run a simple command with arguments, blocking, using OS.execute.
func exec(command, args=[]):
var debug = false
if debug:
print("exec: %s [%s]" % [command, PoolStringArray(args).join(", ")])
var output = []
var exit_code = OS.execute(command, args, true, output, true)
output = output[0]
if exit_code != 0:
push_error("OS.execute failed: %s [%s] Output: %s" % [command, PoolStringArray(args).join(", "), output])
if debug:
print(output)
return output
helpers.crash("Unsupported OS: %s" % os)

54
helpers.gd Normal file
View file

@ -0,0 +1,54 @@
extends Node
var debug_file_io = false
# Crash the game and display the error message.
func crash(message):
push_error(message)
print("Fatal error: " + message)
get_tree().quit()
# Run a simple command with arguments, blocking, using OS.execute.
func exec(command, args=[], crash_on_fail=true):
var debug = false
if debug:
print("exec: %s [%s]" % [command, PoolStringArray(args).join(", ")])
var output = []
var exit_code = OS.execute(command, args, true, output, true)
output = output[0]
if exit_code != 0 and crash_on_fail:
helpers.crash("OS.execute failed: %s [%s] Output: %s" % [command, PoolStringArray(args).join(", "), output])
if debug:
print(output)
return output
# 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):
if debug_file_io:
print("reading " + path)
var file = File.new()
var open_status = file.open(path, File.READ)
if open_status == OK:
var content = file.get_as_text()
file.close()
return content
else:
if fallback_string != null:
return fallback_string
else:
helpers.crash("File %s could not be read, and has no fallback" % path)
func write_file(path, content):
if debug_file_io:
print("writing " + path)
var file = File.new()
file.open(path, File.WRITE)
file.store_string(content)
file.close()
return true

24
main.gd
View file

@ -67,13 +67,13 @@ func list_levels():
var final_level_sequence = []
var level_sequence = Array(game.read_file("res://levels/%s/sequence" % chapter, "").split("\n"))
var level_sequence = Array(helpers.read_file("res://levels/%s/sequence" % chapter, "").split("\n"))
for level in level_sequence:
if level == "":
continue
if not levels.has(level):
push_error("Level '%s' is specified in the sequence, but could not be found" % level)
helpers.crash("Level '%s' is specified in the sequence, but could not be found" % level)
levels.erase(level)
final_level_sequence.push_back(level)
@ -105,7 +105,7 @@ func load_level(id):
var active_script = level_prefix+level+"/start"
var description_file = level_prefix+level+"/description"
var description = game.read_file(description_file, "no description")
var description = helpers.read_file(description_file, "(no description)")
# Surround all lines indented with four spaces with [code] tags.
var monospace_regex = RegEx.new()
@ -114,7 +114,7 @@ func load_level(id):
level_description.bbcode_text = description
var congrats_file = level_prefix+level+"/congrats"
var congrats = game.read_file(congrats_file, "Good job, you solved the level!\n\nFeel free to try a few more things or click 'Next Level'.")
var congrats = helpers.read_file(congrats_file, "Good job, you solved the level!\n\nFeel free to try a few more things or click 'Next Level'.")
level_congrats.bbcode_text = congrats
level_name.text = level
@ -123,18 +123,16 @@ func load_level(id):
# Make sure that active_repository is in a temporary directory.
var expected_prefix = "/tmp"
if active_repository_path.substr(0,4) != expected_prefix:
push_error("Refusing to delete a directory that does not start with %s" % expected_prefix)
get_tree().quit()
helpers.crash("Refusing to delete directory %s that does not start with %s" % [active_repository_path, expected_prefix])
if goal_repository_path.substr(0,4) != expected_prefix:
push_error("Refusing to delete a directory that does not start with %s" % expected_prefix)
get_tree().quit()
helpers.crash("Refusing to delete directory %s that does not start with %s" % [goal_repository_path, expected_prefix])
# Danger zone!
game.global_shell.run("rm -rf '%s'" % active_repository_path)
game.global_shell.run("rm -rf '%s'" % goal_repository_path)
var goal_script_content = game.read_file(goal_script, "")
var active_script_content = game.read_file(active_script, "")
var goal_script_content = helpers.read_file(goal_script, "")
var active_script_content = helpers.read_file(active_script, "")
construct_repo(active_script_content +"\n"+ goal_script_content, goal_repository_path)
construct_repo(active_script_content, active_repository_path)
@ -143,8 +141,8 @@ func load_level(id):
var win_script = level_prefix+level+"/win"
var win_script_target = game.tmp_prefix+"/win"
var win_script_content = game.read_file(win_script, "exit 1\n")
game.write_file(win_script_target, win_script_content)
var win_script_content = helpers.read_file(win_script, "exit 1\n")
helpers.write_file(win_script_target, win_script_content)
terminal.clear()
@ -171,7 +169,7 @@ func construct_repo(script_content, path):
var script_path_outside = game.tmp_prefix+"/git-hydra-script"
var script_path = "/tmp/git-hydra-script"
game.write_file(script_path_outside, script_content)
helpers.write_file(script_path_outside, script_content)
game.global_shell.run("mkdir " + path)
game.global_shell.cd(path)

View file

@ -26,6 +26,7 @@ run/main_scene="res://main.tscn"
[autoload]
game="*res://game.gd"
helpers="*res://helpers.gd"
[display]

View file

@ -49,7 +49,7 @@ func run(command):
#
hacky_command = '"\''+hacky_command.replace("'", "'\"'\"'")+'\'"'
var output = game.exec(_shell_binary(), ["-c", hacky_command])
var output = helpers.exec(_shell_binary(), ["-c", hacky_command], false)
if debug:
print(output)
@ -64,8 +64,7 @@ func _shell_binary():
elif os == "Windows":
return "dependencies\\windows\\git\\bin\\bash.exe"
else:
push_error("Unsupported OS")
get_tree().quit()
helpers.crash("Unsupported OS: %s" % os)
var _t
func run_async(command):

View file

@ -18,7 +18,7 @@ func _process(_delta):
if _s.is_connection_available():
if _connected:
_c.disconnect_from_host()
push_error("Dropping active connection")
helpers.crash("Dropping active connection")
_c = _s.take_connection()
_connected = true
print("connected!")
@ -38,4 +38,4 @@ func send(text):
text += "\n"
_c.put_data(text.to_utf8())
else:
push_error("Trying to send data on closed connection")
helpers.crash("Trying to send data on closed connection")

View file

@ -29,7 +29,7 @@ func _ready():
var error = $TextEditor.connect("hide", self, "editor_closed")
if error != OK:
push_error("Could not connect TextEditor's hide signal")
helpers.crash("Could not connect TextEditor's hide signal")
input.grab_focus()
var all_git_commands = repository.shell.run("git help -a | grep \"^ \\+[a-z-]\\+ \" -o")

View file

@ -22,10 +22,7 @@ func open(filename):
path = filename
var fixme_path = game.tmp_prefix+"/active/"
var content = game.read_file(fixme_path+filename, "[ERROR_FAKE_EDITOR]")
if content == "[ERROR_FAKE_EDITOR]":
push_error("Specified file could not be read.")
get_tree().quit()
var content = helpers.read_file(fixme_path+filename)
text = content
show()
@ -33,7 +30,7 @@ func open(filename):
func save():
var fixme_path = game.tmp_prefix+"/active/"
game.write_file(fixme_path+path, text)
helpers.write_file(fixme_path+path, text)
close()
func close():