Files
upload-gltf/lib/diff-files.ts
T

65 lines
2.1 KiB
TypeScript

import { MODEL_EXTENSIONS } from './constants'
import type { FileChange, PushFile } from './types'
interface DiffResult {
fileChanges: Map<string, FileChange>
changedFilesToPush: PushFile[]
deletedFileNames: string[]
deletePaths: string[]
}
/**
* Classify each file as new, changed, or unchanged by comparing against
* the remote file map.
*
* Rules:
* - Models: always re-pushed, but marked as unchanged when the remote file exists.
* - Textures: compared by size (not compressed, reliable).
* - Orphan remote files: classified as deletions.
*/
export function classifyFileChanges(
filesToPush: PushFile[],
remoteFileMap: Map<string, number>,
folderPath: string,
): DiffResult {
const fileChanges = new Map<string, FileChange>()
const changedFilesToPush: PushFile[] = []
for (const f of filesToPush) {
const filename = f.path.split('/').pop() ?? ''
const ext = filename.slice(filename.lastIndexOf('.')).toLowerCase()
const isModel = MODEL_EXTENSIONS.has(ext)
if (isModel) {
const remoteSize = remoteFileMap.get(filename.toLowerCase())
fileChanges.set(filename.toLowerCase(), remoteSize === undefined ? 'new' : 'unchanged')
changedFilesToPush.push(f)
} else {
const localSize = Buffer.from(f.contentBase64, 'base64').length
const remoteSize = remoteFileMap.get(filename.toLowerCase())
if (remoteSize === undefined) {
fileChanges.set(filename.toLowerCase(), 'new')
changedFilesToPush.push(f)
} else if (remoteSize !== localSize) {
fileChanges.set(filename.toLowerCase(), 'changed')
changedFilesToPush.push(f)
} else {
fileChanges.set(filename.toLowerCase(), 'unchanged')
}
}
}
const newFileNames = new Set(filesToPush.map((f) => (f.path.split('/').pop() ?? '').toLowerCase()))
const deletedFileNames: string[] = []
const deletePaths: string[] = []
for (const [name] of remoteFileMap) {
if (!newFileNames.has(name)) {
deletedFileNames.push(name)
deletePaths.push(`${folderPath}/${name}`)
}
}
return { fileChanges, changedFilesToPush, deletedFileNames, deletePaths }
}