diff options
| author | soryu <soryu@soryu.co> | 2026-01-26 18:45:36 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-01-26 18:54:32 +0000 |
| commit | 904a2efa7d39705215b8312f74e2e1c0a38bab27 (patch) | |
| tree | 2fc9b94169fcb80836cc42137dd950e0cafb1f0e /makima/src/daemon/task | |
| parent | cb4f2fc40dbabb40de948512eee74c7e46264665 (diff) | |
| download | soryu-904a2efa7d39705215b8312f74e2e1c0a38bab27.tar.gz soryu-904a2efa7d39705215b8312f74e2e1c0a38bab27.zip | |
Implement core patch export system
Add functionality to create uncompressed, human-readable git patches
for export. This enables users to generate patches that can be manually
applied or shared, without the compression used for internal checkpoints.
Changes:
- Add ExportPatchResult struct with patch content, file count, and line stats
- Add create_export_patch() function that generates diffs against a base SHA
- Add get_head_sha() utility function
- Add parse_diff_stat() helper to extract line counts from git output
- Add CreateExportPatch command to daemon protocol
- Add ExportPatchCreated response message to protocol
- Add handler in task manager to process export patch requests
- Add server-side handling to broadcast patch results to UI
The export patch system automatically finds the merge-base when no base
SHA is provided, trying upstream tracking branch first, then common
default branches (origin/main, origin/master, main, master).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/src/daemon/task')
| -rw-r--r-- | makima/src/daemon/task/manager.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/makima/src/daemon/task/manager.rs b/makima/src/daemon/task/manager.rs index 74a37bf..f933111 100644 --- a/makima/src/daemon/task/manager.rs +++ b/makima/src/daemon/task/manager.rs @@ -1987,6 +1987,10 @@ impl TaskManager { tracing::info!(source_dir = ?source_dir, "Inheriting git config"); self.handle_inherit_git_config(source_dir).await?; } + DaemonCommand::CreateExportPatch { task_id, base_sha } => { + tracing::info!(task_id = %task_id, base_sha = ?base_sha, "Creating export patch"); + self.handle_create_export_patch(task_id, base_sha).await?; + } DaemonCommand::RestartDaemon => { tracing::info!("Received restart command from server, initiating daemon restart..."); // Shutdown all running tasks gracefully @@ -2707,6 +2711,86 @@ impl TaskManager { Ok(()) } + /// Handle CreateExportPatch command. + /// + /// Creates an uncompressed, human-readable git patch for export. + async fn handle_create_export_patch( + &self, + task_id: Uuid, + base_sha: Option<String>, + ) -> Result<(), DaemonError> { + // Get task's worktree path + let worktree_result = self.get_task_worktree_path(task_id).await; + + let msg = match worktree_result { + Ok(worktree_path) => { + // Create the export patch + match storage::create_export_patch(&worktree_path, base_sha.as_deref()).await { + Ok(result) => { + tracing::info!( + task_id = %task_id, + files_count = result.files_count, + lines_added = result.lines_added, + lines_removed = result.lines_removed, + base_commit_sha = %result.base_commit_sha, + "Export patch created successfully" + ); + + DaemonMessage::ExportPatchCreated { + task_id, + success: true, + patch_content: Some(result.patch_content), + files_count: Some(result.files_count), + lines_added: Some(result.lines_added), + lines_removed: Some(result.lines_removed), + base_commit_sha: Some(result.base_commit_sha), + error: None, + } + } + Err(e) => { + tracing::warn!( + task_id = %task_id, + error = %e, + "Failed to create export patch" + ); + + DaemonMessage::ExportPatchCreated { + task_id, + success: false, + patch_content: None, + files_count: None, + lines_added: None, + lines_removed: None, + base_commit_sha: None, + error: Some(e.to_string()), + } + } + } + } + Err(e) => { + tracing::warn!( + task_id = %task_id, + error = %e, + "Failed to get worktree path for export patch" + ); + + DaemonMessage::ExportPatchCreated { + task_id, + success: false, + patch_content: None, + files_count: None, + lines_added: None, + lines_removed: None, + base_commit_sha: None, + error: Some(format!("Task not found or has no worktree: {}", e)), + } + } + }; + + let _ = self.ws_tx.send(msg).await; + Ok(()) + } + /// Handle ReadRepoFile command. /// /// Reads a file from a repository on the daemon's filesystem and sends |
