We also add `File::remove_section_by_id()` to make it possible to remove specific sections.
Showing the changes to git-config/src (2 of 3 files). Show all
Unified · Split
| @@ -2,6 +2,7 @@ use std::borrow::Cow; · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | use git_features::threading::OwnShared; | 3 | use git_features::threading::OwnShared; |
| 4 | 4 | ||
| 5 | use crate::file::SectionBodyIdsLut; | ||
| 5 | use crate::{ | 6 | use crate::{ |
| 6 | file::{self, rename_section, write::ends_with_newline, MetadataFilter, SectionId, SectionMut}, | 7 | file::{self, rename_section, write::ends_with_newline, MetadataFilter, SectionId, SectionMut}, |
| 7 | lookup, | 8 | lookup, |
| @@ -182,13 +183,39 @@ impl<'event> File<'event> { · 174 unmodified lines | |||
| 182 | .ok()? | 183 | .ok()? |
| 183 | .rev() | 184 | .rev() |
| 184 | .next()?; | 185 | .next()?; |
| 185 | self.section_order.remove( | 186 | self.remove_section_by_id(id) |
| 186 | self.section_order | 187 | } |
| 187 | .iter() | 188 | |
| 188 | .position(|v| *v == id) | 189 | /// Remove the section identified by `id` if it exists and return it, or return `None` if no such section was present. |
| 189 | .expect("known section id"), | 190 | /// |
| 190 | ); | 191 | /// Note that section ids are unambiguous even in the face of removals and additions of sections. |
| 191 | self.sections.remove(&id) | 192 | pub fn remove_section_by_id(&mut self, id: SectionId) -> Option<file::Section<'event>> { |
| 193 | self.section_order | ||
| 194 | .remove(self.section_order.iter().position(|v| *v == id)?); | ||
| 195 | let section = self.sections.remove(&id)?; | ||
| 196 | let lut = self | ||
| 197 | .section_lookup_tree | ||
| 198 | .get_mut(§ion.header.name) | ||
| 199 | .expect("lookup cache still has name to be deleted"); | ||
| 200 | for entry in lut { | ||
| 201 | match section.header.subsection_name.as_deref() { | ||
| 202 | Some(subsection_name) => { | ||
| 203 | if let SectionBodyIdsLut::NonTerminal(map) = entry { | ||
| 204 | if let Some(ids) = map.get_mut(subsection_name) { | ||
| 205 | ids.remove(ids.iter().position(|v| *v == id).expect("present")); | ||
| 206 | break; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | } | ||
| 210 | None => { | ||
| 211 | if let SectionBodyIdsLut::Terminal(ids) = entry { | ||
| 212 | ids.remove(ids.iter().position(|v| *v == id).expect("present")); | ||
| 213 | break; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 | Some(section) | ||
| 192 | } | 219 | } |
| 193 | 220 | ||
| 194 | /// Removes the section with `name` and `subsection_name` that passed `filter`, returning the removed section | 221 | /// Removes the section with `name` and `subsection_name` that passed `filter`, returning the removed section |
| @@ -110,7 +110,7 @@ impl AddAssign<usize> for Size { · 109 unmodified lines | |||
| 110 | /// words, it's possible that a section may have an ID of 3 but the next section | 110 | /// words, it's possible that a section may have an ID of 3 but the next section |
| 111 | /// has an ID of 5 as 4 was deleted. | 111 | /// has an ID of 5 as 4 was deleted. |
| 112 | #[derive(PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord, Debug)] | 112 | #[derive(PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord, Debug)] |
| 113 | pub(crate) struct SectionId(pub(crate) usize); | 113 | pub struct SectionId(pub(crate) usize); |
| 114 | 114 | ||
| 115 | /// All section body ids referred to by a section name. | 115 | /// All section body ids referred to by a section name. |
| 116 | /// | 116 | /// |