smarter sync

This commit is contained in:
Chris Wanstrath 2026-02-09 21:59:02 -08:00
parent 79a0471383
commit 4a2223d3d7

View File

@ -458,9 +458,8 @@ export async function syncApp() {
console.log(`Syncing ${color.bold(appName)}...`)
// Initial sync: pull remote changes, then push local changes
await pullApp({ force: true, quiet: true })
await pushApp({ quiet: true })
// Initial sync: merge based on mtime, then push merged state
await mergeSync(appName)
const gitignore = loadGitignore(process.cwd())
@ -513,7 +512,7 @@ export async function syncApp() {
for (const line of lines) {
if (!line.startsWith('data: ')) continue
if (pullTimer) clearTimeout(pullTimer)
pullTimer = setTimeout(() => pullApp({ force: true, quiet: true }), 500)
pullTimer = setTimeout(() => mergeSync(appName), 500)
}
}
} finally {
@ -881,6 +880,44 @@ function formatVersion(version: string): string {
return date.toLocaleString()
}
async function mergeSync(appName: string): Promise<void> {
const diff = await getManifestDiff(appName)
if (!diff) return
const { changed, remoteOnly, localManifest, remoteManifest } = diff
if (!remoteManifest) return
// Determine which changed files to pull (remote is newer)
const toPull: string[] = [...remoteOnly]
for (const file of changed) {
const localMtime = new Date(localManifest.files[file]!.mtime).getTime()
const remoteMtime = new Date(remoteManifest.files[file]!.mtime).getTime()
if (remoteMtime > localMtime) {
toPull.push(file)
}
}
// Pull remote-newer and remote-only files
if (toPull.length > 0) {
for (const file of toPull) {
const content = await download(`/api/sync/apps/${appName}/files/${file}`)
if (!content) continue
const fullPath = join(process.cwd(), file)
const dir = dirname(fullPath)
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true })
}
writeFileSync(fullPath, content)
console.log(` ${color.green('↓')} ${file}`)
}
}
// Push merged state to server
await pushApp({ quiet: true })
}
async function getManifestDiff(appName: string): Promise<ManifestDiff | null> {
const localManifest = generateManifest(process.cwd(), appName)
const result = await getManifest(appName)