diff --git a/server/managers/BinaryManager.js b/server/managers/BinaryManager.js index 98cb79b2..e9aab609 100644 --- a/server/managers/BinaryManager.js +++ b/server/managers/BinaryManager.js @@ -3,6 +3,7 @@ const which = require('../libs/which') const fs = require('../libs/fsExtra') const ffbinaries = require('../libs/ffbinaries') const Logger = require('../Logger') +const fileUtils = require('../utils/fileUtils') class BinaryManager { @@ -64,16 +65,10 @@ class BinaryManager { async install(binaries) { if (binaries.length == 0) return Logger.info(`[BinaryManager] Installing binaries: ${binaries.join(', ')}`) - let destination = this.mainInstallPath - try { - await fs.access(destination, fs.constants.W_OK) - } catch (err) { - destination = this.altInstallPath - } + let destination = await fileUtils.isWritable(this.mainInstallPath) ? this.mainInstallPath : this.altInstallPath await ffbinaries.downloadBinaries(binaries, { destination }) Logger.info(`[BinaryManager] Binaries installed to ${destination}`) } - } module.exports = BinaryManager \ No newline at end of file diff --git a/server/utils/fileUtils.js b/server/utils/fileUtils.js index ebad97db..c929068d 100644 --- a/server/utils/fileUtils.js +++ b/server/utils/fileUtils.js @@ -354,3 +354,22 @@ module.exports.encodeUriPath = (path) => { const uri = new URL(path, "file://") return uri.pathname } + +/** + * Check if directory is writable. + * This method is necessary because fs.access(directory, fs.constants.W_OK) does not work on Windows + * + * @param {string} directory + * @returns {boolean} + */ +module.exports.isWritable = async (directory) => { + try { + const accessTestFile = path.join(directory, 'accessTest') + await fs.writeFile(accessTestFile, '') + await fs.remove(accessTestFile) + return true + } catch (err) { + return false + } +} + diff --git a/test/server/managers/BinaryManager.test.js b/test/server/managers/BinaryManager.test.js index f9cc4df6..b93973e0 100644 --- a/test/server/managers/BinaryManager.test.js +++ b/test/server/managers/BinaryManager.test.js @@ -1,6 +1,7 @@ const chai = require('chai') const sinon = require('sinon') const fs = require('../../../server/libs/fsExtra') +const fileUtils = require('../../../server/utils/fileUtils') const which = require('../../../server/libs/which') const ffbinaries = require('../../../server/libs/ffbinaries') const path = require('path') @@ -114,19 +115,19 @@ describe('BinaryManager', () => { }) describe('install', () => { - let accessStub + let isWritableStub let downloadBinariesStub beforeEach(() => { binaryManager = new BinaryManager() - accessStub = sinon.stub(fs, 'access') + isWritableStub = sinon.stub(fileUtils, 'isWritable') downloadBinariesStub = sinon.stub(ffbinaries, 'downloadBinaries') binaryManager.mainInstallPath = '/path/to/main/install' binaryManager.altInstallPath = '/path/to/alt/install' }) afterEach(() => { - accessStub.restore() + isWritableStub.restore() downloadBinariesStub.restore() }) @@ -135,19 +136,19 @@ describe('BinaryManager', () => { await binaryManager.install(binaries) - expect(accessStub.called).to.be.false + expect(isWritableStub.called).to.be.false expect(downloadBinariesStub.called).to.be.false }) it('should install binaries in main install path if has access', async () => { const binaries = ['ffmpeg'] const destination = binaryManager.mainInstallPath - accessStub.withArgs(destination, fs.constants.W_OK).resolves() + isWritableStub.withArgs(destination).resolves(true) downloadBinariesStub.resolves() await binaryManager.install(binaries) - expect(accessStub.calledOnce).to.be.true + expect(isWritableStub.calledOnce).to.be.true expect(downloadBinariesStub.calledOnce).to.be.true expect(downloadBinariesStub.calledWith(binaries, sinon.match({ destination: destination }))).to.be.true }) @@ -156,12 +157,12 @@ describe('BinaryManager', () => { const binaries = ['ffmpeg'] const mainDestination = binaryManager.mainInstallPath const destination = binaryManager.altInstallPath - accessStub.withArgs(mainDestination, fs.constants.W_OK).rejects() + isWritableStub.withArgs(mainDestination).resolves(false) downloadBinariesStub.resolves() await binaryManager.install(binaries) - expect(accessStub.calledOnce).to.be.true + expect(isWritableStub.calledOnce).to.be.true expect(downloadBinariesStub.calledOnce).to.be.true expect(downloadBinariesStub.calledWith(binaries, sinon.match({ destination: destination }))).to.be.true })