Detect changes between the working copy and pristine state. This is the main entry point for change detection. It collects files from both the pristine database and working copy, then compares them to find additions, deletions, modifications, and moves. # Arguments `working_copy` - Working copy interface `tracked_paths` - List of tracked file paths from pristine `options` - Detection options #
(
working_copy: &W,
tracked_paths: &[String],
options: &DetectionOptions,
)
| 324 | /// } |
| 325 | /// ``` |
| 326 | pub fn detect_changes_simple<W>( |
| 327 | working_copy: &W, |
| 328 | tracked_paths: &[String], |
| 329 | options: &DetectionOptions, |
| 330 | ) -> DetectionResult |
| 331 | where |
| 332 | W: WorkingCopyRead, |
| 333 | { |
| 334 | let mut result = DetectionResult::new(); |
| 335 | let prefix = options.get_prefix().unwrap_or(""); |
| 336 | |
| 337 | // Build set of tracked paths for quick lookup |
| 338 | let tracked_set: HashSet<&str> = tracked_paths.iter().map(|s| s.as_str()).collect(); |
| 339 | |
| 340 | // Collect working copy files |
| 341 | let working_files = match working_copy.walk_files(prefix) { |
| 342 | Ok(files) => files, |
| 343 | Err(e) => { |
| 344 | result.add_error(format!("Failed to walk working copy: {}", e)); |
| 345 | return result; |
| 346 | } |
| 347 | }; |
| 348 | |
| 349 | let working_set: HashSet<&str> = working_files.iter().map(|s| s.as_str()).collect(); |
| 350 | |
| 351 | // Find added files (in working copy but not tracked) |
| 352 | for path in &working_files { |
| 353 | result.increment_scanned(); |
| 354 | if !tracked_set.contains(path.as_str()) { |
| 355 | // Check prefix filter |
| 356 | if prefix.is_empty() || path.starts_with(prefix) { |
| 357 | let file = DetectedFile::added(path); |
| 358 | result.add_added(file); |
| 359 | } |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | // Find deleted files (tracked but not in working copy) |
| 364 | for path in tracked_paths { |
| 365 | if !working_set.contains(path.as_str()) { |
| 366 | // Check prefix filter |
| 367 | if prefix.is_empty() || path.starts_with(prefix) { |
| 368 | let file = DetectedFile::deleted(path); |
| 369 | result.add_deleted(file); |
| 370 | } |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | // Files in both sets exist in working copy and are tracked. |
| 375 | // Content comparison requires pristine content retrieval, which is |
| 376 | // handled by the caller using record_modified_file() with the |
| 377 | // retrieved pristine content. Here we just identify which files |
| 378 | // need comparison. |
| 379 | for path in tracked_paths { |
| 380 | if working_set.contains(path.as_str()) { |
| 381 | // Check prefix filter |
| 382 | if prefix.is_empty() || path.starts_with(prefix) { |
| 383 | // Files present in both sets are tracked as unchanged here. |