From df6a89af86098b746dd4c34ca8aaf6945846b089 Mon Sep 17 00:00:00 2001 From: "J.T. Sage" Date: Sun, 27 Nov 2022 21:53:24 -0500 Subject: [PATCH] Fail smarter on invalid symlinks, re #17 --- README.md | 13 +++++++++ modAssist_main.js | 67 +++++++++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index ff77c6c6..88e0b09b 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ ___Contents___ - [FSG Mod Assistant](#fsg-mod-assistant) - [What this does](#what-this-does) + - [A Special Note About SymLinks](#a-special-note-about-symlinks) - [What is a Broken Mod?](#what-is-a-broken-mod) - [Usage](#usage) - [Download options](#download-options) @@ -51,6 +52,18 @@ ___Contents___ At it's core functionality, this is a file manager, and it has the ability to edit FS22's `gameSettings.xml` file to set one of your mod collections as the mod location the game reads. __For the security conscious__, it's sole communication with the internet is the self-updater for the program, and pulling a list of modHub mods from a server - all of your mods are tested locally - if you prefer to update manually, you can safely block this app in your firewall - although that will break the "Open on ModHub" button. There is also a portable (no-install) version if you prefer that. +### A Special Note About SymLinks + +One method to keep the size of a mod collection down is to use symlinks - Mod Assist is aware of symlinks, and will treat them much like the game does - like any other mod file. Mod Assist does not have any sort of built in sym link functions, you'll need a third party app or advanced knowledge of the command line to create them. + +When doing file operations + +- `Move`ing a symlink will move the __LINK DESCRIPTOR__ (the linked file remains unchanged) +- `Copy`ing a symlink will copy the __ORIGINAL FILE__ (the linked file is duplicated) +- `Delete`ing a symlink will delete the __LINK DESCRIPTOR__ (the linked file remains unchanged) + +Note that invalid links in your folders will be ignored, however a warning message will be added to the debug log. + ## What is a Broken Mod? - If a mod file is named incorrectly and won't load in the game. diff --git a/modAssist_main.js b/modAssist_main.js index ef473a56..58deca8b 100644 --- a/modAssist_main.js +++ b/modAssist_main.js @@ -1477,38 +1477,48 @@ function fileGetStats(folder, thisFile) { let isFolder = null let date = null let size = null + let error = false - if ( thisFile.isSymbolicLink() ) { - const thisSymLink = fs.readlinkSync(path.join(folder, thisFile.name)) - const thisSymLinkStat = fs.lstatSync(path.join(folder, thisSymLink)) - isFolder = thisSymLinkStat.isDirectory() - date = thisSymLinkStat.ctime + try { + if ( thisFile.isSymbolicLink() ) { + const thisSymLink = fs.readlinkSync(path.join(folder, thisFile.name)) + const thisSymLinkStat = fs.lstatSync(path.join(folder, thisSymLink)) + isFolder = thisSymLinkStat.isDirectory() + date = thisSymLinkStat.ctime - if ( !isFolder ) { size = thisSymLinkStat.size } - } else { - isFolder = thisFile.isDirectory() - } + if ( !isFolder ) { size = thisSymLinkStat.size } + } else { + isFolder = thisFile.isDirectory() + } - if ( ! thisFile.isSymbolicLink() ) { - const theseStats = fs.statSync(path.join(folder, thisFile.name)) - if ( !isFolder ) { size = theseStats.size } - date = theseStats.ctime - - } - if ( isFolder ) { - let bytes = 0 - glob.sync('**', { cwd : path.join(folder, thisFile.name) }).forEach((file) => { - try { - const stats = fs.statSync(path.join(folder, thisFile.name, file)) - if ( stats.isFile() ) { bytes += stats.size } - } catch { /* Do Nothing if we can't read it. */ } - }) - size = bytes + if ( ! thisFile.isSymbolicLink() ) { + const theseStats = fs.statSync(path.join(folder, thisFile.name)) + if ( !isFolder ) { size = theseStats.size } + date = theseStats.ctime + + } + if ( isFolder ) { + let bytes = 0 + glob.sync('**', { cwd : path.join(folder, thisFile.name) }).forEach((file) => { + try { + const stats = fs.statSync(path.join(folder, thisFile.name, file)) + if ( stats.isFile() ) { bytes += stats.size } + } catch { /* Do Nothing if we can't read it. */ } + }) + size = bytes + } + } catch (e) { + log.log.warning(`Unable to stat file ${thisFile.name} in ${folder} : ${e}`, 'file-stat') + isFolder = false + size = 0 + date = new Date(1969, 1, 1, 0, 0, 0, 0) + error = true } return { folder : isFolder, size : size, date : date, + error : error, } } @@ -1557,10 +1567,15 @@ function processModFolders_post(newFolder = false) { return } - modIndex++ - const thisFileStats = fileGetStats(folder, thisFile) + if ( thisFileStats.error ) { + loadingWindow_current() + return + } + + modIndex++ + if ( !thisFileStats.folder && !skipCache ) { const hashString = `${thisFile.name}-${thisFileStats.size}-${thisFileStats.date.toISOString()}` const thisMD5Sum = crypto.createHash('md5').update(hashString).digest('hex')