diff --git a/src/cli/commands/sync.ts b/src/cli/commands/sync.ts index 197b4e5..cd5fa99 100644 --- a/src/cli/commands/sync.ts +++ b/src/cli/commands/sync.ts @@ -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 { + 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 { const localManifest = generateManifest(process.cwd(), appName) const result = await getManifest(appName)