Skip to content

Commit 974af7b

Browse files
committed
feat: describing commits can now be done with conditional dirty-suffix using commit::describe::Resolution::format_with_dirty_suffix()
1 parent 444714d commit 974af7b

File tree

2 files changed

+70
-7
lines changed

2 files changed

+70
-7
lines changed

gix/src/commit.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,32 @@ pub mod describe {
4040
}
4141

4242
impl<'repo> Resolution<'repo> {
43-
/// Turn this instance into something displayable
43+
/// Turn this instance into something displayable.
4444
pub fn format(self) -> Result<gix_revision::describe::Format<'static>, Error> {
4545
let prefix = self.id.shorten()?;
4646
Ok(self.outcome.into_format(prefix.hex_len()))
4747
}
48+
49+
/// Turn this instance into something displayable, possibly with dirty-suffix.
50+
///
51+
/// If `dirty_suffix` is `Some(suffix)`, a possibly expensive [dirty check](crate::Repository::is_dirty()) will be
52+
/// performed so that the `suffix` is appended to the output. If it is `None`, no check will be performed and
53+
/// there will be no suffix.
54+
/// Note that obtaining the dirty-state of the repository can be expensive.
55+
#[cfg(all(feature = "status", feature = "parallel"))]
56+
pub fn format_with_dirty_suffix(
57+
self,
58+
dirty_suffix: impl Into<Option<String>>,
59+
) -> Result<gix_revision::describe::Format<'static>, Error> {
60+
let prefix = self.id.shorten()?;
61+
let mut dirty_suffix = dirty_suffix.into();
62+
if dirty_suffix.is_some() && !self.id.repo.is_dirty()? {
63+
dirty_suffix.take();
64+
}
65+
let mut format = self.outcome.into_format(prefix.hex_len());
66+
format.dirty_suffix = dirty_suffix;
67+
Ok(format)
68+
}
4869
}
4970

5071
/// The error returned by [`try_format()`][Platform::try_format()].
@@ -59,6 +80,9 @@ pub mod describe {
5980
RefIter(#[from] crate::reference::iter::Error),
6081
#[error(transparent)]
6182
RefIterInit(#[from] crate::reference::iter::init::Error),
83+
#[error(transparent)]
84+
#[cfg(all(feature = "status", feature = "parallel"))]
85+
DetermineIsDirty(#[from] crate::status::is_dirty::Error),
6286
}
6387

6488
/// A selector to choose what kind of references should contribute to names.
@@ -179,9 +203,7 @@ pub mod describe {
179203
}
180204

181205
/// Try to find a name for the configured commit id using all prior configuration, returning `Some(describe::Format)`
182-
/// if one was found.
183-
///
184-
/// Note that there will always be `Some(format)`
206+
/// if one was found, or `None` if that wasn't the case.
185207
pub fn try_format(&self) -> Result<Option<gix_revision::describe::Format<'static>>, Error> {
186208
self.try_resolve()?.map(Resolution::format).transpose()
187209
}
@@ -193,10 +215,9 @@ pub mod describe {
193215
///
194216
/// # Performance
195217
///
196-
/// It is greatly recommended to [assure an object cache is set][crate::Repository::object_cache_size_if_unset()]
218+
/// It is greatly recommended to [assure an object cache is set](crate::Repository::object_cache_size_if_unset())
197219
/// to save ~40% of time.
198220
pub fn try_resolve(&self) -> Result<Option<Resolution<'repo>>, Error> {
199-
// TODO: dirty suffix with respective dirty-detection
200221
let mut graph = gix_revwalk::Graph::new(
201222
&self.repo.objects,
202223
gix_commitgraph::Graph::from_info_dir(self.repo.objects.store_ref().path().join("info").as_ref()).ok(),
@@ -218,7 +239,7 @@ pub mod describe {
218239
}))
219240
}
220241

221-
/// Like [`try_format()`][Platform::try_format()], but turns `id_as_fallback()` on to always produce a format.
242+
/// Like [`try_format()`](Self::try_format()), but turns `id_as_fallback()` on to always produce a format.
222243
pub fn format(&mut self) -> Result<gix_revision::describe::Format<'static>, Error> {
223244
self.id_as_fallback = true;
224245
Ok(self.try_format()?.expect("BUG: fallback must always produce a format"))

gix/tests/commit/mod.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,48 @@ mod describe {
44

55
use crate::named_repo;
66

7+
#[cfg(all(feature = "status", feature = "parallel"))]
8+
mod with_dirty_suffix {
9+
use crate::util::named_subrepo_opts;
10+
use gix::commit::describe::SelectRef;
11+
12+
#[test]
13+
fn dirty_suffix_applies_automatically_if_dirty() -> crate::Result {
14+
let repo = named_subrepo_opts(
15+
"make_submodules.sh",
16+
"submodule-head-changed",
17+
gix::open::Options::isolated(),
18+
)?;
19+
20+
let actual = repo
21+
.head_commit()?
22+
.describe()
23+
.names(SelectRef::AllRefs)
24+
.try_resolve()?
25+
.expect("resolution")
26+
.format_with_dirty_suffix("dirty".to_owned())?
27+
.to_string();
28+
assert_eq!(actual, "main-dirty");
29+
Ok(())
30+
}
31+
32+
#[test]
33+
fn dirty_suffix_does_not_apply_if_not_dirty() -> crate::Result {
34+
let repo = named_subrepo_opts("make_submodules.sh", "module1", gix::open::Options::isolated())?;
35+
36+
let actual = repo
37+
.head_commit()?
38+
.describe()
39+
.names(SelectRef::AllRefs)
40+
.try_resolve()?
41+
.expect("resolution")
42+
.format_with_dirty_suffix("dirty".to_owned())?
43+
.to_string();
44+
assert_eq!(actual, "main");
45+
Ok(())
46+
}
47+
}
48+
749
#[test]
850
fn tags_are_sorted_by_date_and_lexicographically() -> crate::Result {
951
let repo = named_repo("make_commit_describe_multiple_tags.sh")?;

0 commit comments

Comments
 (0)