Skip to content

Commit 503098d

Browse files
authored
Merge pull request #1835 from GitoxideLabs/fixes
various fixes
2 parents 5c327bb + be80806 commit 503098d

File tree

6 files changed

+89
-40
lines changed

6 files changed

+89
-40
lines changed

gix-config/src/file/access/mutate.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,8 @@ impl<'event> File<'event> {
8686
.section_ids_by_name_and_subname(name.as_ref(), subsection_name)
8787
.ok()
8888
.and_then(|it| {
89-
it.rev().find(|id| {
90-
let s = &self.sections[id];
91-
filter(s.meta())
92-
})
89+
it.rev()
90+
.find(|id| self.sections.get(id).is_some_and(|s| filter(s.meta())))
9391
}) {
9492
Some(id) => {
9593
let nl = self.detect_newline_style_smallvec();
@@ -305,7 +303,7 @@ impl<'event> File<'event> {
305303
.section_ids_by_name_and_subname(name, subsection_name)
306304
.ok()?
307305
.rev()
308-
.find(|id| filter(self.sections.get(id).expect("each id has a section").meta()))?;
306+
.find(|id| self.sections.get(id).is_some_and(|section| filter(section.meta())))?;
309307
self.section_order.remove(
310308
self.section_order
311309
.iter()

gix-config/tests/config/file/access/mutate.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,59 @@ mod remove_section {
2525
}
2626

2727
#[test]
28-
fn removal_is_complete_and_sections_can_be_readded() {
28+
fn removal_is_complete_and_sections_can_be_read() {
2929
let mut file = gix_config::File::try_from("[core] \na = b\nb=c\n\n[core \"name\"]\nd = 1\ne = 2").unwrap();
3030
assert_eq!(file.sections().count(), 2);
3131

3232
let removed = file.remove_section("core", None).expect("removed correct section");
3333
assert_eq!(removed.header().name(), "core");
3434
assert_eq!(removed.header().subsection_name(), None);
3535
assert_eq!(file.sections().count(), 1);
36+
assert_eq!(file.remove_section("core", None), None, "it's OK to try again");
3637

3738
let removed = file.remove_section("core", Some("name".into())).expect("found");
3839
assert_eq!(removed.header().name(), "core");
3940
assert_eq!(removed.header().subsection_name().expect("present"), "name");
4041
assert_eq!(file.sections().count(), 0);
42+
assert_eq!(file.remove_section("core", Some("name".into())), None);
4143

4244
file.section_mut_or_create_new("core", None).expect("creation succeeds");
4345
file.section_mut_or_create_new("core", Some("name".into()))
4446
.expect("creation succeeds");
4547
}
4648
}
49+
mod remove_section_filter {
50+
#[test]
51+
fn removal_of_section_is_complete() {
52+
let mut file = gix_config::File::try_from("[core] \na = b\nb=c\n\n[core \"name\"]\nd = 1\ne = 2").unwrap();
53+
assert_eq!(file.sections().count(), 2);
54+
55+
let removed = file
56+
.remove_section_filter("core", None, |_| true)
57+
.expect("removed correct section");
58+
assert_eq!(removed.header().name(), "core");
59+
assert_eq!(removed.header().subsection_name(), None);
60+
assert_eq!(file.sections().count(), 1);
61+
let removed = file
62+
.remove_section_filter("core", Some("name".into()), |_| true)
63+
.expect("found");
64+
assert_eq!(removed.header().name(), "core");
65+
assert_eq!(removed.header().subsection_name().expect("present"), "name");
66+
assert_eq!(file.sections().count(), 0);
67+
68+
assert_eq!(
69+
file.remove_section_filter("core", None, |_| true),
70+
None,
71+
"it's OK to try again"
72+
);
73+
assert_eq!(file.remove_section_filter("core", Some("name".into()), |_| true), None);
74+
75+
file.section_mut_or_create_new("core", None).expect("creation succeeds");
76+
file.section_mut_or_create_new("core", Some("name".into()))
77+
.expect("creation succeeds");
78+
}
79+
}
80+
4781
mod rename_section {
4882
use std::borrow::Cow;
4983

gix/src/repository/config/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ impl crate::Repository {
1212
/// Return a mutable snapshot of the configuration as seen upon opening the repository, starting a transaction.
1313
/// When the returned instance is dropped, it is applied in full, even if the reason for the drop is an error.
1414
///
15-
/// Note that changes to the configuration are in-memory only and are observed only the this instance
16-
/// of the [`Repository`][crate::Repository].
15+
/// Note that changes to the configuration are in-memory only and are observed only this instance
16+
/// of the [`Repository`](crate::Repository).
1717
pub fn config_snapshot_mut(&mut self) -> config::SnapshotMut<'_> {
1818
let config = self.config.resolved.as_ref().clone();
1919
config::SnapshotMut {

gix/src/repository/object.rs

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ impl crate::Repository {
254254
self.tag_reference(name, tag_id, constraint).map_err(Into::into)
255255
}
256256

257-
/// Similar to [`commit(…)`][crate::Repository::commit()], but allows to create the commit with `committer` and `author` specified.
257+
/// Similar to [`commit(…)`](crate::Repository::commit()), but allows to create the commit with `committer` and `author` specified.
258258
///
259259
/// This forces setting the commit time and author time by hand. Note that typically, committer and author are the same.
260260
pub fn commit_as<'a, 'c, Name, E>(
@@ -307,28 +307,35 @@ impl crate::Repository {
307307
};
308308

309309
let commit_id = self.write_object(&commit)?;
310-
self.edit_reference(RefEdit {
311-
change: Change::Update {
312-
log: LogChange {
313-
mode: RefLog::AndReference,
314-
force_create_reflog: false,
315-
message: crate::reference::log::message("commit", commit.message.as_ref(), commit.parents.len()),
316-
},
317-
expected: match commit.parents.first().map(|p| Target::Object(*p)) {
318-
Some(previous) => {
319-
if reference.as_bstr() == "HEAD" {
320-
PreviousValue::MustExistAndMatch(previous)
321-
} else {
322-
PreviousValue::ExistingMustMatch(previous)
310+
self.edit_references_as(
311+
Some(RefEdit {
312+
change: Change::Update {
313+
log: LogChange {
314+
mode: RefLog::AndReference,
315+
force_create_reflog: false,
316+
message: crate::reference::log::message(
317+
"commit",
318+
commit.message.as_ref(),
319+
commit.parents.len(),
320+
),
321+
},
322+
expected: match commit.parents.first().map(|p| Target::Object(*p)) {
323+
Some(previous) => {
324+
if reference.as_bstr() == "HEAD" {
325+
PreviousValue::MustExistAndMatch(previous)
326+
} else {
327+
PreviousValue::ExistingMustMatch(previous)
328+
}
323329
}
324-
}
325-
None => PreviousValue::MustNotExist,
330+
None => PreviousValue::MustNotExist,
331+
},
332+
new: Target::Object(commit_id.inner),
326333
},
327-
new: Target::Object(commit_id.inner),
328-
},
329-
name: reference,
330-
deref: true,
331-
})?;
334+
name: reference,
335+
deref: true,
336+
}),
337+
Some(committer),
338+
)?;
332339
Ok(commit_id)
333340
}
334341

gix/src/repository/reference.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{bstr::BString, ext::ReferenceExt, reference, Reference};
1010
impl crate::Repository {
1111
/// Create a lightweight tag with given `name` (and without `refs/tags/` prefix) pointing to the given `target`, and return it as reference.
1212
///
13-
/// It will be created with `constraint` which is most commonly to [only create it][PreviousValue::MustNotExist]
13+
/// It will be created with `constraint` which is most commonly to [only create it](PreviousValue::MustNotExist)
1414
/// or to [force overwriting a possibly existing tag](PreviousValue::Any).
1515
pub fn tag_reference(
1616
&self,
@@ -135,25 +135,37 @@ impl crate::Repository {
135135

136136
/// Edit one or more references as described by their `edits`.
137137
/// Note that one can set the committer name for use in the ref-log by temporarily
138-
/// [overriding the git-config][crate::Repository::config_snapshot_mut()].
138+
/// [overriding the git-config](crate::Repository::config_snapshot_mut()), or use
139+
/// [`edit_references_as(committer)`](Self::edit_references_as()) for convenience.
139140
///
140141
/// Returns all reference edits, which might be more than where provided due the splitting of symbolic references, and
141142
/// whose previous (_old_) values are the ones seen on in storage after the reference was locked.
142143
pub fn edit_references(
143144
&self,
144145
edits: impl IntoIterator<Item = RefEdit>,
146+
) -> Result<Vec<RefEdit>, reference::edit::Error> {
147+
self.edit_references_as(edits, self.committer().transpose()?)
148+
}
149+
150+
/// A way to apply reference `edits` similar to [edit_references(…)](Self::edit_references()), but set a specific
151+
/// `commiter` for use in the reflog. It can be `None` if it's the purpose `edits` are configured to not update the
152+
/// reference log, or cause a failure otherwise.
153+
pub fn edit_references_as(
154+
&self,
155+
edits: impl IntoIterator<Item = RefEdit>,
156+
committer: Option<gix_actor::SignatureRef<'_>>,
145157
) -> Result<Vec<RefEdit>, reference::edit::Error> {
146158
let (file_lock_fail, packed_refs_lock_fail) = self.config.lock_timeout()?;
147159
self.refs
148160
.transaction()
149161
.prepare(edits, file_lock_fail, packed_refs_lock_fail)?
150-
.commit(self.committer().transpose()?)
162+
.commit(committer)
151163
.map_err(Into::into)
152164
}
153165

154166
/// Return the repository head, an abstraction to help dealing with the `HEAD` reference.
155167
///
156-
/// The `HEAD` reference can be in various states, for more information, the documentation of [`Head`][crate::Head].
168+
/// The `HEAD` reference can be in various states, for more information, the documentation of [`Head`](crate::Head).
157169
pub fn head(&self) -> Result<crate::Head<'_>, reference::find::existing::Error> {
158170
let head = self.find_reference("HEAD")?;
159171
Ok(match head.inner.target {
@@ -184,7 +196,7 @@ impl crate::Repository {
184196

185197
/// Return the name to the symbolic reference `HEAD` points to, or `None` if the head is detached.
186198
///
187-
/// The difference to [`head_ref()`][Self::head_ref()] is that the latter requires the reference to exist,
199+
/// The difference to [`head_ref()`](Self::head_ref()) is that the latter requires the reference to exist,
188200
/// whereas here we merely return a the name of the possibly unborn reference.
189201
pub fn head_name(&self) -> Result<Option<FullName>, reference::find::existing::Error> {
190202
Ok(self.head()?.referent_name().map(std::borrow::ToOwned::to_owned))
@@ -228,7 +240,7 @@ impl crate::Repository {
228240
/// Find the reference with the given partial or full `name`, like `main`, `HEAD`, `heads/branch` or `origin/other`,
229241
/// or return an error if it wasn't found.
230242
///
231-
/// Consider [`try_find_reference(…)`][crate::Repository::try_find_reference()] if the reference might not exist
243+
/// Consider [`try_find_reference(…)`](crate::Repository::try_find_reference()) if the reference might not exist
232244
/// without that being considered an error.
233245
pub fn find_reference<'a, Name, E>(&self, name: Name) -> Result<Reference<'_>, reference::find::existing::Error>
234246
where
@@ -249,7 +261,7 @@ impl crate::Repository {
249261

250262
/// Return a platform for iterating references.
251263
///
252-
/// Common kinds of iteration are [all][crate::reference::iter::Platform::all()] or [prefixed][crate::reference::iter::Platform::prefixed()]
264+
/// Common kinds of iteration are [all](crate::reference::iter::Platform::all()) or [prefixed](crate::reference::iter::Platform::prefixed())
253265
/// references.
254266
pub fn references(&self) -> Result<reference::iter::Platform<'_>, reference::iter::Error> {
255267
Ok(reference::iter::Platform {
@@ -261,7 +273,7 @@ impl crate::Repository {
261273
/// Try to find the reference named `name`, like `main`, `heads/branch`, `HEAD` or `origin/other`, and return it.
262274
///
263275
/// Otherwise return `None` if the reference wasn't found.
264-
/// If the reference is expected to exist, use [`find_reference()`][crate::Repository::find_reference()].
276+
/// If the reference is expected to exist, use [`find_reference()`](crate::Repository::find_reference()).
265277
pub fn try_find_reference<'a, Name, E>(&self, name: Name) -> Result<Option<Reference<'_>>, reference::find::Error>
266278
where
267279
Name: TryInto<&'a PartialNameRef, Error = E>,

gix/tests/gix/repository/object.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,16 +536,14 @@ mod tag {
536536
mod commit_as {
537537
use gix_testtools::tempfile;
538538

539-
use crate::util::restricted_and_git;
540-
541539
#[test]
542540
fn specify_committer_and_author() -> crate::Result {
543541
let tmp = tempfile::tempdir()?;
544542
let repo = gix::ThreadSafeRepository::init_opts(
545543
&tmp,
546544
gix::create::Kind::WithWorktree,
547545
Default::default(),
548-
restricted_and_git(),
546+
gix::open::Options::isolated(),
549547
)?
550548
.to_thread_local();
551549
let empty_tree = repo.empty_tree();

0 commit comments

Comments
 (0)