Skip to content

Commit f9f3a2c

Browse files
authored
Merge pull request #68 from R1kaB3rN/download
Update downloading process for launcher
2 parents caa5daa + b546791 commit f9f3a2c

File tree

3 files changed

+63
-239
lines changed

3 files changed

+63
-239
lines changed

umu/umu_dl_util.py

Lines changed: 56 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
from umu_plugins import enable_zenity
1212
from socket import gaierror
1313
from umu_log import log
14-
from umu_consts import STEAM_COMPAT, UMU_CACHE
14+
from umu_consts import STEAM_COMPAT
15+
from tempfile import mkdtemp
1516

1617
try:
1718
from tarfile import tar_filter
@@ -29,34 +30,26 @@ def get_umu_proton(env: Dict[str, str]) -> Union[Dict[str, str]]:
2930
fallback
3031
"""
3132
files: List[Tuple[str, str]] = []
33+
tmp: Path = Path(mkdtemp())
3234

33-
UMU_CACHE.mkdir(exist_ok=True, parents=True)
3435
STEAM_COMPAT.mkdir(exist_ok=True, parents=True)
3536

36-
# Prioritize the Steam compat
37-
if _get_from_steamcompat(env, STEAM_COMPAT, UMU_CACHE):
38-
return env
39-
4037
try:
38+
log.debug("Sending request to api.github.com")
4139
files = _fetch_releases()
4240
except gaierror:
4341
pass # User is offline
4442

45-
# Use the latest Proton in the cache if it exists
46-
if _get_from_cache(env, STEAM_COMPAT, UMU_CACHE, files, True):
47-
return env
48-
49-
# Download the latest if Proton is not in Steam compat
50-
# If the digests mismatched, refer to the cache in the next block
51-
if _get_latest(env, STEAM_COMPAT, UMU_CACHE, files):
43+
# Download the latest Proton
44+
if _get_latest(env, STEAM_COMPAT, tmp, files):
5245
return env
5346

54-
# Refer to an old version previously downloaded
55-
# Reached on digest mismatch, user interrupt or download failure/no internet
56-
if _get_from_cache(env, STEAM_COMPAT, UMU_CACHE, files, False):
47+
# When offline or an error occurs, use the first Proton in
48+
# compatibilitytools.d
49+
if _get_from_steamcompat(env, STEAM_COMPAT):
5750
return env
5851

59-
# No internet and cache/compat tool is empty, just return and raise an
52+
# No internet and compat tool is empty, just return and raise an
6053
# exception from the caller
6154
return env
6255

@@ -68,10 +61,14 @@ def _fetch_releases() -> List[Tuple[str, str]]:
6861
conn: HTTPConnection = HTTPSConnection(
6962
"api.github.com", timeout=30, context=create_default_context()
7063
)
64+
repo: str = "/repos/Open-Wine-Components/umu-proton/releases"
65+
66+
if environ.get("PROTONPATH") == "GE-Proton":
67+
repo = "/repos/GloriousEggroll/proton-ge-custom/releases"
7168

7269
conn.request(
7370
"GET",
74-
"/repos/Open-Wine-Components/umu-proton/releases",
71+
repo,
7572
headers={
7673
"Accept": "application/vnd.github+json",
7774
"X-GitHub-Api-Version": "2022-11-28",
@@ -92,12 +89,14 @@ def _fetch_releases() -> List[Tuple[str, str]]:
9289

9390
for asset in assets:
9491
if (
95-
"name" in asset
92+
asset.get("name")
9693
and (
97-
asset["name"].endswith("sum")
94+
asset.get("name").endswith("sum")
9895
or (
99-
asset["name"].endswith("tar.gz")
100-
and asset["name"].startswith(("umu-proton", "ULWGL-Proton"))
96+
asset.get("name").endswith("tar.gz")
97+
and asset.get("name").startswith(
98+
("umu-proton", "ULWGL-Proton", "GE-Proton")
99+
)
101100
)
102101
)
103102
and "browser_download_url" in asset
@@ -119,7 +118,7 @@ def _fetch_releases() -> List[Tuple[str, str]]:
119118

120119

121120
def _fetch_proton(
122-
env: Dict[str, str], steam_compat: Path, cache: Path, files: List[Tuple[str, str]]
121+
env: Dict[str, str], steam_compat: Path, tmp: Path, files: List[Tuple[str, str]]
123122
) -> Dict[str, str]:
124123
"""Download the latest umu-proton and set it as PROTONPATH."""
125124
hash, hash_url = files[0]
@@ -144,7 +143,7 @@ def _fetch_proton(
144143
f"github.com returned the status: {resp.status}"
145144
)
146145
raise HTTPException(err)
147-
with cache.joinpath(hash).open(mode="wb") as file:
146+
with tmp.joinpath(hash).open(mode="wb") as file:
148147
file.write(resp.read())
149148

150149
# Proton
@@ -156,7 +155,7 @@ def _fetch_proton(
156155
"--silent",
157156
proton_url,
158157
"--output-dir",
159-
cache.as_posix(),
158+
tmp.as_posix(),
160159
]
161160

162161
msg: str = f"Downloading {proton_dir} ..."
@@ -176,21 +175,21 @@ def _fetch_proton(
176175
f"github.com returned the status: {resp.status}"
177176
)
178177
raise HTTPException(err)
179-
with cache.joinpath(proton).open(mode="wb") as file:
178+
with tmp.joinpath(proton).open(mode="wb") as file:
180179
file.write(resp.read())
181180

182181
log.console("Completed.")
183182

184-
with cache.joinpath(proton).open(mode="rb") as file:
183+
with tmp.joinpath(proton).open(mode="rb") as file:
185184
if (
186185
sha512(file.read()).hexdigest()
187-
!= cache.joinpath(hash).read_text().split(" ")[0]
186+
!= tmp.joinpath(hash).read_text().split(" ")[0]
188187
):
189188
err: str = "Digests mismatched.\nFalling back to cache ..."
190189
raise ValueError(err)
191190
log.console(f"{proton}: SHA512 is OK")
192191

193-
_extract_dir(cache.joinpath(proton), steam_compat)
192+
_extract_dir(tmp.joinpath(proton), steam_compat)
194193
environ["PROTONPATH"] = steam_compat.joinpath(proton_dir).as_posix()
195194
env["PROTONPATH"] = environ["PROTONPATH"]
196195

@@ -208,6 +207,8 @@ def _extract_dir(proton: Path, steam_compat: Path) -> None:
208207
log.warning("Archive will be extracted insecurely")
209208

210209
log.console(f"Extracting {proton} -> {steam_compat} ...")
210+
# TODO: Rather than extracting all of the contents, we should prefer
211+
# the difference (e.g., rsync)
211212
tar.extractall(path=steam_compat.as_posix()) # noqa: S202
212213
log.console("Completed.")
213214

@@ -228,9 +229,13 @@ def _cleanup(tarball: str, proton: str, cache: Path, steam_compat: Path) -> None
228229

229230

230231
def _get_from_steamcompat(
231-
env: Dict[str, str], steam_compat: Path, cache: Path
232+
env: Dict[str, str], steam_compat: Path
232233
) -> Union[Dict[str, str], None]:
233-
"""Refer to Steam compat folder for any existing Proton directories."""
234+
"""Refer to Steam compat folder for any existing Proton directories.
235+
236+
Executed when an error occurs when retrieving and setting the latest
237+
Proton
238+
"""
234239
for proton in sorted(
235240
[
236241
proton
@@ -248,57 +253,8 @@ def _get_from_steamcompat(
248253
return None
249254

250255

251-
def _get_from_cache(
252-
env: Dict[str, str],
253-
steam_compat: Path,
254-
cache: Path,
255-
files: List[Tuple[str, str]],
256-
use_latest: bool = True,
257-
) -> Union[Dict[str, str], None]:
258-
"""Refer to umu cache directory.
259-
260-
Use the latest in the cache when present. When download fails, use an old version
261-
Older Proton versions are only referred to when: digests mismatch, user
262-
interrupt, or download failure/no internet
263-
"""
264-
resource: Tuple[Path, str] = None # Path to the archive and its file name
265-
266-
for tarball in [
267-
tarball
268-
for tarball in cache.glob("*.tar.gz")
269-
if tarball.name.startswith("umu-proton")
270-
or tarball.name.startswith("ULWGL-Proton")
271-
]:
272-
# Online
273-
if files and tarball == cache.joinpath(files[1][0]) and use_latest:
274-
resource = (tarball, tarball.name)
275-
break
276-
# Offline, download interrupt, digest mismatch
277-
if not files or not use_latest:
278-
resource = (tarball, tarball.name)
279-
break
280-
281-
if not resource:
282-
return None
283-
284-
path, name = resource
285-
proton: str = name[: name.find(".tar.gz")] # Proton dir
286-
try:
287-
log.console(f"{name} found in: {path}")
288-
_extract_dir(path, steam_compat)
289-
log.console(f"Using {proton}")
290-
environ["PROTONPATH"] = steam_compat.joinpath(proton).as_posix()
291-
env["PROTONPATH"] = environ["PROTONPATH"]
292-
return env
293-
except KeyboardInterrupt:
294-
if steam_compat.joinpath(proton).is_dir():
295-
log.console(f"Purging {proton} in {steam_compat} ...")
296-
rmtree(steam_compat.joinpath(proton).as_posix())
297-
raise
298-
299-
300256
def _get_latest(
301-
env: Dict[str, str], steam_compat: Path, cache: Path, files: List[Tuple[str, str]]
257+
env: Dict[str, str], steam_compat: Path, tmp: Path, files: List[Tuple[str, str]]
302258
) -> Union[Dict[str, str], None]:
303259
"""Download the latest Proton for new installs -- empty cache and Steam compat.
304260
@@ -308,11 +264,25 @@ def _get_latest(
308264
return None
309265

310266
try:
311-
log.console("Fetching latest release ...")
312267
tarball: str = files[1][0]
268+
sums: str = files[0][0]
313269
proton: str = tarball[: tarball.find(".tar.gz")]
314-
_fetch_proton(env, steam_compat, cache, files)
315-
log.console(f"Using {proton}")
270+
version: str = (
271+
"GE-Proton" if environ.get("PROTONPATH") == "GE-Proton" else "umu-proton"
272+
)
273+
274+
if steam_compat.joinpath(proton).is_dir():
275+
log.console(f"{version} is up to date")
276+
environ["PROTONPATH"] = steam_compat.joinpath(proton).as_posix()
277+
env["PROTONPATH"] = environ["PROTONPATH"]
278+
return env
279+
280+
_fetch_proton(env, steam_compat, tmp, files)
281+
log.debug("Removing: %s", tarball)
282+
log.debug("Removing: %s", sums)
283+
tmp.joinpath(tarball).unlink(missing_ok=True)
284+
tmp.joinpath(sums).unlink(missing_ok=True)
285+
log.console(f"Using {version} ({proton})")
316286
env["PROTONPATH"] = environ["PROTONPATH"]
317287
except ValueError:
318288
log.exception("Exception")
@@ -321,7 +291,7 @@ def _get_latest(
321291
# Digest mismatched
322292
# Refer to the cache for old version next
323293
# Since we do not want the user to use a suspect file, delete it
324-
cache.joinpath(tarball).unlink(missing_ok=True)
294+
tmp.joinpath(tarball).unlink(missing_ok=True)
325295
return None
326296
except KeyboardInterrupt:
327297
tarball: str = files[1][0]
@@ -330,7 +300,7 @@ def _get_latest(
330300
# Exit cleanly
331301
# Clean up extracted data and cache to prevent corruption/errors
332302
# Refer to the cache for old version next
333-
_cleanup(tarball, proton_dir, cache, steam_compat)
303+
_cleanup(tarball, proton_dir, tmp, steam_compat)
334304
return None
335305
except HTTPException: # Download failed
336306
return None

umu/umu_run.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ def check_env(
144144
os.environ["PROTONPATH"]
145145
).as_posix()
146146

147+
# GE-Proton
148+
if os.environ.get("PROTONPATH") and os.environ.get("PROTONPATH") == "GE-Proton":
149+
log.debug("GE-Proton selected")
150+
get_umu_proton(env)
151+
147152
if "PROTONPATH" not in os.environ:
148153
os.environ["PROTONPATH"] = ""
149154
get_umu_proton(env)

0 commit comments

Comments
 (0)