mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: adding drive mapping
This commit is contained in:
parent
1705b89355
commit
bcca701dc9
4 changed files with 68 additions and 27 deletions
|
@ -20,3 +20,5 @@ export const seedsPath = app.isPackaged
|
||||||
export const backupsPath = path.join(app.getPath("userData"), "Backups");
|
export const backupsPath = path.join(app.getPath("userData"), "Backups");
|
||||||
|
|
||||||
export const appVersion = app.getVersion();
|
export const appVersion = app.getVersion();
|
||||||
|
|
||||||
|
export const artifactMetadataFileName = "hydra-launcher-metadata.json";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { registerEvent } from "../register-event";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { backupsPath } from "@main/constants";
|
import { artifactMetadataFileName, backupsPath } from "@main/constants";
|
||||||
import type { GameShop } from "@types";
|
import type { GameShop } from "@types";
|
||||||
|
|
||||||
import YAML from "yaml";
|
import YAML from "yaml";
|
||||||
|
@ -20,10 +20,16 @@ export interface LudusaviBackup {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getPathDrive = (key: string) => {
|
||||||
|
const parts = key.split("/");
|
||||||
|
return parts[0];
|
||||||
|
};
|
||||||
|
|
||||||
const replaceLudusaviBackupWithCurrentUser = (
|
const replaceLudusaviBackupWithCurrentUser = (
|
||||||
gameBackupPath: string,
|
backupPath: string,
|
||||||
backupHomeDir: string
|
title: string
|
||||||
) => {
|
) => {
|
||||||
|
const gameBackupPath = path.join(backupPath, title);
|
||||||
const mappingYamlPath = path.join(gameBackupPath, "mapping.yaml");
|
const mappingYamlPath = path.join(gameBackupPath, "mapping.yaml");
|
||||||
|
|
||||||
const data = fs.readFileSync(mappingYamlPath, "utf8");
|
const data = fs.readFileSync(mappingYamlPath, "utf8");
|
||||||
|
@ -32,32 +38,54 @@ const replaceLudusaviBackupWithCurrentUser = (
|
||||||
drives: Record<string, string>;
|
drives: Record<string, string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const metadataPath = path.join(backupPath, artifactMetadataFileName);
|
||||||
|
|
||||||
|
if (!fs.existsSync(metadataPath)) {
|
||||||
|
logger.error(`metadata not found in backup ${gameBackupPath}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")) as {
|
||||||
|
home: string;
|
||||||
|
documents: string;
|
||||||
|
};
|
||||||
|
|
||||||
const currentHomeDir = normalizePath(app.getPath("home"));
|
const currentHomeDir = normalizePath(app.getPath("home"));
|
||||||
|
const currentDocumentsDir = normalizePath(app.getPath("documents"));
|
||||||
|
|
||||||
// TODO: Only works on Windows
|
/* Renaming logic */
|
||||||
const usersDirPath = path.join(gameBackupPath, "drive-C", "Users");
|
const mappedHomeDir = path.join(
|
||||||
|
gameBackupPath,
|
||||||
|
metadata.home.replace("C:", "drive-C")
|
||||||
|
);
|
||||||
|
const mappedDocumentsDir = path.join(
|
||||||
|
gameBackupPath,
|
||||||
|
metadata.documents.replace("C:", "drive-C")
|
||||||
|
);
|
||||||
|
|
||||||
const oldPath = path.join(usersDirPath, path.basename(backupHomeDir));
|
if (fs.existsSync(mappedHomeDir)) {
|
||||||
const newPath = path.join(usersDirPath, path.basename(currentHomeDir));
|
fs.renameSync(
|
||||||
|
mappedHomeDir,
|
||||||
|
path.join(gameBackupPath, currentHomeDir.replace("C:", "drive-C"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Directories are different, rename
|
if (fs.existsSync(mappedDocumentsDir)) {
|
||||||
if (backupHomeDir !== currentHomeDir) {
|
fs.renameSync(
|
||||||
if (fs.existsSync(newPath)) {
|
mappedDocumentsDir,
|
||||||
// Ensures that the destination is empty
|
path.join(gameBackupPath, currentDocumentsDir.replace("C:", "drive-C"))
|
||||||
fs.rmSync(newPath, {
|
);
|
||||||
recursive: true,
|
|
||||||
force: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.renameSync(oldPath, newPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const backups = manifest.backups.map((backup: LudusaviBackup) => {
|
const backups = manifest.backups.map((backup: LudusaviBackup) => {
|
||||||
const files = Object.entries(backup.files).reduce((prev, [key, value]) => {
|
const files = Object.entries(backup.files).reduce((prev, [key, value]) => {
|
||||||
|
const updatedKey = key
|
||||||
|
.replace(metadata.documents, currentDocumentsDir)
|
||||||
|
.replace(metadata.home, currentHomeDir);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
[key.replace(backupHomeDir, currentHomeDir)]: value,
|
[updatedKey]: value,
|
||||||
};
|
};
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
|
@ -76,10 +104,9 @@ const downloadGameArtifact = async (
|
||||||
shop: GameShop,
|
shop: GameShop,
|
||||||
gameArtifactId: string
|
gameArtifactId: string
|
||||||
) => {
|
) => {
|
||||||
const { downloadUrl, objectKey, homeDir } = await HydraApi.post<{
|
const { downloadUrl, objectKey } = await HydraApi.post<{
|
||||||
downloadUrl: string;
|
downloadUrl: string;
|
||||||
objectKey: string;
|
objectKey: string;
|
||||||
homeDir: string;
|
|
||||||
}>(`/profile/games/artifacts/${gameArtifactId}/download`);
|
}>(`/profile/games/artifacts/${gameArtifactId}/download`);
|
||||||
|
|
||||||
const zipLocation = path.join(app.getPath("userData"), objectKey);
|
const zipLocation = path.join(app.getPath("userData"), objectKey);
|
||||||
|
@ -123,10 +150,7 @@ const downloadGameArtifact = async (
|
||||||
const [game] = await Ludusavi.findGames(shop, objectId);
|
const [game] = await Ludusavi.findGames(shop, objectId);
|
||||||
if (!game) throw new Error("Game not found in Ludusavi manifest");
|
if (!game) throw new Error("Game not found in Ludusavi manifest");
|
||||||
|
|
||||||
replaceLudusaviBackupWithCurrentUser(
|
replaceLudusaviBackupWithCurrentUser(backupPath, game);
|
||||||
path.join(backupPath, game),
|
|
||||||
normalizePath(path.normalize(homeDir))
|
|
||||||
);
|
|
||||||
|
|
||||||
Ludusavi.restoreBackup(backupPath).then(() => {
|
Ludusavi.restoreBackup(backupPath).then(() => {
|
||||||
WindowManager.mainWindow?.webContents.send(
|
WindowManager.mainWindow?.webContents.send(
|
||||||
|
|
|
@ -7,7 +7,7 @@ import crypto from "node:crypto";
|
||||||
import { GameShop } from "@types";
|
import { GameShop } from "@types";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
import { backupsPath } from "@main/constants";
|
import { artifactMetadataFileName, backupsPath } from "@main/constants";
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
import { normalizePath } from "@main/helpers";
|
import { normalizePath } from "@main/helpers";
|
||||||
|
|
||||||
|
@ -23,6 +23,21 @@ const bundleBackup = async (shop: GameShop, objectId: string) => {
|
||||||
|
|
||||||
const tarLocation = path.join(backupsPath, `${crypto.randomUUID()}.zip`);
|
const tarLocation = path.join(backupsPath, `${crypto.randomUUID()}.zip`);
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(backupPath, artifactMetadataFileName),
|
||||||
|
JSON.stringify({
|
||||||
|
home: normalizePath(app.getPath("home")),
|
||||||
|
documents: normalizePath(app.getPath("documents")),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
JSON.stringify({
|
||||||
|
home: normalizePath(app.getPath("home")),
|
||||||
|
documents: normalizePath(app.getPath("documents")),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
await tar.create(
|
await tar.create(
|
||||||
{
|
{
|
||||||
gzip: false,
|
gzip: false,
|
||||||
|
|
|
@ -30,4 +30,4 @@ export const isPortableVersion = () =>
|
||||||
process.env.PORTABLE_EXECUTABLE_FILE !== null;
|
process.env.PORTABLE_EXECUTABLE_FILE !== null;
|
||||||
|
|
||||||
export const normalizePath = (str: string) =>
|
export const normalizePath = (str: string) =>
|
||||||
path.normalize(str.replace(/\\/g, "/"));
|
path.normalize(str).replace(/\\/g, "/");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue