mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
[hotfix] move instead of copy if no other version use the linked folder
This commit is contained in:
@@ -14,6 +14,8 @@ import { FolderLinkerService, LinkOptions } from '../services/folder-linker.serv
|
||||
import { LocalMapsManagerService } from '../services/additional-content/local-maps-manager.service';
|
||||
import { readJSON, writeJSON } from 'fs-extra';
|
||||
import log from "electron-log"
|
||||
import { VersionLinkerAction } from 'renderer/services/version-folder-linker.service';
|
||||
import { VersionFolderLinkerService } from '../services/version-folder-linker.service';
|
||||
|
||||
const ipc = IpcService.getInstance();
|
||||
|
||||
@@ -57,9 +59,7 @@ ipcMain.on("bs-version.clone", async (event, req: IpcRequest<{version: BSVersion
|
||||
|
||||
ipc.on("get-version-full-path", async (req: IpcRequest<BSVersion>, reply) => {
|
||||
const localVersions = BSLocalVersionService.getInstance();
|
||||
reply(from(
|
||||
localVersions.getVersionPath(req.args)
|
||||
));
|
||||
reply(from( localVersions.getVersionPath(req.args) ));
|
||||
});
|
||||
|
||||
ipc.on("relative-version-path-to-full", async (req: IpcRequest<{version: BSVersion, relative: string}>, reply) => {
|
||||
@@ -80,9 +80,9 @@ ipc.on("full-version-path-to-relative", async (req: IpcRequest<{version: BSVersi
|
||||
reply(from(promise));
|
||||
});
|
||||
|
||||
ipc.on("get-linked-folders", async (req: IpcRequest<BSVersion>, reply) => {
|
||||
const localVersions = BSLocalVersionService.getInstance();
|
||||
reply(from(localVersions.getLinkedFolders(req.args)));
|
||||
ipc.on("get-linked-folders", async (req: IpcRequest<{version: BSVersion, options?: { relative?: boolean }}>, reply) => {
|
||||
const versionLinker = VersionFolderLinkerService.getInstance();
|
||||
reply(from(versionLinker.getLinkedFolders(req.args.version, req.args.options)));
|
||||
});
|
||||
|
||||
ipc.on("link-folder", async (req: IpcRequest<{ folder: string, options?: LinkOptions}>, reply) => {
|
||||
@@ -121,6 +121,16 @@ ipc.on("link-folder", async (req: IpcRequest<{ folder: string, options?: LinkOpt
|
||||
|
||||
});
|
||||
|
||||
ipc.on("link-version-folder-action", async (req: IpcRequest<VersionLinkerAction>, reply) => {
|
||||
const versionLinker = VersionFolderLinkerService.getInstance();
|
||||
reply(from(versionLinker.doAction(req.args)));
|
||||
});
|
||||
|
||||
ipc.on("is-version-folder-linked", async (req: IpcRequest<{ version: BSVersion, relativeFolder: string }>, reply) => {
|
||||
const versionLinker = VersionFolderLinkerService.getInstance();
|
||||
reply(from(versionLinker.isFolderLinked(req.args.version, req.args.relativeFolder)));
|
||||
});
|
||||
|
||||
ipc.on("unlink-folder", async (req: IpcRequest<{ folder: string, options?: LinkOptions}>, reply) => {
|
||||
|
||||
req.args.options ??= {};
|
||||
|
||||
@@ -77,15 +77,4 @@ ipcMain.on("open-steam", async (event, request: IpcRequest<void>) => {
|
||||
}).catch((e) => {
|
||||
utils.ipcSend(request.responceChannel, {success: false, error: e});
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on("is-folder-symlink", async (req: IpcRequest<string>, reply) => {
|
||||
const promise = new Promise<boolean>(async resolve => {
|
||||
if(!(await pathExist(req.args))){ return resolve(false); }
|
||||
lstat(req.args, (err, stats) => {
|
||||
if(err){ return resolve(false); }
|
||||
resolve(stats.isSymbolicLink());
|
||||
});
|
||||
});
|
||||
reply(from(promise));
|
||||
});
|
||||
@@ -96,6 +96,7 @@ export class BSLocalVersionService{
|
||||
public async getVersionPath(version: BSVersion): Promise<string>{
|
||||
if(version.steam){ return this.steamService.getGameFolder(BS_APP_ID, "Beat Saber") }
|
||||
if(version.oculus){ return this.oculusService.getGameFolder(OCULUS_BS_DIR); }
|
||||
console.log("getVersionPath", this.getVersionFolder(version), version);
|
||||
return path.join(
|
||||
this.installLocationService.versionsDirectory,
|
||||
this.getVersionFolder(version)
|
||||
|
||||
@@ -69,7 +69,7 @@ export class FolderLinkerService {
|
||||
return symlink(sharedPath, folderPath, "junction");
|
||||
}
|
||||
|
||||
public async unlinkFolder(folderPath: string, options?: LinkOptions): Promise<void> {
|
||||
public async unlinkFolder(folderPath: string, options?: UnlinkOptions): Promise<void> {
|
||||
|
||||
if(!(await this.isFolderSymlink(folderPath))){ return; }
|
||||
await unlinkPath(folderPath);
|
||||
@@ -82,10 +82,14 @@ export class FolderLinkerService {
|
||||
return this.restoreFolder(folderPath);
|
||||
}
|
||||
|
||||
if(options.moveContents === true){
|
||||
return moveFolderContent(sharedPath, folderPath).toPromise().then(() => {});
|
||||
}
|
||||
|
||||
if(options?.keepContents === false){ return; }
|
||||
|
||||
await ensureFolderExist(sharedPath);
|
||||
|
||||
|
||||
return copy(sharedPath, folderPath, { errorOnExist: false, recursive: true });
|
||||
}
|
||||
|
||||
@@ -105,5 +109,9 @@ export class FolderLinkerService {
|
||||
export interface LinkOptions {
|
||||
keepContents?: boolean,
|
||||
intermediateFolder?: string,
|
||||
backup?: boolean
|
||||
}
|
||||
backup?: boolean,
|
||||
}
|
||||
|
||||
export interface UnlinkOptions extends LinkOptions {
|
||||
moveContents?: boolean,
|
||||
};
|
||||
@@ -0,0 +1,111 @@
|
||||
import { getFoldersInFolder, pathExist } from "../helpers/fs.helpers";
|
||||
import path from "path";
|
||||
import { VersionLinkerAction, VersionLinkFolderAction, VersionUnlinkFolderAction } from "renderer/services/version-folder-linker.service";
|
||||
import { BSVersion } from "shared/bs-version.interface";
|
||||
import { LocalMapsManagerService } from "./additional-content/local-maps-manager.service";
|
||||
import { BSLocalVersionService } from "./bs-local-version.service";
|
||||
import { FolderLinkerService, LinkOptions } from "./folder-linker.service";
|
||||
|
||||
export class VersionFolderLinkerService {
|
||||
|
||||
private static instance: VersionFolderLinkerService;
|
||||
|
||||
public static getInstance(): VersionFolderLinkerService{
|
||||
if(!VersionFolderLinkerService.instance){ VersionFolderLinkerService.instance = new VersionFolderLinkerService() }
|
||||
return VersionFolderLinkerService.instance;
|
||||
}
|
||||
|
||||
private readonly localVersion: BSLocalVersionService;
|
||||
private readonly folderLinker: FolderLinkerService;
|
||||
|
||||
private constructor(){
|
||||
this.localVersion = BSLocalVersionService.getInstance();
|
||||
this.folderLinker = FolderLinkerService.getInstance();
|
||||
}
|
||||
|
||||
private specialFolderOption(relativeFolder: string, options: LinkOptions): LinkOptions{
|
||||
if(relativeFolder.includes(LocalMapsManagerService.CUSTOM_LEVELS_FOLDER)){
|
||||
return {...options, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER};
|
||||
}
|
||||
|
||||
if(relativeFolder.includes("UserData")){
|
||||
return { ...options, backup: true };
|
||||
}
|
||||
|
||||
return options ?? {};
|
||||
}
|
||||
|
||||
private async isOtherVersionHaveFolderLinked(relativeFolder: string, ignorePath: string): Promise<boolean>{
|
||||
const versions = await this.localVersion.getInstalledVersions();
|
||||
const versionPaths = (await Promise.allSettled(versions.map(version => this.localVersion.getVersionPath(version)))).reduce((acc, res) => {
|
||||
if(res.status === "fulfilled"){
|
||||
acc.push(res.value);
|
||||
}
|
||||
return acc;
|
||||
}, [] as string[]);
|
||||
|
||||
for(const versionPath of versionPaths){
|
||||
const folderPath = this.relativeToFullPath(versionPath, relativeFolder);
|
||||
if(folderPath === ignorePath){ continue; }
|
||||
if(await this.folderLinker.isFolderSymlink(folderPath)){ console.log(folderPath); return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private relativeToFullPath(parentPath: string, relativePath: string): string{
|
||||
return path.join(parentPath, relativePath);
|
||||
}
|
||||
|
||||
|
||||
public async linkVersionFolder(action: VersionLinkerAction): Promise<boolean>{
|
||||
action.options = this.specialFolderOption(action.relativeFolder, action.options);
|
||||
const versionPath = await this.localVersion.getVersionPath(action.version);
|
||||
const folderPath = this.relativeToFullPath(versionPath, action.relativeFolder);
|
||||
return this.folderLinker.linkFolder(folderPath, action.options).catch(() => false).then(() => true)
|
||||
}
|
||||
|
||||
public async unlinkVersionFolder(action: VersionUnlinkFolderAction): Promise<boolean>{
|
||||
action.options = this.specialFolderOption(action.relativeFolder, action.options);
|
||||
|
||||
const versionPath = await this.localVersion.getVersionPath(action.version);
|
||||
const folderPath = this.relativeToFullPath(versionPath, action.relativeFolder);
|
||||
|
||||
action.options.moveContents = !(await this.isOtherVersionHaveFolderLinked(action.relativeFolder, folderPath));
|
||||
|
||||
return this.folderLinker.unlinkFolder(folderPath, action.options).catch(() => false).then(() => true);
|
||||
}
|
||||
|
||||
public async doAction(action: VersionLinkerAction): Promise<boolean>{
|
||||
if(action.type === "link"){
|
||||
return this.linkVersionFolder(action);
|
||||
}
|
||||
return this.unlinkVersionFolder(action as VersionUnlinkFolderAction);
|
||||
}
|
||||
|
||||
public async isFolderLinked(version: BSVersion, relativeFolder: string): Promise<boolean>{
|
||||
const versionPath = await this.localVersion.getVersionPath(version);
|
||||
const folderPath = this.relativeToFullPath(versionPath, relativeFolder);
|
||||
return this.folderLinker.isFolderSymlink(folderPath);
|
||||
}
|
||||
|
||||
public async getLinkedFolders(version: BSVersion, options?: { relative?: boolean }): Promise<string[]>{
|
||||
const versionPath = await this.localVersion.getVersionPath(version);
|
||||
const [rootFolders, beatSaberDataFolders] = await Promise.all([
|
||||
getFoldersInFolder(versionPath),
|
||||
getFoldersInFolder(path.join(versionPath, "Beat Saber_Data"))
|
||||
]);
|
||||
|
||||
const linkedFolder = await Promise.all([...rootFolders, ...beatSaberDataFolders].map(async folder => {
|
||||
if(!(await this.folderLinker.isFolderSymlink(folder))){ return null; }
|
||||
return folder;
|
||||
}));
|
||||
|
||||
if(options?.relative){
|
||||
return linkedFolder.filter(folder => folder).map(folder => path.relative(versionPath, folder));
|
||||
}
|
||||
|
||||
return linkedFolder.filter(folder => folder);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user