Merge pull request #707 from silentrald/feat/706

[feat-706] show DepotDownloader missing executable error
This commit is contained in:
MathieuG-P
2024-12-23 09:44:28 +01:00
committed by GitHub
12 changed files with 66 additions and 28 deletions
+30 -12
View File
@@ -1,30 +1,48 @@
import path from "path";
import fs from "fs";
import { ChildProcessWithoutNullStreams, SpawnOptionsWithoutStdio, spawn } from "child_process";
import { Observable, ReplaySubject, Subscriber, filter, map, share } from "rxjs";
import { DepotDownloaderArgsOptions, DepotDownloaderErrorEvent, DepotDownloaderEvent, DepotDownloaderEventType, DepotDownloaderEventTypes, DepotDownloaderInfoEvent, DepotDownloaderWarningEvent } from "../../shared/models/bs-version-download/depot-downloader.model";
import { UtilsService } from 'main/services/utils.service';
import { CustomError } from "shared/models/exceptions/custom-error.class";
export class DepotDownloader {
private static readonly EXE_PATH = path.join(
UtilsService.getInstance().getAssetsScriptsPath(),
process.platform === "win32" ? "DepotDownloader.exe" : "DepotDownloader"
);
private process: ChildProcessWithoutNullStreams;
private processOut$: Observable<string>;
private subscriber: Subscriber<string>;
public constructor(
options: {
command: string, args?: string[], options?: SpawnOptionsWithoutStdio, echoStartData?: unknown
},
args?: string[], options?: SpawnOptionsWithoutStdio, echoStartData?: unknown
},
logger?: Logger
){
this.processOut$ = new Observable<string>(subscriber => {
) {
if (!fs.existsSync(DepotDownloader.EXE_PATH)) {
throw new CustomError(
"DepotDownloader executable not found",
process.platform === "win32"
? DepotDownloaderErrorEvent.ExeNotFoundWindows
: DepotDownloaderErrorEvent.ExeNotFoundLinux
);
}
this.processOut$ = new Observable<string>(subscriber => {
this.subscriber = subscriber;
this.process = spawn(options.command, options.args ?? [], options.options);
this.process = spawn(DepotDownloader.EXE_PATH, options.args ?? [], options.options);
subscriber.next(`[Info]|[Start]|${JSON.stringify(options.echoStartData) ?? ""}`);
this.process.stdout.on("data", data => {
const stringData: string = data.toString();
if(!stringData.includes(DepotDownloaderInfoEvent.Progress) && !stringData.includes(DepotDownloaderInfoEvent.Validated)){
logger?.info("DepotDownloader stdout:", stringData);
}
@@ -32,7 +50,7 @@ export class DepotDownloader {
const lines: string[] = stringData.split("\n");
lines.forEach(line => subscriber.next(line));
});
this.process.on("error", error => subscriber.error(error));
this.process.stderr.on("error", error => subscriber.error(error));
this.process.on("exit", () => subscriber.complete());
@@ -74,7 +92,7 @@ export class DepotDownloader {
data: splitedLine[2],
}
}),
}),
filter(Boolean));
}
@@ -93,7 +111,7 @@ export class DepotDownloader {
const args: string[] = [];
for(const [key, value] of Object.entries(depotDownloaderArgs)){
if(value === true){
args.push(`-${key}`);
}
@@ -102,7 +120,7 @@ export class DepotDownloader {
args.push(`${value}`);
}
}
return args;
}
@@ -112,4 +130,4 @@ interface Logger {
info: (...args: unknown[]) => void,
warn: (...args: unknown[]) => void,
error: (...args: unknown[]) => void,
}
}
@@ -1,7 +1,6 @@
import { BS_APP_ID, BS_DEPOT } from "../../constants";
import path from "path";
import { BSVersion } from "shared/bs-version.interface";
import { UtilsService } from "../utils.service";
import log from "electron-log";
import { InstallationLocationService } from "../installation-location.service";
import { BSLocalVersionService } from "../bs-local-version.service";
@@ -17,14 +16,12 @@ import { CustomError } from "shared/models/exceptions/custom-error.class";
export class BsSteamDownloaderService {
private static instance: BsSteamDownloaderService;
private readonly utils: UtilsService;
private readonly installLocationService: InstallationLocationService;
private readonly localVersionService: BSLocalVersionService;
private depotDownloader: DepotDownloader;
private constructor() {
this.utils = UtilsService.getInstance();
this.installLocationService = InstallationLocationService.getInstance();
this.localVersionService = BSLocalVersionService.getInstance();
@@ -40,10 +37,6 @@ export class BsSteamDownloaderService {
return BsSteamDownloaderService.instance;
}
private getDepotDownloaderExePath(): string {
return path.join(this.utils.getAssetsScriptsPath(), process.platform === 'linux' ? "DepotDownloader" : "DepotDownloader.exe");
}
private async buildDepotDownloaderInstance(downloadInfos: DownloadSteamInfo, qr?: boolean): Promise<{depotDownloader: DepotDownloader, depotDownloaderOptions: DepotDownloaderArgsOptions, version: BSVersion}> {
const versionPath = await this.localVersionService.getVersionPath(downloadInfos.bsVersion);
@@ -68,11 +61,9 @@ export class BsSteamDownloaderService {
await ensureDir(this.installLocationService.versionsDirectory());
const exePath = this.getDepotDownloaderExePath();
const args = DepotDownloader.buildArgs(depotDownloaderOptions);
const depotDownloader = new DepotDownloader({
command: exePath,
args,
options: { cwd: this.installLocationService.versionsDirectory() },
echoStartData: downloadVersion
@@ -104,11 +95,21 @@ export class BsSteamDownloaderService {
finalize(() => this.localVersionService.initVersionMetadata(version, { store: BsStore.STEAM }))
).subscribe(sub);
}).catch(err => sub.error({
type: DepotDownloaderEventType.Error,
subType: DepotDownloaderErrorEvent.Unknown,
data: err
} as DepotDownloaderEvent));
}).catch(err => {
if (err instanceof CustomError
&& Object.values(DepotDownloaderErrorEvent).includes(
err.code as DepotDownloaderErrorEvent
)
) {
return sub.error(err);
}
return sub.error({
type: DepotDownloaderEventType.Error,
subType: DepotDownloaderErrorEvent.Unknown,
data: err
} as DepotDownloaderEvent)
});
return () => {
depotDownloaderBuildPromise.then(({ depotDownloader }) => depotDownloader.stop());
@@ -2,7 +2,6 @@ export enum DepotDownloaderEventType {
Error = "Error",
Warning = "Warning",
Info = "Info",
}
export interface DepotDownloaderEvent<T = unknown> {
@@ -27,6 +26,8 @@ export enum DepotDownloaderInfoEvent {
}
export enum DepotDownloaderErrorEvent {
ExeNotFoundWindows = "ExeNotFoundWindows",
ExeNotFoundLinux = "ExeNotFoundLinux",
Password = "Password",
InvalidCredentials = "InvalidCredentials",
NoManifest = "NoManifest",
@@ -66,4 +67,4 @@ export interface DepotDownloaderArgsOptions {
dir: string,
validate?: boolean,
qr?: boolean,
}
}