Skip to content

Commit

Permalink
Fix handling of file moves from root folder to sub folder and back
Browse files Browse the repository at this point in the history
  • Loading branch information
mikiher committed Mar 23, 2024
1 parent 1bee082 commit 68276fe
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 8 deletions.
2 changes: 1 addition & 1 deletion server/scanner/LibraryItemScanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class LibraryItemScanner {

const libraryItemPath = updateLibraryItemDetails?.path || fileUtils.filePathToPOSIX(libraryItem.path)
const folder = library.libraryFolders[0]
const libraryItemScanData = await this.getLibraryItemScanData(libraryItemPath, library, folder, false)
const libraryItemScanData = await this.getLibraryItemScanData(libraryItemPath, library, folder, updateLibraryItemDetails?.isFile || false)

let libraryItemDataUpdated = await libraryItemScanData.checkLibraryItemData(libraryItem, scanLogger)

Expand Down
75 changes: 68 additions & 7 deletions server/scanner/LibraryScanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,11 @@ class LibraryScanner {
let libraryItemData = libraryItemDataFound.find(lid => lid.path === existingLibraryItem.path)
if (!libraryItemData) {
// Fallback to finding matching library item with matching inode value
libraryItemData = libraryItemDataFound.find(lid => lid.ino === existingLibraryItem.ino)
libraryItemData = libraryItemDataFound.find(lid =>
ItemToItemInoMatch(lid, existingLibraryItem) ||
ItemToFileInoMatch(lid, existingLibraryItem) ||
ItemToFileInoMatch(existingLibraryItem, lid)
)
if (libraryItemData) {
libraryScan.addLog(LogLevel.INFO, `Library item with path "${existingLibraryItem.path}" was not found, but library item inode "${existingLibraryItem.ino}" was found at path "${libraryItemData.path}"`)
}
Expand Down Expand Up @@ -522,23 +526,25 @@ class LibraryScanner {

// Check if book dir group is already an item
let existingLibraryItem = await Database.libraryItemModel.findOneOld({
libraryId: library.id,
path: potentialChildDirs
})

let updatedLibraryItemDetails = {}
if (!existingLibraryItem) {
const dirIno = await fileUtils.getIno(fullPath)
existingLibraryItem = await Database.libraryItemModel.findOneOld({
ino: dirIno
})
const isSingleMedia = isSingleMediaFile(fileUpdateGroup, itemDir)
existingLibraryItem =
await findLibraryItemByItemToItemInoMatch(library.id, fullPath) ||
await findLibraryItemByItemToFileInoMatch(library.id, fullPath, isSingleMedia) ||
await findLibraryItemByFileToItemInoMatch(library.id, fullPath, isSingleMedia, fileUpdateGroup[itemDir])
if (existingLibraryItem) {
Logger.debug(`[LibraryScanner] scanFolderUpdates: Library item found by inode value=${dirIno}. "${existingLibraryItem.relPath} => ${itemDir}"`)
// Update library item paths for scan
existingLibraryItem.path = fullPath
existingLibraryItem.relPath = itemDir
updatedLibraryItemDetails.path = fullPath
updatedLibraryItemDetails.relPath = itemDir
updatedLibraryItemDetails.libraryFolderId = folder.id
updatedLibraryItemDetails.isFile = isSingleMedia
}
}
if (existingLibraryItem) {
Expand All @@ -555,7 +561,6 @@ class LibraryScanner {
continue
}
}

// Scan library item for updates
Logger.debug(`[LibraryScanner] Folder update for relative path "${itemDir}" is in library item "${existingLibraryItem.media.metadata.title}" - scan for updates`)
itemGroupingResults[itemDir] = await LibraryItemScanner.scanLibraryItem(existingLibraryItem.id, updatedLibraryItemDetails)
Expand Down Expand Up @@ -595,6 +600,14 @@ class LibraryScanner {
}
module.exports = new LibraryScanner()

function ItemToFileInoMatch(libraryItem1, libraryItem2) {
return libraryItem1.isFile && libraryItem2.libraryFiles.some(lf => lf.ino === libraryItem1.ino)
}

function ItemToItemInoMatch(libraryItem1, libraryItem2) {
return libraryItem1.ino === libraryItem2.ino
}

function hasAudioFiles(fileUpdateGroup, itemDir) {
return isSingleMediaFile(fileUpdateGroup, itemDir) ?
scanUtils.checkFilepathIsAudioFile(fileUpdateGroup[itemDir]) :
Expand All @@ -604,3 +617,51 @@ function hasAudioFiles(fileUpdateGroup, itemDir) {
function isSingleMediaFile(fileUpdateGroup, itemDir) {
return itemDir === fileUpdateGroup[itemDir]
}

async function findLibraryItemByItemToItemInoMatch(libraryId, fullPath) {
const ino = await fileUtils.getIno(fullPath)
if (!ino) return null
const existingLibraryItem = await Database.libraryItemModel.findOneOld({
libraryId: libraryId,
ino: ino
})
if (existingLibraryItem)
Logger.debug(`[LibraryScanner] Found library item with matching inode "${ino}" at path "${existingLibraryItem.path}"`)
return existingLibraryItem
}

async function findLibraryItemByItemToFileInoMatch(libraryId, fullPath, isSingleMedia) {
if (!isSingleMedia) return null
// check if it was moved from another folder by comparing the ino to the library files
const ino = await fileUtils.getIno(fullPath)
if (!ino) return null
const existingLibraryItem = await Database.libraryItemModel.findOneOld({
libraryId: libraryId,
libraryFiles: {
[ sequelize.Op.substring ]: ino
}
})
if (existingLibraryItem)
Logger.debug(`[LibraryScanner] Found library item with a library file matching inode "${ino}" at path "${existingLibraryItem.path}"`)
return existingLibraryItem
}

async function findLibraryItemByFileToItemInoMatch(libraryId, fullPath, isSingleMedia, itemFiles) {
if (isSingleMedia) return null
// check if it was moved from the root folder by comparing the ino to the ino of the scanned files
let itemFileInos = []
for (const itemFile of itemFiles) {
const ino = await fileUtils.getIno(Path.posix.join(fullPath, itemFile))
if (ino) itemFileInos.push(ino)
}
if (!itemFileInos.length) return null
const existingLibraryItem = await Database.libraryItemModel.findOneOld({
libraryId: libraryId,
ino: {
[ sequelize.Op.in ] : itemFileInos
}
})
if (existingLibraryItem)
Logger.debug(`[LibraryScanner] Found library item with inode matching one of "${itemFileInos.join(',')}" at path "${existingLibraryItem.path}"`)
return existingLibraryItem
}

0 comments on commit 68276fe

Please sign in to comment.