diff --git a/level.gd b/level.gd index 1082132..2f5ea24 100644 --- a/level.gd +++ b/level.gd @@ -4,12 +4,7 @@ class_name Level var slug var description var congrats -var start_commands -var goal_commands -var win_commands - -var _goal_repository_path = game.tmp_prefix_inside+"/repos/goal/" -var _active_repository_path = game.tmp_prefix_inside+"/repos/active/" +var repos = {} # The path is an outer path. func load(path): @@ -21,41 +16,91 @@ func load(path): # This is an old-style level. description = helpers.read_file(path+"/description", "(no description)") congrats = helpers.read_file(path+"/congrats", "Good job, you solved the level!\n\nFeel free to try a few more things or click 'Next Level'.") - start_commands = helpers.read_file(path+"/start", "") - goal_commands = helpers.read_file(path+"/goal", "") - win_commands = helpers.read_file(path+"/win", "exit 1\n") + + var yours = LevelRepo.new() + yours.setup_commands = helpers.read_file(path+"/start", "") + #goal_commands = helpers.read_file(path+"/goal", "") + yours.win_commands = helpers.read_file(path+"/win", "") + + repos["yours"] = yours elif dir.file_exists(path): # This is a new-style level. var config = helpers.parse(path) description = config.get("description", "(no description)") congrats = config.get("congrats", "Good job, you solved the level!\n\nFeel free to try a few more things or click 'Next Level'.") - start_commands = config.get("setup", "") - goal_commands = "" - win_commands = config.get("win", "exit 1\n") + + var keys = config.keys() + var repo_setups = [] + for k in keys: + if k.begins_with("setup"): + repo_setups.push_back(k) + var repo_wins = [] + for k in keys: + if k.begins_with("win"): + repo_wins.push_back(k) + + for k in repo_setups: + var repo + if " " in k: + repo = Array(k.split(" "))[1] + else: + repo = "yours" + if not repos.has(repo): + repos[repo] = LevelRepo.new() + repos[repo].setup_commands = config[k] + + for k in repo_wins: + var repo + if " " in k: + repo = Array(k.split(" "))[1] + else: + repo = "yours" + repos[repo].win_commands = config[k] else: helpers.crash("Level %s does not exist." % path) + for repo in repos: + repos[repo].path = game.tmp_prefix_inside+"repos/%s/" % repo + repos[repo].slug = repo + # Surround all lines indented with four spaces with [code] tags. var monospace_regex = RegEx.new() monospace_regex.compile("\n (.*)\n") description = monospace_regex.sub(description, "\n [code]$1[/code]\n", true) func construct(): - _construct_repo(start_commands +"\n"+ goal_commands, _goal_repository_path) - _construct_repo(start_commands, _active_repository_path) - -func _construct_repo(script_content, path): - # We're actually destroying stuff here. - # Make sure that active_repository is in a temporary directory. - helpers.careful_delete(path) - - game.global_shell.run("mkdir " + path) - game.global_shell.cd(path) - game.global_shell.run("git init") - game.global_shell.run("git symbolic-ref HEAD refs/heads/main") - game.global_shell.run(script_content) + for r in repos: + var repo = repos[r] + # We're actually destroying stuff here. + # Make sure that active_repository is in a temporary directory. + helpers.careful_delete(repo.path) + + game.global_shell.run("mkdir " + 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") + + # 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]) + + # Allow receiving a push of the checked-out branch. + game.global_shell.run("git config receive.denyCurrentBranch ignore") + + for r in repos: + var repo = repos[r] + game.global_shell.cd(repo.path) + game.global_shell.run(repo.setup_commands) func check_win(): - game.global_shell.cd(_active_repository_path) - return game.global_shell.run("function win { %s; }; win 2>/dev/null >/dev/null && echo yes || echo no" % win_commands) == "yes\n" + var won = true + for r in repos: + var repo = repos[r] + if repo.win_commands != "": + game.global_shell.cd(repo.path) + if not game.global_shell.run("function win { %s\n}; win 2>/dev/null >/dev/null && echo yes || echo no" % repo.win_commands) == "yes\n": + won = false + return won diff --git a/levels/top-down/pull-merge-push b/levels/top-down/pull-merge-push new file mode 100644 index 0000000..1e64ffc --- /dev/null +++ b/levels/top-down/pull-merge-push @@ -0,0 +1,32 @@ +title = A pull and a conflict +author = blinry + +[description] + +You want to push your new commits to the server, but someone has already pushed their own changes. + +In this situation, you need to pull first! Try that here - you'll have to resolve a merge conflict. Push your changes afterwards. + +[congrats] + +Good job! Here's some additional info: banana! + +[setup yours] + +echo fu > file +git add . +git commit -m "Initial commit" +git push + +echo fi > file +git commit -a -m "Fi is good" + +[setup origin] + +echo fa > file +git add . +git commit -a -m "Fa is good" + +[win origin] + +test "$(git rev-parse HEAD^1^)" = "$(git rev-parse HEAD^2^)" diff --git a/main.gd b/main.gd index 56c2c51..433d90e 100644 --- a/main.gd +++ b/main.gd @@ -8,8 +8,8 @@ var current_level onready var terminal = $Columns/RightSide/Terminal onready var input = terminal.input onready var output = terminal.output -onready var goal_repository = $Columns/Repositories/GoalRepository -onready var active_repository = $Columns/Repositories/ActiveRepository +onready var repositories_node = $Columns/Repositories +var repositories = {} onready var level_select = $Columns/RightSide/TopStuff/Menu/LevelSelect onready var chapter_select = $Columns/RightSide/TopStuff/Menu/ChapterSelect onready var next_level_button = $Columns/RightSide/TopStuff/Menu/NextLevelButton @@ -57,17 +57,26 @@ func load_level(level_id): AudioServer.set_bus_mute(AudioServer.get_bus_index("Master"), true) levels.chapters[current_chapter].levels[current_level].construct() - - var goal_repository_path = game.tmp_prefix_inside+"/repos/goal/" - var active_repository_path = game.tmp_prefix_inside+"/repos/active/" var level = levels.chapters[current_chapter].levels[current_level] level_description.bbcode_text = level.description level_congrats.bbcode_text = level.congrats level_name.text = level.slug - goal_repository.path = goal_repository_path - active_repository.path = active_repository_path + for r in repositories_node.get_children(): + r.queue_free() + repositories = {} + + for r in level.repos: + var repo = level.repos[r] + var new_repo = preload("res://repository.tscn").instance() + new_repo.path = repo.path + new_repo.label = repo.slug + new_repo.size_flags_horizontal = SIZE_EXPAND_FILL + repositories_node.add_child(new_repo) + repositories[r] = new_repo + + terminal.repository = repositories[repositories.keys()[0]] terminal.clear() # Unmute the audio after a while, so that player can hear pop sounds for @@ -81,6 +90,7 @@ func load_level(level_id): # FIXME: Need to clean these up when switching levels somehow. func reload_level(): + levels.reload() load_level(current_level) func load_next_level(): @@ -104,6 +114,10 @@ func repopulate_chapters(): for c in levels.chapters: chapter_select.add_item(c.slug) -func check_win_condition(): +func update_repos(): + for r in repositories: + var repo = repositories[r] + repo.update_everything() + if levels.chapters[current_chapter].levels[current_level].check_win(): show_win_status() diff --git a/main.tscn b/main.tscn index 6a4af7b..d39bb03 100644 --- a/main.tscn +++ b/main.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=10 format=2] +[gd_scene load_steps=9 format=2] [ext_resource path="res://terminal.tscn" type="PackedScene" id=1] [ext_resource path="res://main.gd" type="Script" id=2] -[ext_resource path="res://repository.tscn" type="PackedScene" id=3] [ext_resource path="res://styles/alert_button.tres" type="StyleBox" id=4] [ext_resource path="res://tcp_server.tscn" type="PackedScene" id=5] [ext_resource path="res://styles/theme.tres" type="Theme" id=6] @@ -65,26 +64,6 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="GoalRepository" parent="Columns/Repositories" instance=ExtResource( 3 )] -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_right = 633.0 -margin_bottom = 1070.0 -size_flags_horizontal = 3 -size_flags_vertical = 3 -label = "Goal" -file_browser_active = false - -[node name="ActiveRepository" parent="Columns/Repositories" instance=ExtResource( 3 )] -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_left = 633.0 -margin_right = 1267.0 -margin_bottom = 1070.0 -size_flags_horizontal = 3 -size_flags_vertical = 3 -label = "Your repository" - [node name="RightSide" type="VSplitContainer" parent="Columns"] margin_left = 1279.0 margin_right = 1910.0 @@ -192,7 +171,6 @@ margin_top = 541.0 margin_right = 631.0 margin_bottom = 1070.0 size_flags_vertical = 3 -repository_path = NodePath("../../../Columns/Repositories/ActiveRepository") [node name="Test" type="Node2D" parent="."] visible = false @@ -213,4 +191,5 @@ __meta__ = { [connection signal="button_down" from="Columns/RightSide/TopStuff/Menu/LevelSelect" to="." method="repopulate_levels"] [connection signal="pressed" from="Columns/RightSide/TopStuff/Menu/ReloadButton" to="." method="reload_level"] [connection signal="pressed" from="Columns/RightSide/TopStuff/Menu/NextLevelButton" to="." method="load_next_level"] +[connection signal="command_done" from="Columns/RightSide/Terminal" to="." method="update_repos"] [connection signal="text_entered" from="Test/LineEdit" to="Test" method="send"] diff --git a/project.godot b/project.godot index 94b0c63..ef74dca 100644 --- a/project.godot +++ b/project.godot @@ -20,6 +20,11 @@ _global_script_classes=[ { "path": "res://level.gd" }, { "base": "Node", +"class": "LevelRepo", +"language": "GDScript", +"path": "res://level_repo.gd" +}, { +"base": "Node", "class": "Shell", "language": "GDScript", "path": "res://shell.gd" @@ -27,6 +32,7 @@ _global_script_classes=[ { _global_script_class_icons={ "Chapter": "", "Level": "", +"LevelRepo": "", "Shell": "" } diff --git a/repository.gd b/repository.gd index 2a5626d..30e99fe 100644 --- a/repository.gd +++ b/repository.gd @@ -27,6 +27,9 @@ func _ready(): set_file_browser_active(file_browser_active) set_simplified_view(simplified_view) set_editable_path(editable_path) + set_path(path) + + update_everything() func _process(_delta): nodes.rect_pivot_offset = nodes.rect_size / 2 @@ -44,7 +47,8 @@ func there_is_a_git(): return shell.run("test -d .git && echo yes || echo no") == "yes\n" func update_everything(): - file_browser.update() + if file_browser: + file_browser.update() if there_is_a_git(): update_head() update_refs() @@ -52,19 +56,22 @@ func update_everything(): update_objects() remove_gone_stuff() else: - index.text = "" + if index: + index.text = "" for o in objects: objects[o].queue_free() objects = {} func set_path(new_path): path = new_path - path_node.text = path + if path_node: + path_node.text = path shell.cd(new_path) for o in objects.values(): o.queue_free() objects = {} - update_everything() + if is_inside_tree(): + update_everything() func get_path(): return path diff --git a/repository.tscn b/repository.tscn index bff0b4d..362786c 100644 --- a/repository.tscn +++ b/repository.tscn @@ -25,7 +25,7 @@ __meta__ = { [node name="RepoVis" type="Control" parent="Rows"] margin_right = 1920.0 -margin_bottom = 994.0 +margin_bottom = 925.0 mouse_filter = 1 size_flags_vertical = 3 __meta__ = { @@ -110,11 +110,11 @@ __meta__ = { [node name="FileBrowser" parent="Rows" instance=ExtResource( 4 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 1006.0 +margin_top = 937.0 margin_right = 1920.0 margin_bottom = 1080.0 size_flags_vertical = 3 -size_flags_stretch_ratio = 0.08 +size_flags_stretch_ratio = 0.16 [connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] [connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] [connection signal="pressed" from="Rows/RepoVis/Button" to="." method="update_everything"] diff --git a/sandbox.tscn b/sandbox.tscn index f8df3bf..910bb5b 100644 --- a/sandbox.tscn +++ b/sandbox.tscn @@ -49,4 +49,3 @@ margin_left = 961.0 margin_right = 1910.0 margin_bottom = 1070.0 size_flags_horizontal = 3 -repository_path = NodePath("../../Columns/Repository") diff --git a/terminal.gd b/terminal.gd index 77c3130..d2d4d07 100644 --- a/terminal.gd +++ b/terminal.gd @@ -1,5 +1,7 @@ extends Control +signal command_done + var thread var history_position = 0 @@ -9,8 +11,8 @@ var git_commands_help = [] onready var input = $Rows/InputLine/Input onready var output = $Rows/TopHalf/Output onready var completions = $Rows/TopHalf/Completions -export(NodePath) var repository_path -onready var repository = get_node(repository_path) +#export(NodePath) var repository_path +var repository onready var command_dropdown = $Rows/InputLine/CommandDropdown onready var main = get_tree().get_root().get_node("Main") @@ -32,13 +34,13 @@ func _ready(): 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") + var all_git_commands = game.global_shell.run("git help -a | grep \"^ \\+[a-z-]\\+ \" -o") git_commands = Array(all_git_commands.split("\n")) for i in range(git_commands.size()): git_commands[i] = git_commands[i].strip_edges(true, true) git_commands.pop_back() - var all_git_commands_help = repository.shell.run("git help -a | grep \" [A-Z].\\+$\" -o") + var all_git_commands_help = game.global_shell.run("git help -a | grep \" [A-Z].\\+$\" -o") git_commands_help = Array(all_git_commands_help.split("\n")) for i in range(git_commands_help.size()): git_commands_help[i] = git_commands_help[i].strip_edges(true, true) @@ -95,18 +97,17 @@ func send_command_async(command): func run_command_in_a_thread(command): var o = repository.shell.run(command, false) - if main: - main.check_win_condition() - input.text = "" input.editable = true - if o.length() <= 200: + if o.length() <= 1000: output.text = output.text + "$ " + command + "\n" + o else: $Pager/Text.text = o $Pager.popup() - repository.update_everything() + + emit_signal("command_done") + #repository.update_everything() func receive_output(text): output.text += text diff --git a/terminal.tscn b/terminal.tscn index 58dc53d..dbba3f6 100644 --- a/terminal.tscn +++ b/terminal.tscn @@ -110,7 +110,6 @@ syntax_highlighting = false [node name="TCPServer" parent="." instance=ExtResource( 3 )] [node name="Pager" type="WindowDialog" parent="."] -visible = true anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 18.0 diff --git a/text_editor.gd b/text_editor.gd index 144de9b..f3344b0 100644 --- a/text_editor.gd +++ b/text_editor.gd @@ -15,13 +15,13 @@ func _process(_delta): _client_connection = _server.take_connection() var length = _client_connection.get_u8() var filename = _client_connection.get_string(length) - filename = filename.replace("%srepos/active/" % game.tmp_prefix_inside, "") + filename = filename.replace("%srepos/" % game.tmp_prefix_inside, "") open(filename) func open(filename): path = filename - var fixme_path = game.tmp_prefix_outside+"/repos/active/" + var fixme_path = game.tmp_prefix_outside+"repos/" var content = helpers.read_file(fixme_path+filename) text = content @@ -29,7 +29,7 @@ func open(filename): grab_focus() func save(): - var fixme_path = game.tmp_prefix_outside+"/repos/active/" + var fixme_path = game.tmp_prefix_outside+"repos/" helpers.write_file(fixme_path+path, text) close()