But explicitly with the special case early, laying out the various case become
simpler.
(The initial motivation was to make some future lifetime error simpler).
| Alphare |
| hg-reviewers |
But explicitly with the special case early, laying out the various case become
simpler.
(The initial motivation was to make some future lifetime error simpler).
| Automatic diff as part of commit; lint not applicable. |
| Automatic diff as part of commit; unit tests not applicable. |
| Path | Packages | |||
|---|---|---|---|---|
| M | rust/hg-core/src/dirstate/dirstate_tree/node.rs (63 lines) |
| ) -> InsertResult { | ) -> InsertResult { | ||||
| let mut split = path.splitn(2, |&c| c == b'/'); | let mut split = path.splitn(2, |&c| c == b'/'); | ||||
| let head = split.next().unwrap_or(b""); | let head = split.next().unwrap_or(b""); | ||||
| let tail = split.next().unwrap_or(b""); | let tail = split.next().unwrap_or(b""); | ||||
| // Are we're modifying the current file ? Is the the end of the path ? | // Are we're modifying the current file ? Is the the end of the path ? | ||||
| let is_current_file = tail.is_empty() && head.is_empty(); | let is_current_file = tail.is_empty() && head.is_empty(); | ||||
| // Potentially Replace the current file with a directory if it's marked | |||||
| // as `Removed` | |||||
| if !is_current_file { | |||||
| if let NodeKind::File(file) = &mut self.kind { | if let NodeKind::File(file) = &mut self.kind { | ||||
| if file.entry.state == EntryState::Removed { | |||||
| self.kind = NodeKind::Directory(Directory { | |||||
| was_file: Some(Box::from(file.clone())), | |||||
| children: Default::default(), | |||||
| }) | |||||
| } | |||||
| } | |||||
| } | |||||
| match &mut self.kind { | |||||
| NodeKind::Directory(directory) => { | |||||
| Node::insert_in_directory(directory, new_entry, head, tail) | |||||
| } | |||||
| NodeKind::File(file) => { | |||||
| if is_current_file { | if is_current_file { | ||||
| let new = Self { | let new = Self { | ||||
| kind: NodeKind::File(File { | kind: NodeKind::File(File { | ||||
| entry: new_entry, | entry: new_entry, | ||||
| ..file.clone() | ..file.clone() | ||||
| }), | }), | ||||
| }; | }; | ||||
| return InsertResult { | InsertResult { | ||||
| did_insert: false, | did_insert: false, | ||||
| old_entry: Some(std::mem::replace(self, new)), | old_entry: Some(std::mem::replace(self, new)), | ||||
| }; | } | ||||
| } else { | } else { | ||||
| match file.entry.state { | match file.entry.state { | ||||
| // Only replace the current file with a directory if it's | |||||
| // marked as `Removed` | |||||
| EntryState::Removed => { | EntryState::Removed => { | ||||
| self.kind = NodeKind::Directory(Directory { | unreachable!("Removed file turning into a directory was dealt with earlier") | ||||
| was_file: Some(Box::from(file.clone())), | |||||
| children: Default::default(), | |||||
| }) | |||||
| } | } | ||||
| _ => { | _ => { | ||||
| return Node::insert_in_file( | Node::insert_in_file( | ||||
| file, new_entry, head, tail, | file, new_entry, head, tail, | ||||
| ) | ) | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| match &mut self.kind { | |||||
| NodeKind::Directory(directory) => { | |||||
| Node::insert_in_directory(directory, new_entry, head, tail) | |||||
| } | |||||
| NodeKind::File(_) => { | |||||
| unreachable!("The file case has already been handled") | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| /// The current file still exists and is not marked as `Removed`. | /// The current file still exists and is not marked as `Removed`. | ||||
| /// Insert the entry in its `was_directory`. | /// Insert the entry in its `was_directory`. | ||||
| fn insert_in_file( | fn insert_in_file( | ||||
| file: &mut File, | file: &mut File, | ||||
| new_entry: DirstateEntry, | new_entry: DirstateEntry, | ||||