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

Unified · Split

3 files
  1. git-config/src/file/access/mutate.rs +34 −7
  2. git-config/src/file/mod.rs +1 −1
  3. git-config/tests/file/access/mutate.rs +23 −0
git-config/src/file/access/mutate.rs+34−7
@@ -2,6 +2,7 @@ use std::borrow::Cow; · 1 unmodified line
2 2
3use git_features::threading::OwnShared;3use git_features::threading::OwnShared;
4 4
5use crate::file::SectionBodyIdsLut;
5use crate::{6use 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_order187 }
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(&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)
192 }219 }
193 220
194 /// Removes the section with `name` and `subsection_name` that passed `filter`, returning the removed section221 /// 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
110/// words, it's possible that a section may have an ID of 3 but the next section110/// 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)]
113pub(crate) struct SectionId(pub(crate) usize);113pub 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///
git-config/tests/file/access/mutate.rs+23−0
@@ -1,3 +1,26 @@
1mod remove_section {
2 use std::convert::TryFrom;
3
4 #[test]
5 fn removal_is_complete() {
6 let mut file = git_config::File::try_from("[core] \na = b\nb=c\n\n[core \"name\"]\nd = 1\ne = 2").unwrap();
7 assert_eq!(file.sections().count(), 2);
8
9 let removed = file.remove_section("core", None).expect("removed correct section");
10 assert_eq!(removed.header().name(), "core");
11 assert_eq!(removed.header().subsection_name(), None);
12 assert_eq!(file.sections().count(), 1);
13
14 let removed = file.remove_section("core", Some("name")).expect("found");
15 assert_eq!(removed.header().name(), "core");
16 assert_eq!(removed.header().subsection_name().expect("present"), "name");
17 assert_eq!(file.sections().count(), 0);
18
19 file.section_mut_or_create_new("core", None).expect("creation succeeds");
20 file.section_mut_or_create_new("core", Some("name"))
21 .expect("creation succeeds");
22 }
23}
1mod rename_section {24mod rename_section {
2 use std::{borrow::Cow, convert::TryFrom};25 use std::{borrow::Cow, convert::TryFrom};
3 26