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