From 579f18736ac8b2689aee01257050a688f315ede9 Mon Sep 17 00:00:00 2001 From: Sebastian Morr Date: Tue, 8 Sep 2020 16:00:18 +0200 Subject: [PATCH] Introduce Shell class with a `cd` method and a `run` method game.exec is now the only point in the code that calls OS.execute. shell.run is the only point that refers to /bin/sh. --- game.gd | 70 ++++++++++++--------------------------------------- main.gd | 53 ++++++++++++++------------------------ project.godot | 16 ++++++++++-- repository.gd | 15 +++++------ shell.gd | 35 ++++++++++++++++++++++++++ terminal.gd | 6 ++--- 6 files changed, 93 insertions(+), 102 deletions(-) create mode 100644 shell.gd diff --git a/game.gd b/game.gd index 58a6d24..ce3a99e 100644 --- a/game.gd +++ b/game.gd @@ -1,65 +1,27 @@ extends Node -var _file = "user://savegame.json" -var state = {} +var cwd func _ready(): - load_state() - -func _initial_state(): - return {} - -func save_state() -> bool: - var savegame = File.new() - - savegame.open(_file, File.WRITE) - savegame.store_line(to_json(state)) - savegame.close() - return true - -func load_state() -> bool: - var savegame = File.new() - if not savegame.file_exists(_file): - return false - - savegame.open(_file, File.READ) - - state = _initial_state() - var new_state = parse_json(savegame.get_line()) - for key in new_state: - state[key] = new_state[key] - savegame.close() - return true + cwd = exec("pwd", [], true) -# Run a simple command given as a string, blocking, using execute. -func run(command): - print("run: "+command) - var output = [] - OS.execute(command, [], true, output, true) - # Remove trailing newline. - return output[0].substr(0,len(output[0])-1) - -func sh(command, wd="/tmp/"): - print("sh in "+wd+": "+command) - var cwd = game.run("pwd") +# Run a simple command with arguments, blocking, using OS.execute. +func exec(command, args=[], remote_trailing_newline=false): + var debug = false + if debug: + print("game.exec: %s [%s]" % [command, PoolStringArray(args).join(", ")]) + var output = [] + OS.execute(command, args, true, output, true) + output = output[0] - var hacky_command = command - hacky_command = "cd '"+wd+"';"+hacky_command - hacky_command = "export EDITOR=fake-editor;"+hacky_command - hacky_command = "export PATH=\"$PATH\":"+cwd+"/scripts;"+hacky_command - OS.execute("/bin/sh", ["-c", hacky_command], true, output, true) - return output[0] + if debug: + print(output) -func script(filename, wd="/tmp/"): - print("sh script in "+wd+": "+filename) - var cwd = game.run("pwd") - var output = [] - - var hacky_command = "/bin/sh " + filename - hacky_command = "cd '"+wd+"';"+hacky_command - OS.execute("/bin/sh", ["-c", hacky_command], true, output, true) - return output[0] + if remote_trailing_newline: + output = output.substr(0,len(output)-1) + + return output func read_file(path): print("read "+path) diff --git a/main.gd b/main.gd index 15d97bd..5639b87 100644 --- a/main.gd +++ b/main.gd @@ -46,9 +46,8 @@ func load_level(id): var levels = list_levels() var level = levels[id] - var cwd = game.run("pwd") var tmp_prefix = "/tmp/" - var level_prefix = cwd + "/levels/" + var level_prefix = game.cwd + "/levels/" var goal_repository_path = tmp_prefix+"goal/" var active_repository_path = tmp_prefix+"active/" @@ -58,8 +57,19 @@ func load_level(id): var description = game.read_file(level_prefix+level+"/description") $LevelDescription.bbcode_text = description - OS.execute("rm", ["-r", active_repository_path], true) - OS.execute("rm", ["-r", goal_repository_path], true) + # Danger zone! We're actually destroying stuff here. + # 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() + 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() + + game.exec("rm", ["-r", active_repository_path]) + game.exec("rm", ["-r", goal_repository_path]) + construct_repo(goal_script, goal_repository_path) construct_repo(active_script, active_repository_path) @@ -67,41 +77,16 @@ func load_level(id): active_repository.path = active_repository_path func construct_repo(script, path): - print(path) - game.sh("mkdir "+path) - game.sh("git init", path) - print(game.script(script, path)) - #var commands = game.read_file(script).split("\n") - #print(commands) - #for command in commands: - # print(command) - # game.sh(command, path) + var shell = Shell.new() + shell.run("mkdir " + path) + shell.cd(path) + shell.run("git init") + print(shell.run("source "+script)) func _process(delta): if server.is_connection_available(): client_connection = server.take_connection() read_commit_message() -# if true or get_global_mouse_position().x < get_viewport_rect().size.x*0.7: -# if Input.is_action_just_pressed("click"): -# var mindist = 9999999 -# for o in objects.values(): -# var d = o.position.distance_to(get_global_mouse_position()) -# if d < mindist: -# mindist = d -# dragged = o -# if Input.is_action_just_released("click"): -# dragged = null -# if dragged: -# dragged.position = get_global_mouse_position() - -#func run(command): -# var a = command.split(" ") -# var cmd = a[0] -# a.remove(0) -# var output = [] -# OS.execute(cmd, a, true, output, true) -# print(command) -# print(output[0]) func read_commit_message(): $CommitMessage.show() diff --git a/project.godot b/project.godot index 130fd77..6c84ce5 100644 --- a/project.godot +++ b/project.godot @@ -8,9 +8,14 @@ config_version=4 -_global_script_classes=[ ] +_global_script_classes=[ { +"base": "Node", +"class": "Shell", +"language": "GDScript", +"path": "res://shell.gd" +} ] _global_script_class_icons={ - +"Shell": "" } [application] @@ -60,3 +65,10 @@ click={ "events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) ] } + +[network] + +limits/debugger_stdout/max_chars_per_second=100000 +limits/debugger_stdout/max_messages_per_frame=1000 +limits/debugger_stdout/max_errors_per_second=1000 +limits/debugger_stdout/max_warnings_per_second=1000 diff --git a/repository.gd b/repository.gd index 7d6d9d7..cd53c9f 100644 --- a/repository.gd +++ b/repository.gd @@ -2,10 +2,12 @@ extends Container export var label: String setget set_label export var path: String setget set_path, get_path -var objects = {} var node = preload("res://node.tscn") +var shell = Shell.new() +var objects = {} + func _ready(): pass @@ -21,6 +23,7 @@ func update_everything(): func set_path(new_path): path = new_path + shell.cd(new_path) for o in objects.values(): o.queue_free() objects = {} @@ -109,13 +112,7 @@ func apply_forces(): o.position -= dir*f func git(args, splitlines = false): - var output = [] - var a = args.split(" ") - #print ("Running: ", a) - a.insert(0, "-C") - a.insert(1, path) - OS.execute("git", a, true, output, true) - var o = output[0] + var o = shell.run("git " + args) if splitlines: o = o.split("\n") @@ -150,7 +147,7 @@ func update_head(): add_child(n2) func all_objects(): - return git("cat-file --batch-check=%(objectname) --batch-all-objects", true) + return git("cat-file --batch-check='%(objectname)' --batch-all-objects", true) func object_type(id): return git("cat-file -t "+id) diff --git a/shell.gd b/shell.gd new file mode 100644 index 0000000..0485b76 --- /dev/null +++ b/shell.gd @@ -0,0 +1,35 @@ +extends Node +class_name Shell + +var _cwd + +func _init(): + pass + +func cd(dir): + _cwd = dir + +# Run a shell command given as a string. Run this if you're interested in the +# output of the command. +func run(command): + var debug = true + + if debug: + print("$ %s" % command) + + var env = {} + env["EDITOR"] = game.cwd+"/scripts/fake-editor" + env["TEST"] = "hi" + + var hacky_command = "" + for variable in env: + hacky_command += "export %s='%s';" % [variable, env[variable]] + hacky_command += "cd '%s';" % _cwd + hacky_command += command + + var output = game.exec("/bin/sh", ["-c", hacky_command]) + + if debug: + print(output) + + return output diff --git a/terminal.gd b/terminal.gd index 04766dc..0be1343 100644 --- a/terminal.gd +++ b/terminal.gd @@ -7,6 +7,7 @@ var history_position = 0 onready var input = $Control/Input onready var output = $Control/Output +onready var repo = $"../Repositories/ActiveRepository" func _input(event): if history.size() > 0: @@ -32,9 +33,8 @@ func send_command(command): thread.start(self, "run_command_in_a_thread", command) func run_command_in_a_thread(command): - var o = game.sh(command, "/tmp/active") + var o = repo.shell.run(command) input.text = "" output.text = output.text + "$ " + command + "\n" + o - #output.scroll_vertical = 999999 - $"../Repositories/ActiveRepository".update_everything() # FIXME + repo.update_everything() # FIXME