hook up downloading releases and templates to component
This commit is contained in:
parent
94c256b608
commit
db5700b62d
@ -21,22 +21,55 @@ var threads: Array[Thread]
|
|||||||
signal releases_fetched(releases: Releases)
|
signal releases_fetched(releases: Releases)
|
||||||
signal version_downloaded(version: String)
|
signal version_downloaded(version: String)
|
||||||
signal export_templates_downloaded(version: String)
|
signal export_templates_downloaded(version: String)
|
||||||
|
signal status_update(status: String)
|
||||||
|
|
||||||
|
enum Status{
|
||||||
|
IDLE,
|
||||||
|
RELEASE_DOWNLOAD_IN_PROGRESS,
|
||||||
|
TEMPLATE_DOWNLOAD_IN_PROGRESS,
|
||||||
|
DOWNLOAD_DONE,
|
||||||
|
FETCHING_RELEASES,
|
||||||
|
FETCHING_DONE,
|
||||||
|
VERSION_NOT_IN_INDEX,
|
||||||
|
RELEASE_ALREADY_EXISTS,
|
||||||
|
TEMPLATE_ALREADY_EXISTS,
|
||||||
|
UNPACKING_TEMPLATES,
|
||||||
|
UNPACKING_RELEASE,
|
||||||
|
RELEASE_INSTALLED,
|
||||||
|
TEMPLATE_INSTALLED,
|
||||||
|
}
|
||||||
|
|
||||||
|
const STATUS_MESSAGES := {
|
||||||
|
Status.IDLE: "Idle",
|
||||||
|
Status.RELEASE_DOWNLOAD_IN_PROGRESS: "Downloading Godot v%s",
|
||||||
|
Status.TEMPLATE_DOWNLOAD_IN_PROGRESS: "Downloading Export Templates for v%s",
|
||||||
|
Status.DOWNLOAD_DONE: "Done downloading",
|
||||||
|
Status.FETCHING_RELEASES: "Fetching releases",
|
||||||
|
Status.FETCHING_DONE: "Done fetching releases",
|
||||||
|
Status.VERSION_NOT_IN_INDEX: "Version not in index. Fetch first",
|
||||||
|
Status.RELEASE_ALREADY_EXISTS: "This version already exists",
|
||||||
|
Status.TEMPLATE_ALREADY_EXISTS: "Templates for this version already exist",
|
||||||
|
Status.UNPACKING_TEMPLATES: "Unpacking Export Templates for v%s",
|
||||||
|
Status.UNPACKING_RELEASE: "Unpacking Godot v%s",
|
||||||
|
Status.RELEASE_INSTALLED: "Godot v%s installed",
|
||||||
|
Status.TEMPLATE_INSTALLED: "Export Templates for Godot v%s installed",
|
||||||
|
}
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
DirAccess.make_dir_absolute(TEMP_FOLDER)
|
DirAccess.make_dir_absolute(TEMP_FOLDER)
|
||||||
DirAccess.make_dir_absolute(RELEASES_BASE_FOLDER)
|
DirAccess.make_dir_absolute(RELEASES_BASE_FOLDER)
|
||||||
add_child(http)
|
add_child(http)
|
||||||
releases = load_releases()
|
releases = load_releases()
|
||||||
|
clean_tmp()
|
||||||
|
|
||||||
|
|
||||||
func fetch_releases(force_local: bool = false) -> void:
|
func fetch_releases(force_local: bool = false) -> void:
|
||||||
if force_local:
|
if force_local && FileAccess.file_exists(RELEASES_FILE):
|
||||||
releases_fetched.emit(releases)
|
releases_fetched.emit(releases)
|
||||||
return
|
return
|
||||||
|
|
||||||
if is_downloading:
|
if is_downloading:
|
||||||
print("downloading something, try again later")
|
print("Another download is in progress, try again later")
|
||||||
return
|
return
|
||||||
|
|
||||||
if releases.last_checked_at + FETCH_COOLDOWN > Time.get_unix_time_from_system():
|
if releases.last_checked_at + FETCH_COOLDOWN > Time.get_unix_time_from_system():
|
||||||
@ -82,7 +115,8 @@ func fetch_releases(force_local: bool = false) -> void:
|
|||||||
if rm.is_empty():
|
if rm.is_empty():
|
||||||
releases.releases.erase(i.tag_name)
|
releases.releases.erase(i.tag_name)
|
||||||
|
|
||||||
releases_fetched.emit()
|
releases_fetched.emit(releases)
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.FETCHING_DONE])
|
||||||
is_downloading = false
|
is_downloading = false
|
||||||
save_releases()
|
save_releases()
|
||||||
|
|
||||||
@ -92,6 +126,7 @@ func fetch_releases(force_local: bool = false) -> void:
|
|||||||
"X-GitHub-Api-Version: 2022-11-28",
|
"X-GitHub-Api-Version: 2022-11-28",
|
||||||
]
|
]
|
||||||
is_downloading = true
|
is_downloading = true
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.FETCHING_RELEASES])
|
||||||
http.request(API_SLUG + RELEASES_SLUG, PackedStringArray(headers))
|
http.request(API_SLUG + RELEASES_SLUG, PackedStringArray(headers))
|
||||||
http.request_completed.connect(response_func, CONNECT_ONE_SHOT)
|
http.request_completed.connect(response_func, CONNECT_ONE_SHOT)
|
||||||
|
|
||||||
@ -102,11 +137,13 @@ func download_release(version: String) -> void:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if !releases.releases.has(version):
|
if !releases.releases.has(version):
|
||||||
print("this version is not in the index yet or does not exist. fetch first")
|
# print("this version is not in the index yet or does not exist. fetch first")
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.VERSION_NOT_IN_INDEX])
|
||||||
return
|
return
|
||||||
|
|
||||||
if (releases.releases[version] as ReleaseMetadata).binary_path != "":
|
if (releases.releases[version] as ReleaseMetadata).binary_path != "":
|
||||||
print("already have this version")
|
# print("already have this version")
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.RELEASE_ALREADY_EXISTS])
|
||||||
return
|
return
|
||||||
|
|
||||||
var rm: ReleaseMetadata = releases.releases[version]
|
var rm: ReleaseMetadata = releases.releases[version]
|
||||||
@ -114,6 +151,7 @@ func download_release(version: String) -> void:
|
|||||||
if response_code == 200:
|
if response_code == 200:
|
||||||
# download happens in place.
|
# download happens in place.
|
||||||
# we know the file is zip, so save it to temp first before unpacking
|
# we know the file is zip, so save it to temp first before unpacking
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.DOWNLOAD_DONE])
|
||||||
print("got it in place")
|
print("got it in place")
|
||||||
print("downloading url: ", rm.binary_github_filename)
|
print("downloading url: ", rm.binary_github_filename)
|
||||||
var zip_filename := TEMP_FOLDER.path_join("%s.zip" % version)
|
var zip_filename := TEMP_FOLDER.path_join("%s.zip" % version)
|
||||||
@ -132,7 +170,8 @@ func download_release(version: String) -> void:
|
|||||||
return
|
return
|
||||||
var res := zip.read_file(filename.trim_suffix(".zip"))
|
var res := zip.read_file(filename.trim_suffix(".zip"))
|
||||||
zip.close()
|
zip.close()
|
||||||
# clean_tmp()
|
clean_tmp()
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.UNPACKING_RELEASE] % version)
|
||||||
var d := DirAccess.open(RELEASES_BASE_FOLDER)
|
var d := DirAccess.open(RELEASES_BASE_FOLDER)
|
||||||
d.make_dir_recursive(version)
|
d.make_dir_recursive(version)
|
||||||
var new_file := RELEASES_BASE_FOLDER.path_join(version)
|
var new_file := RELEASES_BASE_FOLDER.path_join(version)
|
||||||
@ -142,6 +181,7 @@ func download_release(version: String) -> void:
|
|||||||
f.close()
|
f.close()
|
||||||
rm.binary_path = new_file
|
rm.binary_path = new_file
|
||||||
version_downloaded.emit(version)
|
version_downloaded.emit(version)
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.RELEASE_INSTALLED] % version)
|
||||||
is_downloading = false
|
is_downloading = false
|
||||||
save_releases()
|
save_releases()
|
||||||
|
|
||||||
@ -155,6 +195,7 @@ func download_release(version: String) -> void:
|
|||||||
"X-GitHub-Api-Version: 2022-11-28",
|
"X-GitHub-Api-Version: 2022-11-28",
|
||||||
]
|
]
|
||||||
var asset_url = API_SLUG.path_join(RELEASES_SLUG).path_join(ASSET_SLUG) % rm.binary_github_asset_id
|
var asset_url = API_SLUG.path_join(RELEASES_SLUG).path_join(ASSET_SLUG) % rm.binary_github_asset_id
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.RELEASE_DOWNLOAD_IN_PROGRESS] % version)
|
||||||
is_downloading = true
|
is_downloading = true
|
||||||
http.request(asset_url, PackedStringArray(headers))
|
http.request(asset_url, PackedStringArray(headers))
|
||||||
http.request_completed.connect(response_func.bind(rm.binary_github_filename), CONNECT_ONE_SHOT)
|
http.request_completed.connect(response_func.bind(rm.binary_github_filename), CONNECT_ONE_SHOT)
|
||||||
@ -166,16 +207,19 @@ func download_export_templates(version: String) -> void:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if !releases.releases.has(version):
|
if !releases.releases.has(version):
|
||||||
print("this version is not in the index yet or does not exist. fetch first")
|
# print("this version is not in the index yet or does not exist. fetch first")
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.VERSION_NOT_IN_INDEX])
|
||||||
return
|
return
|
||||||
|
|
||||||
if (releases.releases[version] as ReleaseMetadata).export_templates_path != "":
|
if (releases.releases[version] as ReleaseMetadata).export_templates_path != "":
|
||||||
print("already have templates for this version")
|
# print("already have templates for this version")
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.TEMPLATE_ALREADY_EXISTS])
|
||||||
return
|
return
|
||||||
|
|
||||||
var rm: ReleaseMetadata = releases.releases[version]
|
var rm: ReleaseMetadata = releases.releases[version]
|
||||||
var response_func = func(_result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray):
|
var response_func = func(_result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray):
|
||||||
if response_code == 200:
|
if response_code == 200:
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.DOWNLOAD_DONE])
|
||||||
print("got it in place")
|
print("got it in place")
|
||||||
print("downloading url: ", rm.export_github_filename)
|
print("downloading url: ", rm.export_github_filename)
|
||||||
var zip_filename := TEMP_FOLDER.path_join("%s_export.tpz" % version)
|
var zip_filename := TEMP_FOLDER.path_join("%s_export.tpz" % version)
|
||||||
@ -196,10 +240,11 @@ func download_export_templates(version: String) -> void:
|
|||||||
var d := DirAccess.open(RELEASES_BASE_FOLDER)
|
var d := DirAccess.open(RELEASES_BASE_FOLDER)
|
||||||
d.make_dir_recursive(version.path_join("templates"))
|
d.make_dir_recursive(version.path_join("templates"))
|
||||||
var templates_folder := RELEASES_BASE_FOLDER.path_join(version)
|
var templates_folder := RELEASES_BASE_FOLDER.path_join(version)
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.UNPACKING_TEMPLATES] % version)
|
||||||
for file in files:
|
for file in files:
|
||||||
var t := Thread.new()
|
var t := Thread.new()
|
||||||
threads.append(t)
|
threads.append(t)
|
||||||
t.start(unpack_zip_file.bind(zip_filename, file, templates_folder.path_join(file), t))
|
t.start(unpack_zip_file.bind(zip_filename, file, templates_folder.path_join(file), t, version))
|
||||||
|
|
||||||
zip.close()
|
zip.close()
|
||||||
# don't clean tmp just yet, since there might be other threads
|
# don't clean tmp just yet, since there might be other threads
|
||||||
@ -220,12 +265,13 @@ func download_export_templates(version: String) -> void:
|
|||||||
"X-GitHub-Api-Version: 2022-11-28",
|
"X-GitHub-Api-Version: 2022-11-28",
|
||||||
]
|
]
|
||||||
var asset_url = API_SLUG.path_join(RELEASES_SLUG).path_join(ASSET_SLUG) % rm.export_github_asset_id
|
var asset_url = API_SLUG.path_join(RELEASES_SLUG).path_join(ASSET_SLUG) % rm.export_github_asset_id
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.TEMPLATE_DOWNLOAD_IN_PROGRESS] % version)
|
||||||
is_downloading = true
|
is_downloading = true
|
||||||
http.request(asset_url, PackedStringArray(headers))
|
http.request(asset_url, PackedStringArray(headers))
|
||||||
http.request_completed.connect(response_func, CONNECT_ONE_SHOT)
|
http.request_completed.connect(response_func, CONNECT_ONE_SHOT)
|
||||||
|
|
||||||
|
|
||||||
func unpack_zip_file(zip_file: String, from_file: String, dest_file: String, thread: Thread) -> void:
|
func unpack_zip_file(zip_file: String, from_file: String, dest_file: String, thread: Thread, version: String) -> void:
|
||||||
print("extracting file ", from_file, " to: ", dest_file)
|
print("extracting file ", from_file, " to: ", dest_file)
|
||||||
var z := ZIPReader.new()
|
var z := ZIPReader.new()
|
||||||
var f := z.open(zip_file)
|
var f := z.open(zip_file)
|
||||||
@ -239,14 +285,15 @@ func unpack_zip_file(zip_file: String, from_file: String, dest_file: String, thr
|
|||||||
file.close()
|
file.close()
|
||||||
z.close()
|
z.close()
|
||||||
|
|
||||||
_clean_threads.call_deferred(thread)
|
_clean_threads.call_deferred(thread, version)
|
||||||
|
|
||||||
|
|
||||||
func _clean_threads(thread: Thread) -> void:
|
func _clean_threads(thread: Thread, version: String) -> void:
|
||||||
threads.erase(thread)
|
threads.erase(thread)
|
||||||
thread.wait_to_finish()
|
thread.wait_to_finish()
|
||||||
|
|
||||||
if threads.is_empty():
|
if threads.is_empty():
|
||||||
|
status_update.emit(STATUS_MESSAGES[Status.TEMPLATE_INSTALLED] % version)
|
||||||
clean_tmp()
|
clean_tmp()
|
||||||
|
|
||||||
|
|
||||||
@ -274,6 +321,14 @@ func get_version_metadata(version: String) -> ReleaseMetadata:
|
|||||||
return releases.releases.get(version)
|
return releases.releases.get(version)
|
||||||
|
|
||||||
|
|
||||||
|
func get_installed_versions() -> Array[ReleaseMetadata]:
|
||||||
|
var res: Array[ReleaseMetadata] = []
|
||||||
|
for version in releases.releases:
|
||||||
|
if is_version_installed(version):
|
||||||
|
res.append(releases.releases[version])
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
func clean_tmp() -> void:
|
func clean_tmp() -> void:
|
||||||
var d := DirAccess.open(TEMP_FOLDER)
|
var d := DirAccess.open(TEMP_FOLDER)
|
||||||
if !d:
|
if !d:
|
||||||
|
@ -7,18 +7,18 @@ class_name ReleaseItem
|
|||||||
|
|
||||||
var version: String
|
var version: String
|
||||||
|
|
||||||
signal install_button_pressed
|
signal install_button_pressed(version)
|
||||||
signal install_templates_button_pressed
|
signal install_templates_button_pressed(version)
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
install_button.pressed.connect(func(): install_button_pressed.emit())
|
install_button.pressed.connect(func(): install_button_pressed.emit(version))
|
||||||
install_templates_button.pressed.connect(func(): install_templates_button_pressed.emit())
|
install_templates_button.pressed.connect(func(): install_templates_button_pressed.emit(version))
|
||||||
|
|
||||||
|
|
||||||
func set_version(v: String) -> void:
|
func set_version(v: String) -> void:
|
||||||
version = v
|
version = v
|
||||||
version_label.text = v
|
version_label.text = "Godot v%s" % v
|
||||||
|
|
||||||
|
|
||||||
func set_install_button_disabled(d: bool) -> void:
|
func set_install_button_disabled(d: bool) -> void:
|
||||||
@ -27,3 +27,21 @@ func set_install_button_disabled(d: bool) -> void:
|
|||||||
|
|
||||||
func set_templates_button_disabled(d: bool) -> void:
|
func set_templates_button_disabled(d: bool) -> void:
|
||||||
install_templates_button.disabled = d
|
install_templates_button.disabled = d
|
||||||
|
|
||||||
|
|
||||||
|
func _on_version_downloaded(p_version: String) -> void:
|
||||||
|
if p_version != version:
|
||||||
|
# this isn't us
|
||||||
|
return
|
||||||
|
|
||||||
|
set_install_button_disabled(true)
|
||||||
|
ReleasesManager.version_downloaded.disconnect(_on_version_downloaded)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_export_templates_downloaded(p_version: String) -> void:
|
||||||
|
if p_version != version:
|
||||||
|
# this isn't us
|
||||||
|
return
|
||||||
|
|
||||||
|
set_templates_button_disabled(true)
|
||||||
|
ReleasesManager.export_templates_downloaded.disconnect(_on_export_templates_downloaded)
|
||||||
|
@ -1,3 +1,43 @@
|
|||||||
extends VBoxContainer
|
extends VBoxContainer
|
||||||
|
|
||||||
const ITEM_SCENE := preload("res://UI/Components/ReleaseItem.tscn")
|
const ITEM_SCENE := preload("res://UI/Components/ReleaseItem.tscn")
|
||||||
|
|
||||||
|
@onready var release_items_container: VBoxContainer = %ReleaseItemsContainer
|
||||||
|
@onready var fetch_button: Button = %FetchButton
|
||||||
|
@onready var status_label: Label = %StatusLabel
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
ReleasesManager.releases_fetched.connect(releases_updated)
|
||||||
|
ReleasesManager.releases_fetched.connect(func(_x):
|
||||||
|
await get_tree().process_frame
|
||||||
|
fetch_button.disabled = false
|
||||||
|
)
|
||||||
|
fetch_button.pressed.connect(func():
|
||||||
|
ReleasesManager.fetch_releases()
|
||||||
|
fetch_button.disabled = true
|
||||||
|
)
|
||||||
|
ReleasesManager.fetch_releases(true)
|
||||||
|
|
||||||
|
ReleasesManager.status_update.connect(status_label.set_text)
|
||||||
|
|
||||||
|
|
||||||
|
func releases_updated(releases: ReleasesManager.Releases) -> void:
|
||||||
|
clear_releases()
|
||||||
|
for version in releases.releases:
|
||||||
|
var item: ReleaseItem = ITEM_SCENE.instantiate()
|
||||||
|
release_items_container.add_child(item)
|
||||||
|
item.set_version(version)
|
||||||
|
item.set_install_button_disabled(ReleasesManager.is_version_installed(version))
|
||||||
|
item.set_templates_button_disabled(ReleasesManager.is_version_templates_installed(version))
|
||||||
|
|
||||||
|
item.install_button_pressed.connect(ReleasesManager.download_release)
|
||||||
|
item.install_templates_button_pressed.connect(ReleasesManager.download_release)
|
||||||
|
|
||||||
|
ReleasesManager.version_downloaded.connect(item._on_version_downloaded)
|
||||||
|
ReleasesManager.export_templates_downloaded.connect(item._on_export_templates_downloaded)
|
||||||
|
|
||||||
|
|
||||||
|
func clear_releases() -> void:
|
||||||
|
for i in release_items_container.get_children():
|
||||||
|
i.queue_free()
|
||||||
|
@ -46,6 +46,5 @@ alignment = 2
|
|||||||
|
|
||||||
[node name="StatusLabel" type="Label" parent="HBoxContainer/HBoxContainer"]
|
[node name="StatusLabel" type="Label" parent="HBoxContainer/HBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
visible = false
|
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Downloading v..."
|
text = "Idle"
|
||||||
|
Loading…
Reference in New Issue
Block a user