Restore workspace to a specific checkpoint
(&self, conversation: &mut ConversationState, tag: &str, hard: bool)
| 205 | |
| 206 | /// Restore workspace to a specific checkpoint |
| 207 | pub fn restore(&self, conversation: &mut ConversationState, tag: &str, hard: bool) -> Result<()> { |
| 208 | let checkpoint = self.get_checkpoint(tag)?; |
| 209 | |
| 210 | if hard { |
| 211 | // Hard: reset the whole work-tree to the tag |
| 212 | let output = run_git(&self.shadow_repo_path, Some(&self.work_tree_path), &[ |
| 213 | "reset", "--hard", tag, |
| 214 | ])?; |
| 215 | if !output.status.success() { |
| 216 | bail!( |
| 217 | "Failed to restore checkpoint: {}", |
| 218 | String::from_utf8_lossy(&output.stderr) |
| 219 | ); |
| 220 | } |
| 221 | } else { |
| 222 | // Soft: only restore tracked files. If the tag is an empty tree, this is a no-op. |
| 223 | if !self.tag_has_any_paths(tag)? { |
| 224 | // Nothing tracked in this checkpoint -> nothing to restore; treat as success. |
| 225 | conversation.restore_to_checkpoint(checkpoint)?; |
| 226 | return Ok(()); |
| 227 | } |
| 228 | // Use checkout against work-tree |
| 229 | let output = run_git(&self.shadow_repo_path, Some(&self.work_tree_path), &[ |
| 230 | "checkout", tag, "--", ".", |
| 231 | ])?; |
| 232 | if !output.status.success() { |
| 233 | bail!( |
| 234 | "Failed to restore checkpoint: {}", |
| 235 | String::from_utf8_lossy(&output.stderr) |
| 236 | ); |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | // Restore conversation history |
| 241 | conversation.restore_to_checkpoint(checkpoint)?; |
| 242 | |
| 243 | Ok(()) |
| 244 | } |
| 245 | |
| 246 | /// Return true iff the given tag/tree has any tracked paths. |
| 247 | fn tag_has_any_paths(&self, tag: &str) -> eyre::Result<bool> { |
no test coverage detected