[hotfix] create backup of userdata folder when linking

This commit is contained in:
MathieuG-P
2023-03-13 15:33:39 +01:00
parent 1b54d86324
commit 509b2cd9b9
10 changed files with 90 additions and 37 deletions
+21 -7
View File
@@ -10,7 +10,7 @@ import { IpcService } from '../services/ipc.service';
import { from } from 'rxjs';
import path from 'path';
import { pathExist } from '../helpers/fs.helpers';
import { FolderLinkerService } from '../services/folder-linker.service';
import { FolderLinkerService, LinkOptions } from '../services/folder-linker.service';
import { LocalMapsManagerService } from '../services/additional-content/local-maps-manager.service';
import { readJSON, writeJSON } from 'fs-extra';
import log from "electron-log"
@@ -85,16 +85,23 @@ ipc.on("get-linked-folders", async (req: IpcRequest<BSVersion>, reply) => {
reply(from(localVersions.getLinkedFolders(req.args)));
});
ipc.on("link-folder", async (req: IpcRequest<{ folder: string, keepContents?: boolean}>, reply) => {
ipc.on("link-folder", async (req: IpcRequest<{ folder: string, options?: LinkOptions}>, reply) => {
req.args.options ??= {};
const linker = FolderLinkerService.getInstance();
const relativeMapsFolder = path.join(LocalMapsManagerService.LEVELS_ROOT_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER)
if(req.args.folder.includes(relativeMapsFolder)){
return reply(from(linker.linkFolder(req.args.folder, {keepContents: req.args.keepContents, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER})));
return reply(from(linker.linkFolder(req.args.folder, {keepContents: req.args.options?.keepContents, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER})));
}
const res = from(linker.linkFolder(req.args.folder, {keepContents: true}));
if(req.args.folder.includes("UserData")){
req.args.options = { ...req.args.options, backup: true };
}
const res = from(linker.linkFolder(req.args.folder, req.args.options));
const jsonIPAPath = path.join(req.args.folder, "Beat Saber IPA.json");
@@ -114,16 +121,23 @@ ipc.on("link-folder", async (req: IpcRequest<{ folder: string, keepContents?: bo
});
ipc.on("unlink-folder", async (req: IpcRequest<{folder: string, keepContents?: boolean}>, reply) => {
ipc.on("unlink-folder", async (req: IpcRequest<{ folder: string, options?: LinkOptions}>, reply) => {
req.args.options ??= {};
const linker = FolderLinkerService.getInstance();
const relativeMapsFolder = path.join(LocalMapsManagerService.LEVELS_ROOT_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER)
if(req.args.folder.includes(relativeMapsFolder)){
return reply(from(linker.unlinkFolder(req.args.folder, {keepContents: req.args.keepContents, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER})));
return reply(from(linker.unlinkFolder(req.args.folder, {...req.args.options, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER})));
}
reply(from(linker.unlinkFolder(req.args.folder, {keepContents: req.args.keepContents})));
if(req.args.folder.includes("UserData")){
req.args.options = { ...req.args.options, backup: true };
}
reply(from(linker.unlinkFolder(req.args.folder, req.args.options)));
});
+27 -2
View File
@@ -30,6 +30,22 @@ export class FolderLinkerService {
return path.join(this.sharedFolder, intermediateFolder ?? "", path.basename(folderPath));
}
private getBackupFolder(folderPath: string): string {
return folderPath + "_backup";
}
private async backupFolder(folderPath: string): Promise<void> {
if(!await pathExist(folderPath)){ return; }
return copy(folderPath, this.getBackupFolder(folderPath), { overwrite: true, errorOnExist: false });
}
private async restoreFolder(folderPath: string): Promise<void> {
if(!await pathExist( this.getBackupFolder(folderPath) )){ return; }
return copy(this.getBackupFolder(folderPath), folderPath, { overwrite: true, errorOnExist: false }).then(() => {
return deleteFolder(this.getBackupFolder(folderPath));
});
}
public async linkFolder(folderPath: string, options?: LinkOptions): Promise<void> {
if(await this.isFolderSymlink(folderPath)){ return; }
@@ -39,10 +55,14 @@ export class FolderLinkerService {
await ensureFolderExist(folderPath);
await ensureFolderExist(sharedPath);
if(options?.backup === true){
await this.backupFolder(folderPath);
}
if(options?.keepContents !== false){
await moveFolderContent(folderPath, sharedPath).toPromise();
}
await deleteFolder(folderPath);
return symlink(sharedPath, folderPath, "junction");
@@ -57,11 +77,15 @@ export class FolderLinkerService {
await ensureFolderExist(folderPath);
if(options?.backup === true){
return this.restoreFolder(folderPath);
}
if(options?.keepContents === false){ return; }
await ensureFolderExist(sharedPath);
return copy(sharedPath, folderPath, { errorOnExist: false });
return copy(sharedPath, folderPath, { errorOnExist: false, recursive: true });
}
public async isFolderSymlink(folder: string): Promise<boolean> {
@@ -80,4 +104,5 @@ export class FolderLinkerService {
export interface LinkOptions {
keepContents?: boolean,
intermediateFolder?: string,
backup?: boolean
}
+3 -1
View File
@@ -1,10 +1,11 @@
import { IpcResponse, IpcRequest } from "shared/models/ipc";
import { IpcRequest } from "shared/models/ipc";
import { ipcMain } from "electron";
import { Observable } from "rxjs";
import { IpcChannel, IpcCompleteChannel, IpcErrorChannel } from "shared/models/ipc/ipc-response.interface";
import { AppWindow } from "shared/models/window-manager/app-window.model";
import { WindowManagerService } from "./window-manager.service";
import { IpcReplier } from "shared/models/ipc/ipc-request.interface";
import log from "electron-log";
export class IpcService {
@@ -47,6 +48,7 @@ export class IpcService {
observable.subscribe(data => {
this.send(channel, window, data);
}, error => {
log.error(error);
this.send(this.getErrorChannel(channel), window, error);
}, () => {
this.send(this.getCompleteChannel(channel), window);