Add a file or directory to tracking. This registers the file with the repository so it will be included in future changes. Adding a file does NOT create a change - you need to call `record()` for that. # Arguments `path` - Path to the file or directory (relative to repository root) `options` - Options controlling the add operation # Returns Statistics about what was added. # Errors Returns
(
&self,
path: P,
options: TrackingOptions,
)
| 38 | /// repo.add("src/", TrackingOptions::non_recursive())?; |
| 39 | /// ``` |
| 40 | pub fn add<P: AsRef<Path>>( |
| 41 | &self, |
| 42 | path: P, |
| 43 | options: TrackingOptions, |
| 44 | ) -> Result<TrackingStats, RepositoryError> { |
| 45 | let path = path.as_ref(); |
| 46 | let mut stats = TrackingStats::new(); |
| 47 | |
| 48 | // Load ignore rules |
| 49 | let rules = self.ignore_rules(); |
| 50 | |
| 51 | // Check for internal paths and ignore patterns |
| 52 | let abs_path = self.root.join(path); |
| 53 | let is_dir = abs_path.is_dir(); |
| 54 | if should_ignore_with_rules(path, true, is_dir, Some(&rules)) { |
| 55 | return Err(RepositoryError::PathIgnored { |
| 56 | path: path.to_path_buf(), |
| 57 | }); |
| 58 | } |
| 59 | |
| 60 | // Collect files to add (respecting ignore rules) |
| 61 | let files = collect_files_for_tracking_with_rules(&self.root, path, &options, Some(&rules)) |
| 62 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 63 | |
| 64 | if files.is_empty() { |
| 65 | return Ok(stats); |
| 66 | } |
| 67 | |
| 68 | // Don't modify if dry run |
| 69 | if options.dry_run { |
| 70 | for file_path in files { |
| 71 | // Only count files, not directories (directories are implicitly tracked) |
| 72 | let abs_path = self.root.join(&file_path); |
| 73 | if !abs_path.is_dir() { |
| 74 | stats.files_added += 1; |
| 75 | } |
| 76 | } |
| 77 | return Ok(stats); |
| 78 | } |
| 79 | |
| 80 | // Add to tracking |
| 81 | let mut txn = self |
| 82 | .pristine |
| 83 | .write_txn() |
| 84 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 85 | |
| 86 | for file_path in files { |
| 87 | // Normalize path with repo root to handle absolute paths correctly |
| 88 | // (e.g., on macOS where /tmp -> /private/tmp) |
| 89 | let normalized = normalize_path_with_root(&file_path, Some(&self.root)); |
| 90 | let abs_path = self.root.join(&file_path); |
| 91 | |
| 92 | // Skip directories - they are implicitly tracked through their contents |
| 93 | if abs_path.is_dir() { |
| 94 | continue; |
| 95 | } |
| 96 | |
| 97 | // Check if already tracked |