Fix permission issues in embed/merge

This commit is contained in:
mikiher 2024-07-29 20:19:58 +03:00
parent 6183001fca
commit 294490f814
4 changed files with 105 additions and 34 deletions

View file

@ -4,7 +4,7 @@ const ffmpgegUtils = require('../libs/fluentFfmpeg/utils')
const fs = require('../libs/fsExtra')
const Path = require('path')
const Logger = require('../Logger')
const { filePathToPOSIX } = require('./fileUtils')
const { filePathToPOSIX, copyToExisting } = require('./fileUtils')
const LibraryItem = require('../objects/LibraryItem')
function escapeSingleQuotes(path) {
@ -250,11 +250,12 @@ module.exports.writeFFMetadataFile = writeFFMetadataFile
* @param {string} metadataFilePath - Path to the ffmetadata file.
* @param {number} track - The track number to embed in the audio file.
* @param {string} mimeType - The MIME type of the audio file.
* @param {Ffmpeg} ffmpeg - The Ffmpeg instance to use (optional). Used for dependency injection in tests.
* @param {function(number): void|null} progressCB - A callback function to report progress.
* @param {Ffmpeg} ffmpeg - The Ffmpeg instance to use (optional). Used for dependency injection in tests.
* @param {function(string, string): Promise<void>} copyFunc - The function to use for copying files (optional). Used for dependency injection in tests.
* @returns {Promise<void>} A promise that resolves if the operation is successful, rejects otherwise.
*/
async function addCoverAndMetadataToFile(audioFilePath, coverFilePath, metadataFilePath, track, mimeType, progressCB = null, ffmpeg = Ffmpeg()) {
async function addCoverAndMetadataToFile(audioFilePath, coverFilePath, metadataFilePath, track, mimeType, progressCB = null, ffmpeg = Ffmpeg(), copyFunc = copyToExisting) {
const isMp4 = mimeType === 'audio/mp4'
const isMp3 = mimeType === 'audio/mpeg'
@ -316,7 +317,8 @@ async function addCoverAndMetadataToFile(audioFilePath, coverFilePath, metadataF
Logger.debug('[ffmpegHelpers] ffmpeg stderr:', stderr)
Logger.debug('[ffmpegHelpers] Moving temp file to audio file path:', `"${tempFilePath}"`, '->', `"${audioFilePath}"`)
try {
await fs.move(tempFilePath, audioFilePath, { overwrite: true })
await copyFunc(tempFilePath, audioFilePath)
await fs.remove(tempFilePath)
resolve()
} catch (error) {
Logger.error(`[ffmpegHelpers] Failed to move temp file to audio file path: "${tempFilePath}" -> "${audioFilePath}"`, error)

View file

@ -464,3 +464,46 @@ module.exports.getDirectoriesInPath = async (dirPath, level) => {
return []
}
}
/**
* Copies a file from the source path to an existing destination path, preserving the destination's permissions.
*
* @param {string} srcPath - The path of the source file.
* @param {string} destPath - The path of the existing destination file.
* @returns {Promise<void>} A promise that resolves when the file has been successfully copied.
* @throws {Error} If there is an error reading the source file or writing the destination file.
*/
async function copyToExisting(srcPath, destPath) {
return new Promise((resolve, reject) => {
// Create a readable stream from the source file
const readStream = fs.createReadStream(srcPath)
// Create a writable stream to the destination file
const writeStream = fs.createWriteStream(destPath, { flags: 'w' })
// Pipe the read stream to the write stream
readStream.pipe(writeStream)
// Handle the end of the stream
writeStream.on('finish', () => {
Logger.debug(`[copyToExisting] Successfully copied file from ${srcPath} to ${destPath}`)
resolve()
})
// Handle errors
readStream.on('error', (error) => {
Logger.error(`[copyToExisting] Error reading from source file ${srcPath}: ${error.message}`)
readStream.close()
writeStream.close()
reject(error)
})
writeStream.on('error', (error) => {
Logger.error(`[copyToExisting] Error writing to destination file ${destPath}: ${error.message}`)
readStream.close()
writeStream.close()
reject(error)
})
})
}
module.exports.copyToExisting = copyToExisting