a very good jj gui
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add abandon revision and commit recency commands

+90 -1
+90 -1
apps/desktop/src-tauri/src/repo/jj.rs
··· 3 3 use jj_lib::commit::Commit; 4 4 use jj_lib::config::ConfigSource; 5 5 use jj_lib::merged_tree::MergedTree; 6 - use jj_lib::object_id::{HexPrefix, PrefixResolution}; 6 + use jj_lib::object_id::{HexPrefix, ObjectId, PrefixResolution}; 7 + use jj_lib::op_walk; 7 8 use jj_lib::repo::{Repo, StoreFactories}; 8 9 use jj_lib::repo_path::RepoPath; 9 10 use jj_lib::settings::UserSettings; 10 11 use jj_lib::workspace::{Workspace, default_working_copy_factories}; 12 + use std::collections::HashMap; 11 13 use std::path::Path; 12 14 use tokio::io::AsyncReadExt; 13 15 ··· 234 236 Ok(()) 235 237 } 236 238 239 + pub fn abandon_revision(&mut self, change_id: &str) -> Result<()> { 240 + let repo = self.workspace.repo_loader().load_at_head()?; 241 + let mut tx = repo.start_transaction(); 242 + 243 + // Resolve change ID to commit 244 + let commit_id = self.resolve_change_id(repo.as_ref(), change_id)?; 245 + let commit = repo.store().get_commit(&commit_id) 246 + .map_err(|e| anyhow::anyhow!("Failed to get commit: {}", e))?; 247 + 248 + // Get the current working copy info before changes 249 + let wc_commit_id = repo 250 + .view() 251 + .get_wc_commit_id(self.workspace.workspace_name()) 252 + .cloned(); 253 + let is_abandoning_wc = wc_commit_id.as_ref() == Some(commit.id()); 254 + 255 + // Record the commit as abandoned 256 + tx.repo_mut().record_abandoned_commit(&commit); 257 + 258 + // Rebase descendants (this handles moving children to the parent) 259 + tx.repo_mut().rebase_descendants()?; 260 + 261 + // If we abandoned the working copy, check out the parent 262 + if is_abandoning_wc { 263 + let parent_id = commit.parent_ids().first().cloned() 264 + .context("Abandoned commit has no parent")?; 265 + let parent_commit = repo.store().get_commit(&parent_id)?; 266 + 267 + // Set the parent as the new working copy 268 + let workspace_name = self.workspace.workspace_name().to_owned(); 269 + tx.repo_mut() 270 + .set_wc_commit(workspace_name, parent_id.clone()) 271 + .context("Failed to set working copy commit")?; 272 + 273 + // Finalize transaction before checkout 274 + let new_repo = tx.commit("abandon")?; 275 + let operation_id = new_repo.operation().id().clone(); 276 + 277 + // Check out the parent commit 278 + let old_tree_id = commit.tree_id().clone(); 279 + self.workspace 280 + .check_out(operation_id, Some(&old_tree_id), &parent_commit) 281 + .context("Failed to check out parent commit")?; 282 + } else { 283 + // Finalize transaction 284 + tx.commit("abandon")?; 285 + } 286 + 287 + Ok(()) 288 + } 289 + 237 290 pub fn edit_revision(&mut self, change_id: String) -> Result<()> { 238 291 let repo = self.workspace.repo_loader().load_at_head()?; 239 292 let mut tx = repo.start_transaction(); ··· 267 320 .context("Failed to check out commit")?; 268 321 269 322 Ok(()) 323 + } 324 + 325 + /// Walk the operation log to find when each commit was last the working copy. 326 + /// Returns a map of commit_id (hex) -> timestamp_millis. 327 + /// This is used to determine "recency" for branch ordering. 328 + pub fn get_commit_recency(&self, limit: usize) -> Result<HashMap<String, i64>> { 329 + let repo = self.workspace.repo_loader().load_at_head()?; 330 + let current_op = repo.operation(); 331 + let workspace_name = self.workspace.workspace_name(); 332 + 333 + let mut recency: HashMap<String, i64> = HashMap::new(); 334 + 335 + // Walk operations from newest to oldest 336 + let op_iter = op_walk::walk_ancestors(std::slice::from_ref(current_op)); 337 + 338 + for (idx, op_result) in op_iter.enumerate() { 339 + if idx >= limit { 340 + break; 341 + } 342 + 343 + let op = op_result.context("Failed to load operation")?; 344 + let metadata = op.metadata(); 345 + let timestamp_millis = metadata.time.start.timestamp.0; 346 + 347 + // Get the view for this operation to see what was the WC 348 + let view = op.view().context("Failed to load operation view")?; 349 + 350 + // Check what commit was the working copy at this operation 351 + if let Some(wc_commit_id) = view.wc_commit_ids().get(workspace_name) { 352 + let commit_hex = wc_commit_id.hex(); 353 + // Only record the first (most recent) occurrence 354 + recency.entry(commit_hex).or_insert(timestamp_millis); 355 + } 356 + } 357 + 358 + Ok(recency) 270 359 } 271 360 }