- try to not force `clone_from()` into move semantics unless necessary
Unified · Split
| @@ -172,10 +172,9 @@ where · 171 unmodified lines | ||
| 172 | 172 | if more_than_one_parent { |
| 173 | 173 | // None of the changes affected the file we’re currently blaming. |
| 174 | 174 | // Copy blame to parent. |
| 175 | − hunks_to_blame = hunks_to_blame | |
| 176 | − .into_iter() | |
| 177 | − .map(|unblamed_hunk| unblamed_hunk.clone_blame(suspect, parent_id)) | |
| 178 | − .collect(); | |
| 175 | + for unblamed_hunk in &mut hunks_to_blame { | |
| 176 | + unblamed_hunk.clone_blame(suspect, parent_id); | |
| 177 | + } | |
| 179 | 178 | } else { |
| 180 | 179 | pass_blame_from_to(suspect, parent_id, &mut hunks_to_blame); |
| 181 | 180 | } |
| @@ -202,26 +201,20 @@ where · 20 unmodified lines | ||
| 202 | 201 | } |
| 203 | 202 | } |
| 204 | 203 | |
| 205 | − hunks_to_blame = hunks_to_blame | |
| 206 | − .into_iter() | |
| 207 | − .filter_map(|mut unblamed_hunk| { | |
| 208 | − if unblamed_hunk.suspects.len() == 1 { | |
| 209 | − if let Some(entry) = BlameEntry::from_unblamed_hunk(&unblamed_hunk, suspect) { | |
| 210 | − // At this point, we have copied blame for every hunk to a parent. Hunks | |
| 211 | − // that have only `suspect` left in `suspects` have not passed blame to any | |
| 212 | − // parent and so they can be converted to a `BlameEntry` and moved to | |
| 213 | − // `out`. | |
| 214 | − out.push(entry); | |
| 215 | − | |
| 216 | − return None; | |
| 217 | − } | |
| 204 | + hunks_to_blame.retain_mut(|unblamed_hunk| { | |
| 205 | + if unblamed_hunk.suspects.len() == 1 { | |
| 206 | + if let Some(entry) = BlameEntry::from_unblamed_hunk(&unblamed_hunk, suspect) { | |
| 207 | + // At this point, we have copied blame for every hunk to a parent. Hunks | |
| 208 | + // that have only `suspect` left in `suspects` have not passed blame to any | |
| 209 | + // parent, and so they can be converted to a `BlameEntry` and moved to | |
| 210 | + // `out`. | |
| 211 | + out.push(entry); | |
| 212 | + return false; | |
| 218 | 213 | } |
| 219 | − | |
| 220 | − unblamed_hunk.remove_blame(suspect); | |
| 221 | − | |
| 222 | − Some(unblamed_hunk) | |
| 223 | − }) | |
| 224 | − .collect(); | |
| 214 | + } | |
| 215 | + unblamed_hunk.remove_blame(suspect); | |
| 216 | + true | |
| 217 | + }); | |
| 225 | 218 | |
| 226 | 219 | // This block asserts that line ranges for each suspect never overlap. If they did overlap |
| 227 | 220 | // this would mean that the same line in a *Source File* would map to more than one line in |
| @@ -66,7 +66,7 @@ fn process_change( · 65 unmodified lines | ||
| 66 | 66 | |
| 67 | 67 | // Nothing to do with `hunk` except shifting it, |
| 68 | 68 | // but `unchanged` needs to be checked against the next hunk to catch up. |
| 69 | − new_hunks_to_blame.push(hunk.clone_blame(suspect, parent).shift_by(parent, *offset)); | |
| 69 | + new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset)); | |
| 70 | 70 | (None, Some(Change::Unchanged(unchanged))) |
| 71 | 71 | } |
| 72 | 72 | (false, false) => { |
| @@ -95,7 +95,7 @@ fn process_change( · 22 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | // Nothing to do with `hunk` except shifting it, |
| 97 | 97 | // but `unchanged` needs to be checked against the next hunk to catch up. |
| 98 | − new_hunks_to_blame.push(hunk.clone_blame(suspect, parent).shift_by(parent, *offset)); | |
| 98 | + new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset)); | |
| 99 | 99 | (None, Some(Change::Unchanged(unchanged))) |
| 100 | 100 | } |
| 101 | 101 | } |
| @@ -125,7 +125,7 @@ fn process_change( · 23 unmodified lines | ||
| 125 | 125 | } |
| 126 | 126 | Either::Right((before, after)) => { |
| 127 | 127 | // requeue the left side `before` after offsetting it… |
| 128 | − new_hunks_to_blame.push(before.clone_blame(suspect, parent).shift_by(parent, *offset)); | |
| 128 | + new_hunks_to_blame.push(before.cloned_blame(suspect, parent).shift_by(parent, *offset)); | |
| 129 | 129 | // …and treat `after` as `new_hunk`, which contains the `added` range. |
| 130 | 130 | after |
| 131 | 131 | } |
| @@ -162,7 +162,7 @@ fn process_change( · 30 unmodified lines | ||
| 162 | 162 | Either::Left(hunk) => hunk, |
| 163 | 163 | Either::Right((before, after)) => { |
| 164 | 164 | // Keep looking for the left side of the unblamed portion. |
| 165 | − new_hunks_to_blame.push(before.clone_blame(suspect, parent).shift_by(parent, *offset)); | |
| 165 | + new_hunks_to_blame.push(before.cloned_blame(suspect, parent).shift_by(parent, *offset)); | |
| 166 | 166 | after |
| 167 | 167 | } |
| 168 | 168 | }; |
| @@ -220,7 +220,7 @@ fn process_change( · 51 unmodified lines | ||
| 220 | 220 | // <----> (added) |
| 221 | 221 | |
| 222 | 222 | // Retry `hunk` once there is overlapping changes to process. |
| 223 | − new_hunks_to_blame.push(hunk.clone_blame(suspect, parent).shift_by(parent, *offset)); | |
| 223 | + new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset)); | |
| 224 | 224 | |
| 225 | 225 | // Let hunks catchup with this change. |
| 226 | 226 | ( |
| @@ -273,7 +273,7 @@ fn process_change( · 46 unmodified lines | ||
| 273 | 273 | } |
| 274 | 274 | Either::Right((before, after)) => { |
| 275 | 275 | // `before` isn't affected by deletion, so keep it for later. |
| 276 | − new_hunks_to_blame.push(before.clone_blame(suspect, parent).shift_by(parent, *offset)); | |
| 276 | + new_hunks_to_blame.push(before.cloned_blame(suspect, parent).shift_by(parent, *offset)); | |
| 277 | 277 | // after will be affected by offset, and we will see if there are more changes affecting it. |
| 278 | 278 | after |
| 279 | 279 | } |
| @@ -285,7 +285,7 @@ fn process_change( · 5 unmodified lines | ||
| 285 | 285 | // | (line_number_in_destination) |
| 286 | 286 | |
| 287 | 287 | // Catchup with changes. |
| 288 | − new_hunks_to_blame.push(hunk.clone_blame(suspect, parent).shift_by(parent, *offset)); | |
| 288 | + new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset)); | |
| 289 | 289 | |
| 290 | 290 | ( |
| 291 | 291 | None, |
| @@ -295,7 +295,7 @@ fn process_change( · 3 unmodified lines | ||
| 295 | 295 | } |
| 296 | 296 | (Some(hunk), None) => { |
| 297 | 297 | // nothing to do - changes are exhausted, re-evaluate `hunk`. |
| 298 | − new_hunks_to_blame.push(hunk.clone_blame(suspect, parent).shift_by(parent, *offset)); | |
| 298 | + new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset)); | |
| 299 | 299 | (None, None) |
| 300 | 300 | } |
| 301 | 301 | (None, Some(Change::Unchanged(_))) => { |
| @@ -409,13 +409,17 @@ impl UnblamedHunk { · 107 unmodified lines | ||
| 409 | 409 | } |
| 410 | 410 | } |
| 411 | 411 | |
| 412 | − // TODO | |
| 413 | − // Should this also accept `&mut self` as the other functions do? | |
| 414 | − fn clone_blame(mut self, from: ObjectId, to: ObjectId) -> Self { | |
| 412 | + /// This is like [`Self::clone_blame()`], but easier to use in places | |
| 413 | + /// where the cloning is done 'inline'. | |
| 414 | + fn cloned_blame(mut self, from: ObjectId, to: ObjectId) -> Self { | |
| 415 | + self.clone_blame(from, to); | |
| 416 | + self | |
| 417 | + } | |
| 418 | + | |
| 419 | + fn clone_blame(&mut self, from: ObjectId, to: ObjectId) { | |
| 415 | 420 | if let Some(range_in_suspect) = self.suspects.get(&from) { |
| 416 | 421 | self.suspects.insert(to, range_in_suspect.clone()); |
| 417 | 422 | } |
| 418 | − self | |
| 419 | 423 | } |
| 420 | 424 | |
| 421 | 425 | fn remove_blame(&mut self, suspect: ObjectId) { |