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 tmp_prefix = _tmp_prefix()
var global_shell var global_shell
var debug_file_io = false
var fake_editor var fake_editor
var _file = "user://savegame.json" var _file = "user://savegame.json"
@ -38,41 +37,16 @@ func load_state() -> bool:
state[key] = new_state[key] state[key] = new_state[key]
savegame.close() savegame.close()
return true return true
func copy_file_to_game_env(filename): func copy_file_to_game_env(filename):
# Copy fake-editor to tmp directory (because the original might be in a .pck file). # Copy fake-editor to tmp directory (because the original might be in a .pck file).
var file_outside = tmp_prefix + filename var file_outside = tmp_prefix + filename
var file_inside = "/tmp/"+filename var file_inside = "/tmp/"+filename
var content = game.read_file("res://scripts/"+filename, "") var content = helpers.read_file("res://scripts/"+filename)
if content.empty(): helpers.write_file(file_outside, content)
push_error(filename + " could not be read.")
write_file(file_outside, content)
global_shell.run("chmod u+x " + file_inside) global_shell.run("chmod u+x " + file_inside)
return 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(): func _tmp_prefix():
var os = OS.get_name() var os = OS.get_name()
if os == "X11": if os == "X11":
@ -80,26 +54,6 @@ func _tmp_prefix():
elif os == "Windows": elif os == "Windows":
# For some reason, this command outputs a space in the end? We remove it. # 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. # 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: else:
push_error("Unsupported OS") helpers.crash("Unsupported OS: %s" % 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

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 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: for level in level_sequence:
if level == "": if level == "":
continue continue
if not levels.has(level): 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) levels.erase(level)
final_level_sequence.push_back(level) final_level_sequence.push_back(level)
@ -105,7 +105,7 @@ func load_level(id):
var active_script = level_prefix+level+"/start" var active_script = level_prefix+level+"/start"
var description_file = level_prefix+level+"/description" 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. # Surround all lines indented with four spaces with [code] tags.
var monospace_regex = RegEx.new() var monospace_regex = RegEx.new()
@ -114,7 +114,7 @@ func load_level(id):
level_description.bbcode_text = description level_description.bbcode_text = description
var congrats_file = level_prefix+level+"/congrats" 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_congrats.bbcode_text = congrats
level_name.text = level level_name.text = level
@ -123,18 +123,16 @@ func load_level(id):
# Make sure that active_repository is in a temporary directory. # Make sure that active_repository is in a temporary directory.
var expected_prefix = "/tmp" var expected_prefix = "/tmp"
if active_repository_path.substr(0,4) != expected_prefix: if active_repository_path.substr(0,4) != expected_prefix:
push_error("Refusing to delete a directory that does not start with %s" % expected_prefix) helpers.crash("Refusing to delete directory %s that does not start with %s" % [active_repository_path, expected_prefix])
get_tree().quit()
if goal_repository_path.substr(0,4) != 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) helpers.crash("Refusing to delete directory %s that does not start with %s" % [goal_repository_path, expected_prefix])
get_tree().quit()
# Danger zone! # Danger zone!
game.global_shell.run("rm -rf '%s'" % active_repository_path) game.global_shell.run("rm -rf '%s'" % active_repository_path)
game.global_shell.run("rm -rf '%s'" % goal_repository_path) game.global_shell.run("rm -rf '%s'" % goal_repository_path)
var goal_script_content = game.read_file(goal_script, "") var goal_script_content = helpers.read_file(goal_script, "")
var active_script_content = game.read_file(active_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 +"\n"+ goal_script_content, goal_repository_path)
construct_repo(active_script_content, active_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 = level_prefix+level+"/win"
var win_script_target = game.tmp_prefix+"/win" var win_script_target = game.tmp_prefix+"/win"
var win_script_content = game.read_file(win_script, "exit 1\n") var win_script_content = helpers.read_file(win_script, "exit 1\n")
game.write_file(win_script_target, win_script_content) helpers.write_file(win_script_target, win_script_content)
terminal.clear() 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_outside = game.tmp_prefix+"/git-hydra-script"
var script_path = "/tmp/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.run("mkdir " + path)
game.global_shell.cd(path) game.global_shell.cd(path)

View file

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

View file

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

View file

@ -18,7 +18,7 @@ func _process(_delta):
if _s.is_connection_available(): if _s.is_connection_available():
if _connected: if _connected:
_c.disconnect_from_host() _c.disconnect_from_host()
push_error("Dropping active connection") helpers.crash("Dropping active connection")
_c = _s.take_connection() _c = _s.take_connection()
_connected = true _connected = true
print("connected!") print("connected!")
@ -38,4 +38,4 @@ func send(text):
text += "\n" text += "\n"
_c.put_data(text.to_utf8()) _c.put_data(text.to_utf8())
else: 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") var error = $TextEditor.connect("hide", self, "editor_closed")
if error != OK: if error != OK:
push_error("Could not connect TextEditor's hide signal") helpers.crash("Could not connect TextEditor's hide signal")
input.grab_focus() input.grab_focus()
var all_git_commands = repository.shell.run("git help -a | grep \"^ \\+[a-z-]\\+ \" -o") 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 path = filename
var fixme_path = game.tmp_prefix+"/active/" var fixme_path = game.tmp_prefix+"/active/"
var content = game.read_file(fixme_path+filename, "[ERROR_FAKE_EDITOR]") var content = helpers.read_file(fixme_path+filename)
if content == "[ERROR_FAKE_EDITOR]":
push_error("Specified file could not be read.")
get_tree().quit()
text = content text = content
show() show()
@ -33,7 +30,7 @@ func open(filename):
func save(): func save():
var fixme_path = game.tmp_prefix+"/active/" var fixme_path = game.tmp_prefix+"/active/"
game.write_file(fixme_path+path, text) helpers.write_file(fixme_path+path, text)
close() close()
func close(): func close():