Async everywhere...

This commit is contained in:
blinry 2023-09-07 14:45:52 +02:00
parent 19fcad2920
commit 8362b9d9b2
9 changed files with 89 additions and 130 deletions

View file

@ -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()

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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()

View file

@ -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):

View file

@ -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

View file

@ -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)

View file

@ -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()