Fix directory writable check (fs.access not working on Windows)

This commit is contained in:
mikiher 2023-12-14 09:47:18 +02:00
parent 6f6395bad7
commit 8f7a420cca
3 changed files with 30 additions and 15 deletions

View File

@ -3,6 +3,7 @@ const which = require('../libs/which')
const fs = require('../libs/fsExtra') const fs = require('../libs/fsExtra')
const ffbinaries = require('../libs/ffbinaries') const ffbinaries = require('../libs/ffbinaries')
const Logger = require('../Logger') const Logger = require('../Logger')
const fileUtils = require('../utils/fileUtils')
class BinaryManager { class BinaryManager {
@ -64,16 +65,10 @@ class BinaryManager {
async install(binaries) { async install(binaries) {
if (binaries.length == 0) return if (binaries.length == 0) return
Logger.info(`[BinaryManager] Installing binaries: ${binaries.join(', ')}`) Logger.info(`[BinaryManager] Installing binaries: ${binaries.join(', ')}`)
let destination = this.mainInstallPath let destination = await fileUtils.isWritable(this.mainInstallPath) ? this.mainInstallPath : this.altInstallPath
try {
await fs.access(destination, fs.constants.W_OK)
} catch (err) {
destination = this.altInstallPath
}
await ffbinaries.downloadBinaries(binaries, { destination }) await ffbinaries.downloadBinaries(binaries, { destination })
Logger.info(`[BinaryManager] Binaries installed to ${destination}`) Logger.info(`[BinaryManager] Binaries installed to ${destination}`)
} }
} }
module.exports = BinaryManager module.exports = BinaryManager

View File

@ -354,3 +354,22 @@ module.exports.encodeUriPath = (path) => {
const uri = new URL(path, "file://") const uri = new URL(path, "file://")
return uri.pathname 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
}
}

View File

@ -1,6 +1,7 @@
const chai = require('chai') const chai = require('chai')
const sinon = require('sinon') const sinon = require('sinon')
const fs = require('../../../server/libs/fsExtra') const fs = require('../../../server/libs/fsExtra')
const fileUtils = require('../../../server/utils/fileUtils')
const which = require('../../../server/libs/which') const which = require('../../../server/libs/which')
const ffbinaries = require('../../../server/libs/ffbinaries') const ffbinaries = require('../../../server/libs/ffbinaries')
const path = require('path') const path = require('path')
@ -114,19 +115,19 @@ describe('BinaryManager', () => {
}) })
describe('install', () => { describe('install', () => {
let accessStub let isWritableStub
let downloadBinariesStub let downloadBinariesStub
beforeEach(() => { beforeEach(() => {
binaryManager = new BinaryManager() binaryManager = new BinaryManager()
accessStub = sinon.stub(fs, 'access') isWritableStub = sinon.stub(fileUtils, 'isWritable')
downloadBinariesStub = sinon.stub(ffbinaries, 'downloadBinaries') downloadBinariesStub = sinon.stub(ffbinaries, 'downloadBinaries')
binaryManager.mainInstallPath = '/path/to/main/install' binaryManager.mainInstallPath = '/path/to/main/install'
binaryManager.altInstallPath = '/path/to/alt/install' binaryManager.altInstallPath = '/path/to/alt/install'
}) })
afterEach(() => { afterEach(() => {
accessStub.restore() isWritableStub.restore()
downloadBinariesStub.restore() downloadBinariesStub.restore()
}) })
@ -135,19 +136,19 @@ describe('BinaryManager', () => {
await binaryManager.install(binaries) await binaryManager.install(binaries)
expect(accessStub.called).to.be.false expect(isWritableStub.called).to.be.false
expect(downloadBinariesStub.called).to.be.false expect(downloadBinariesStub.called).to.be.false
}) })
it('should install binaries in main install path if has access', async () => { it('should install binaries in main install path if has access', async () => {
const binaries = ['ffmpeg'] const binaries = ['ffmpeg']
const destination = binaryManager.mainInstallPath const destination = binaryManager.mainInstallPath
accessStub.withArgs(destination, fs.constants.W_OK).resolves() isWritableStub.withArgs(destination).resolves(true)
downloadBinariesStub.resolves() downloadBinariesStub.resolves()
await binaryManager.install(binaries) await binaryManager.install(binaries)
expect(accessStub.calledOnce).to.be.true expect(isWritableStub.calledOnce).to.be.true
expect(downloadBinariesStub.calledOnce).to.be.true expect(downloadBinariesStub.calledOnce).to.be.true
expect(downloadBinariesStub.calledWith(binaries, sinon.match({ destination: destination }))).to.be.true expect(downloadBinariesStub.calledWith(binaries, sinon.match({ destination: destination }))).to.be.true
}) })
@ -156,12 +157,12 @@ describe('BinaryManager', () => {
const binaries = ['ffmpeg'] const binaries = ['ffmpeg']
const mainDestination = binaryManager.mainInstallPath const mainDestination = binaryManager.mainInstallPath
const destination = binaryManager.altInstallPath const destination = binaryManager.altInstallPath
accessStub.withArgs(mainDestination, fs.constants.W_OK).rejects() isWritableStub.withArgs(mainDestination).resolves(false)
downloadBinariesStub.resolves() downloadBinariesStub.resolves()
await binaryManager.install(binaries) await binaryManager.install(binaries)
expect(accessStub.calledOnce).to.be.true expect(isWritableStub.calledOnce).to.be.true
expect(downloadBinariesStub.calledOnce).to.be.true expect(downloadBinariesStub.calledOnce).to.be.true
expect(downloadBinariesStub.calledWith(binaries, sinon.match({ destination: destination }))).to.be.true expect(downloadBinariesStub.calledWith(binaries, sinon.match({ destination: destination }))).to.be.true
}) })