From 8362b9d9b2a14c6080156462beed9712feafad05 Mon Sep 17 00:00:00 2001 From: blinry Date: Thu, 7 Sep 2023 14:45:52 +0200 Subject: [PATCH] Async everywhere... --- scenes/file_browser.gd | 33 +++++---------------- scenes/file_browser_item.gd | 12 ++++---- scenes/game.gd | 30 +++++++------------ scenes/level.gd | 20 ++++++------- scenes/main.gd | 26 ++++++++--------- scenes/repository.gd | 58 ++++++++++++++++++------------------- scenes/sandbox.gd | 10 +++---- scenes/shell.gd | 18 ++++-------- scenes/terminal.gd | 12 ++------ 9 files changed, 89 insertions(+), 130 deletions(-) diff --git a/scenes/file_browser.gd b/scenes/file_browser.gd index dcf9ce0..dcd14d9 100644 --- a/scenes/file_browser.gd +++ b/scenes/file_browser.gd @@ -57,11 +57,11 @@ func update(): if repository.there_is_a_git_cache: # Files in the HEAD commit. - head_files = Array(repository.shell.run("git ls-tree --name-only -r HEAD 2> /dev/null || true").split("\n")) + head_files = Array((await repository.shell.run("git ls-tree --name-only -r HEAD 2> /dev/null || true")).split("\n")) # The last entry is an empty string, remove it. head_files.pop_back() # Files in the index. - index_files = Array(repository.shell.run("git ls-files -s | cut -f2 | uniq").split("\n")) + index_files = Array((await repository.shell.run("git ls-files -s | cut -f2 | uniq")).split("\n")) # The last entry is an empty string, remove it. index_files.pop_back() @@ -90,8 +90,8 @@ func update(): if shell: var deleted_files = [] - if shell.run("test -d super.git && echo yes || echo no") == "yes\n": - deleted_files = Array(shell.run("git status -s | grep '^.D' | sed 's/^...//'").split("\n")) + if (await shell.run("test -d super.git && echo yes || echo no")) == "yes\n": + deleted_files = Array((await shell.run("git status -s | grep '^.D' | sed 's/^...//'")).split("\n")) deleted_files.pop_back() #var is_visible = false @@ -122,7 +122,7 @@ func update(): #var is_visible = false if repository and repository.there_is_a_git_cache: - var deleted_files = Array(repository.shell.run("git status -s | grep '^D' | sed 's/^...//'").split("\n")) + var deleted_files = Array((await repository.shell.run("git status -s | grep '^D' | sed 's/^...//'")).split("\n")) # The last entries are empty strings, remove them. for file_path in files: @@ -135,25 +135,6 @@ func update(): # is_visible = true #visible = is_visible -#func get_file_status(file_path, the_shell, idx): -# var file_status = the_shell.run("git status -s '%s'" % file_path) -# if file_status.length()>0: -# match file_status[idx]: -# "D": -# return FileBrowserItem.IconStatus.REMOVED -# "M": -# return FileBrowserItem.IconStatus.EDIT -# "U": -# return FileBrowserItem.IconStatus.CONFLICT -# " ": -# return FileBrowserItem.IconStatus.NONE -# "A": -# return FileBrowserItem.IconStatus.NEW -# "?": -# return FileBrowserItem.IconStatus.UNTRACKED -# else: -# return FileBrowserItem.IconStatus.NONE - func item_clicked(item): if not item.get_node("VBoxContainer/Control/WD").visible: return @@ -162,11 +143,11 @@ func item_clicked(item): FileBrowserMode.WORKING_DIRECTORY: text_edit.text = helpers.read_file(repository.shell._cwd + item.label) FileBrowserMode.COMMIT: - text_edit.text = commit.repository.shell.run("git show %s:\"%s\"" % [commit.id, item.label]) + text_edit.text = await commit.repository.shell.run("git show %s:\"%s\"" % [commit.id, item.label]) FileBrowserMode.INDEX: if item.status == item.IconStatus.CONFLICT: return - text_edit.text = repository.shell.run("git show :\"%s\"" % [item.label]) + text_edit.text = await repository.shell.run("git show :\"%s\"" % [item.label]) open_file = item.label text_edit.show() diff --git a/scenes/file_browser_item.gd b/scenes/file_browser_item.gd index b0bc1f6..8c880ed 100644 --- a/scenes/file_browser_item.gd +++ b/scenes/file_browser_item.gd @@ -13,13 +13,13 @@ var repository func _ready(): _set_label(label) #$PopupMenu.add_item("Delete file", 0) - var exists_in_wd = repository.shell.run("test -f '%s' && echo yes || echo no" % label) == "yes\n" - var exists_in_index = repository.shell.run("git ls-files --error-unmatch '%s' &>/dev/null && echo yes || echo no" % label) == "yes\n" - var exists_in_head = repository.shell.run("git cat-file -e HEAD:'%s' &>/dev/null && echo yes || echo no" % label) == "yes\n" + var exists_in_wd = (await repository.shell.run("test -f '%s' && echo yes || echo no" % label)) == "yes\n" + var exists_in_index = (await repository.shell.run("git ls-files --error-unmatch '%s' &>/dev/null && echo yes || echo no" % label)) == "yes\n" + var exists_in_head = (await repository.shell.run("git cat-file -e HEAD:'%s' &>/dev/null && echo yes || echo no" % label)) == "yes\n" - var wd_hash = repository.shell.run("git hash-object '%s' 2>/dev/null || true" % label) - var index_hash = repository.shell.run("git ls-files -s '%s' | cut -f2 -d' '" % label) - var head_hash = repository.shell.run("git ls-tree HEAD '%s' | cut -f1 | cut -f3 -d' '" % label) + var wd_hash = await repository.shell.run("git hash-object '%s' 2>/dev/null || true" % label) + var index_hash = await repository.shell.run("git ls-files -s '%s' | cut -f2 -d' '" % label) + var head_hash = await repository.shell.run("git ls-tree HEAD '%s' | cut -f1 | cut -f3 -d' '" % label) var conflict = Array(index_hash.split("\n")).size() > 2 diff --git a/scenes/game.gd b/scenes/game.gd index fe9dc2f..86576b0 100644 --- a/scenes/game.gd +++ b/scenes/game.gd @@ -21,7 +21,7 @@ func get_tmp_prefix(): if OS.get_name() == "Web": return "/tmp/" else: - OS.get_user_data_dir() + "/tmp/" + return OS.get_user_data_dir() + "/tmp/" func _ready(): mutex = Mutex.new() @@ -34,25 +34,17 @@ func _ready(): if OS.get_name() == "Windows": start_remote_shell() - global_shell = new_shell() - -# var cmd = global_shell.run("echo hi") -# print(cmd) -# cmd = global_shell.run("seq 1 10") -# print(cmd) -# cmd = global_shell.run("ls") -# print(cmd) -# helpers.crash(":)") + global_shell = await new_shell() if false: - if global_shell.run("command -v git &>/dev/null && echo yes || echo no") == "no\n": + if (await global_shell.run("command -v git &>/dev/null && echo yes || echo no")) == "no\n": game.skipped_title = true get_tree().change_scene_to_file("res://scenes/no_git.tscn") else: - create_file_in_game_env(".gitconfig", helpers.read_file("res://scripts/gitconfig")) + await create_file_in_game_env(".gitconfig", helpers.read_file("res://scripts/gitconfig")) - copy_script_to_game_env("fake-editor") - copy_script_to_game_env("hint") + await copy_script_to_game_env("fake-editor") + await copy_script_to_game_env("hint") func start_remote_shell(): var user_dir = ProjectSettings.globalize_path("user://") @@ -86,8 +78,8 @@ func _notification(what): func copy_script_to_game_env(name): - create_file_in_game_env(name, helpers.read_file("res://scripts/%s" % name)) - global_shell.run("chmod u+x '%s'" % (tmp_prefix + name)) + await create_file_in_game_env(name, helpers.read_file("res://scripts/%s" % name)) + await global_shell.run("chmod u+x '%s'" % (tmp_prefix + name)) func _initial_state(): return {"history": [], "solved_levels": [], "received_hints": [], "cli_badge": [], "played_cards": []} @@ -116,9 +108,9 @@ func load_state(): # filename is relative to the tmp directory! func create_file_in_game_env(filename, content): - global_shell.cd(tmp_prefix) + await global_shell.cd(tmp_prefix) # Quoted HERE doc doesn't do any substitutions inside. - global_shell.run("cat > '%s' <<'HEREHEREHERE'\n%s\nHEREHEREHERE" % [filename, content]) + await global_shell.run("cat > '%s' <<'HEREHEREHERE'\n%s\nHEREHEREHERE" % [filename, content]) func notify(text, target=null, hint_slug=null): if hint_slug: @@ -167,4 +159,4 @@ func new_shell(): if OS.get_name() == "Windows": return BetterShell.new() else: - return Shell.new() + return await Shell.new() diff --git a/scenes/level.gd b/scenes/level.gd index d2a18e2..05bb0cf 100644 --- a/scenes/level.gd +++ b/scenes/level.gd @@ -115,32 +115,32 @@ func construct(): # Make sure that active_repository is in a temporary directory. helpers.careful_delete(repo.path) - game.global_shell.run("mkdir '%s'" % repo.path) - game.global_shell.cd(repo.path) - game.global_shell.run("git init") - game.global_shell.run("git symbolic-ref HEAD refs/heads/main") + await game.global_shell.run("mkdir '%s'" % repo.path) + await game.global_shell.cd(repo.path) + await game.global_shell.run("git init") + await game.global_shell.run("git symbolic-ref HEAD refs/heads/main") # Add other repos as remotes. for r2 in repos: if r == r2: continue - game.global_shell.run("git remote add %s '%s'" % [r2, repos[r2].path]) + await game.global_shell.run("git remote add %s '%s'" % [r2, repos[r2].path]) for r in repos: var repo = repos[r] - game.global_shell.cd(repo.path) - game.global_shell.run(repo.setup_commands) + await game.global_shell.cd(repo.path) + await game.global_shell.run(repo.setup_commands) func check_win(): var win_states = {} for r in repos: var repo = repos[r] - game.global_shell.cd(repo.path) + await game.global_shell.cd(repo.path) if repo.action_commands.length() > 0: - game.global_shell.run("function actions { %s\n}; actions 2>/dev/null >/dev/null || true" % repo.action_commands) + await game.global_shell.run("function actions { %s\n}; actions 2>/dev/null >/dev/null || true" % repo.action_commands) if repo.win_conditions.size() > 0: for description in repo.win_conditions: var commands = repo.win_conditions[description] - var won = game.global_shell.run("function win { %s\n}; win 2>/dev/null >/dev/null && echo yes || echo no" % commands) == "yes\n" + var won = (await game.global_shell.run("function win { %s\n}; win 2>/dev/null >/dev/null && echo yes || echo no" % commands)) == "yes\n" win_states[description] = won return win_states diff --git a/scenes/main.gd b/scenes/main.gd index 96c4203..c39b02b 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -15,12 +15,12 @@ var repositories = {} @onready var file_browser = $Rows/Columns/RightSide/FileBrowser @onready var goals = $Rows/Columns/RightSide/LevelInfo/LevelPanel/Goals -var _hint_server -var _hint_client_connection +#var _hint_server +#var _hint_client_connection func _ready(): - _hint_server = TCPServer.new() - _hint_server.listen(1235) + #_hint_server = TCPServer.new() + #_hint_server.listen(1235) var args = helpers.parse_args() @@ -45,11 +45,11 @@ func _ready(): input.grab_focus() func _process(delta): - if _hint_server.is_connection_available(): - _hint_client_connection = _hint_server.take_connection() - var length = _hint_client_connection.get_u32() - var message = _hint_client_connection.get_string(length) - game.notify(message) +# if _hint_server.is_connection_available(): +# _hint_client_connection = _hint_server.take_connection() +# var length = _hint_client_connection.get_u32() +# var message = _hint_client_connection.get_string(length) +# game.notify(message) # if game.used_cards: # $Menu/CLIBadge.impossible = true @@ -110,7 +110,7 @@ func load_level(level_id): terminal.clear() terminal.find_child("TextEditor").close() - update_repos() + await update_repos() # Unmute the audio after a while, so that player can hear pop sounds for # nodes they create. @@ -205,13 +205,13 @@ func show_win_status(win_states): # chapter_select.select(game.current_chapter) func update_repos(): - var win_states = levels.chapters[game.current_chapter].levels[game.current_level].check_win() + var win_states = await levels.chapters[game.current_chapter].levels[game.current_level].check_win() show_win_status(win_states) for r in repositories: var repo = repositories[r] - repo.update_everything() - file_browser.update() + await repo.update_everything() + await file_browser.update() input.grab_focus() diff --git a/scenes/repository.gd b/scenes/repository.gd index a351f04..8b8cbd5 100644 --- a/scenes/repository.gd +++ b/scenes/repository.gd @@ -14,7 +14,7 @@ var type = "remote" var node = preload("res://scenes/node.tscn") -var shell = game.new_shell() +var shell = await game.new_shell() var objects = {} var mouse_inside = false var has_been_layouted = false @@ -52,18 +52,18 @@ func there_is_a_git(): return await shell.run("test -d .git && echo yes || echo no") == "yes\n" func update_everything(): - there_is_a_git_cache = there_is_a_git() + there_is_a_git_cache = await there_is_a_git() if there_is_a_git_cache: - update_head() - update_refs() - update_objects() - remove_gone_stuff() + await update_head() + await update_refs() + await update_objects() + await remove_gone_stuff() else: for o in objects: objects[o].queue_free() objects = {} if not has_been_layouted: - update_node_positions() + await update_node_positions() has_been_layouted = true func set_path(new_path): @@ -96,14 +96,14 @@ func random_position(): return Vector2(randf_range(0, size.x), randf_range(0, size.y)) func update_objects(): - all_objects_cache = all_objects() + all_objects_cache = await all_objects() # Create new objects, if necessary. for o in all_objects_cache: if objects.has(o): continue - var type = object_type(o) + var type = await object_type(o) if simplified_view: if type == "tree" or type == "blob": @@ -111,20 +111,20 @@ func update_objects(): var n = node.instantiate() n.id = o - n.type = object_type(o) - n.content = object_content(o) + n.type = await object_type(o) + n.content = await object_content(o) n.repository = self match type: "blob": pass "tree": - n.children = tree_children(o) + n.children = await tree_children(o) n.content = n.content.replacen("\t", " ") "commit": var c = {} #c[commit_tree(o)] = "" - for p in commit_parents(o): + for p in await commit_parents(o): c[p] = "" n.children = c @@ -132,7 +132,7 @@ func update_objects(): # if _commit_count >= 3 and not simplified_view: # set_simplified_view(true) "tag": - n.children = tag_target(o) + n.children = await tag_target(o) n.position = find_position(n) nodes.add_child(n) @@ -164,7 +164,7 @@ func update_node_positions(): objects["HEAD"].position = Vector2(target.position.x ,target.position.y - 100) func update_refs(): - all_refs_cache = all_refs() + all_refs_cache = await all_refs() for r in all_refs_cache: if not objects.has(r): var n = node.instantiate() @@ -173,11 +173,11 @@ func update_refs(): n.content = "" n.repository = self objects[r] = n - n.children = {ref_target(r): ""} + n.children = {(await ref_target(r)): ""} n.position = find_position(n) nodes.add_child(n) var n = objects[r] - n.children = {ref_target(r): ""} + n.children = {(await ref_target(r)): ""} func apply_forces(): for o in objects.values(): @@ -238,25 +238,25 @@ func update_head(): objects["HEAD"] = n nodes.add_child(n) var n = objects["HEAD"] - n.children = {ref_target("HEAD"): ""} + n.children = {(await ref_target("HEAD")): ""} func all_objects(): #var obj = git("cat-file --batch-check='%(objectname)' --batch-all-objects", true) - var obj = git("cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep '\\(tag\\|commit\\)$' | cut -f1 -d' '", true) + var obj = await git("cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep '\\(tag\\|commit\\)$' | cut -f1 -d' '", true) var dict = {} for o in obj: dict[o] = "" return dict func object_type(id): - return git("cat-file -t "+id) + return await git("cat-file -t "+id) func object_content(id): #return git("cat-file -p "+id) - return git("show -s --format=%B "+id).strip_edges() + return (await git("show -s --format=%B "+id)).strip_edges() func tree_children(id): - var children = git("cat-file -p "+id, true) + var children = await git("cat-file -p "+id, true) var ids = {} for c in children: var a = c.split(" ") @@ -264,7 +264,7 @@ func tree_children(id): return ids func commit_tree(id): - var c = git("cat-file -p "+id, true) + var c = await git("cat-file -p "+id, true) for cc in c: var ccc = cc.split(" ", 2) match ccc[0]: @@ -274,7 +274,7 @@ func commit_tree(id): func commit_parents(id): var parents = [] - var c = git("cat-file -p "+id, true) + var c = await git("cat-file -p "+id, true) for cc in c: var ccc = cc.split(" ", 2) match ccc[0]: @@ -283,13 +283,13 @@ func commit_parents(id): return parents func tag_target(id): - var c = git("rev-parse %s^{}" % id) + var c = await git("rev-parse %s^{}" % id) return {c: ""} func all_refs(): var refs = {} # If there are no refs, show-ref will have exit code 1. We don't care. - for line in git("show-ref || true", true): + for line in await git("show-ref || true", true): line = line.split(" ") var _id = line[0] var name = line[1] @@ -298,13 +298,13 @@ func all_refs(): func ref_target(ref): # Test whether this is a symbolic ref. - var ret = git("symbolic-ref -q "+ref+" || true") + var ret = await git("symbolic-ref -q "+ref+" || true") # If it's not, it's probably a regular ref. if ret == "": if ref == "HEAD": - ret = git("show-ref --head "+ref).split(" ")[0] + ret = (await git("show-ref --head "+ref)).split(" ")[0] else: - ret = git("show-ref "+ref).split(" ")[0] + ret = (await git("show-ref "+ref)).split(" ")[0] return ret func set_simplified_view(simplify): diff --git a/scenes/sandbox.gd b/scenes/sandbox.gd index 864ec6d..f3ef3bc 100644 --- a/scenes/sandbox.gd +++ b/scenes/sandbox.gd @@ -16,12 +16,12 @@ func _ready(): if path == null: path = game.tmp_prefix+"/repos/sandbox/" - helpers.careful_delete(path) + await helpers.careful_delete(path) - game.global_shell.run("mkdir '%s'" % path) - game.global_shell.cd(path) - game.global_shell.run("git init") - game.global_shell.run("git symbolic-ref HEAD refs/heads/main") + await game.global_shell.run("mkdir '%s'" % path) + await game.global_shell.cd(path) + await game.global_shell.run("git init") + await game.global_shell.run("git symbolic-ref HEAD refs/heads/main") $Columns/Repository.path = path diff --git a/scenes/shell.gd b/scenes/shell.gd index ba67503..b6f7d2e 100644 --- a/scenes/shell.gd +++ b/scenes/shell.gd @@ -11,7 +11,7 @@ var web_shell = JavaScriptBridge.get_interface("web_shell") func _init(): # Create required directories and move into the tmp directory. _cwd = "/tmp" - run("mkdir -p '%s/repos'" % game.tmp_prefix) + await run("mkdir -p '%s/repos'" % game.tmp_prefix) _cwd = game.tmp_prefix func cd(dir): @@ -20,26 +20,17 @@ func cd(dir): # Run a shell command given as a string. Run this if you're interested in the # output of the command. func run(command, crash_on_fail=true): + print("run " + command) var shell_command = ShellCommand.new() shell_command.command = command shell_command.crash_on_fail = crash_on_fail run_async_thread(shell_command) await shell_command.done + print("output in run (" +command+ "): " + shell_command.output) exit_code = shell_command.exit_code return shell_command.output -func run_async(command, crash_on_fail=true): - var shell_command = ShellCommand.new() - shell_command.command = command - shell_command.crash_on_fail = crash_on_fail - - var t = Thread.new() - shell_command.thread = t - t.start(Callable(self, "run_async_thread").bind(shell_command)) - - return shell_command - func run_async_web(command, crash_on_fail=true): var shell_command = ShellCommand.new() shell_command.command = command @@ -48,6 +39,7 @@ func run_async_web(command, crash_on_fail=true): return shell_command func run_async_thread(shell_command): + print("in async thread " + shell_command.command) var debug = false var command = shell_command.command @@ -103,7 +95,7 @@ func run_async_thread(shell_command): #print(hacky_command) shell_command.js_callback = JavaScriptBridge.create_callback(Callable(shell_command, "callback")) - web_shell.run_in_vm(command).then(shell_command.js_callback) + web_shell.run_in_vm(hacky_command).then(shell_command.js_callback) else: helpers.crash("Unimplemented OS: %s" % _os) diff --git a/scenes/terminal.gd b/scenes/terminal.gd index c423fce..8be80a9 100644 --- a/scenes/terminal.gd +++ b/scenes/terminal.gd @@ -14,7 +14,7 @@ var git_commands_help = [] var repository @onready var main = get_tree().get_root().get_node("Main") -var shell = Shell.new() +var shell = await Shell.new() var premade_commands = [ 'git commit --allow-empty -m "empty"', @@ -90,16 +90,10 @@ func send_command(command): shell.cd(repository.path) + print("running " + command) var cmd = shell.run_async_web(command, false) await cmd.done call_deferred("command_done", cmd) - -# var output = shell.run(command, false) -# var shell_command = ShellCommand.new() -# shell_command.exit_code = 0 -# shell_command.output = output -# shell_command.command = command -# command_done(shell_command) func command_done(cmd): if cmd.exit_code == 0: @@ -131,7 +125,7 @@ func editor_closed(): input.grab_focus() func regenerate_completions_menu(new_text): - var comp = generate_completions(new_text) + var comp = await generate_completions(new_text) completions.clear()