History

fix: `File::remove_section()` was fixed to allow re-adding a similarly named section.

We also add `File::remove_section_by_id()` to make it possible to remove specific sections.

Sebastian Thiel committed 4 years ago

Commit e5339931 parent 79a49523 files · +58 −8Browse files

Showing the changes to git-config/src (2 of 3 files). Show all

Unified · Split

2 files
  1. git-config/src/file/access/mutate.rs +34 −7
  2. git-config/src/file/mod.rs +1 −1
git-config/src/file/access/mutate.rs+34−7
@@ -2,6 +2,7 @@ use std::borrow::Cow; · 1 unmodified line
22
33 use git_features::threading::OwnShared;
44
5+use crate::file::SectionBodyIdsLut;
56 use crate::{
67 file::{self, rename_section, write::ends_with_newline, MetadataFilter, SectionId, SectionMut},
78 lookup,
@@ -182,13 +183,39 @@ impl<'event> File<'event> { · 174 unmodified lines
182183 .ok()?
183184 .rev()
184185 .next()?;
185− self.section_order.remove(
186− self.section_order
187− .iter()
188− .position(|v| *v == id)
189− .expect("known section id"),
190− );
191− self.sections.remove(&id)
186+ self.remove_section_by_id(id)
187+ }
188+
189+ /// Remove the section identified by `id` if it exists and return it, or return `None` if no such section was present.
190+ ///
191+ /// Note that section ids are unambiguous even in the face of removals and additions of sections.
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(&section.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)
192219 }
193220
194221 /// Removes the section with `name` and `subsection_name` that passed `filter`, returning the removed section
git-config/src/file/mod.rs+1−1
@@ -110,7 +110,7 @@ impl AddAssign<usize> for Size { · 109 unmodified lines
110110 /// words, it's possible that a section may have an ID of 3 but the next section
111111 /// has an ID of 5 as 4 was deleted.
112112 #[derive(PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord, Debug)]
113−pub(crate) struct SectionId(pub(crate) usize);
113+pub struct SectionId(pub(crate) usize);
114114
115115 /// All section body ids referred to by a section name.
116116 ///