( originalFile: string, backupFileName: string, originalStatsHint?: Stats, )
| 600 | * Exported for testing. |
| 601 | */ |
| 602 | export async function checkOriginFileChanged( |
| 603 | originalFile: string, |
| 604 | backupFileName: string, |
| 605 | originalStatsHint?: Stats, |
| 606 | ): Promise<boolean> { |
| 607 | const backupPath = resolveBackupPath(backupFileName) |
| 608 | |
| 609 | let originalStats: Stats | null = originalStatsHint ?? null |
| 610 | if (!originalStats) { |
| 611 | try { |
| 612 | originalStats = await stat(originalFile) |
| 613 | } catch (e: unknown) { |
| 614 | if (!isENOENT(e)) return true |
| 615 | } |
| 616 | } |
| 617 | let backupStats: Stats | null = null |
| 618 | try { |
| 619 | backupStats = await stat(backupPath) |
| 620 | } catch (e: unknown) { |
| 621 | if (!isENOENT(e)) return true |
| 622 | } |
| 623 | |
| 624 | return compareStatsAndContent(originalStats, backupStats, async () => { |
| 625 | try { |
| 626 | const [originalContent, backupContent] = await Promise.all([ |
| 627 | readFile(originalFile, 'utf-8'), |
| 628 | readFile(backupPath, 'utf-8'), |
| 629 | ]) |
| 630 | return originalContent !== backupContent |
| 631 | } catch { |
| 632 | // File deleted between stat and read -> treat as changed. |
| 633 | return true |
| 634 | } |
| 635 | }) |
| 636 | } |
| 637 | |
| 638 | /** |
| 639 | * Shared stat/content comparison logic for sync and async change checks. |
no test coverage detected