History

feat: Support for no prefixes in version headers (#228)

These are also inherited so once set by a single versioned release section, fully generated sections will inherit their prefix from that one.

Sebastian Thiel committed 5 years ago

Commit 3613a951 parent 86cafe311 files · +100 −31Browse files

Unified · Split

11 files
  1. cargo-smart-release/src/changelog/merge.rs +27 −17
  2. cargo-smart-release/src/changelog/mod.rs +2 −0
  3. cargo-smart-release/src/changelog/parse.rs +17 −6
  4. cargo-smart-release/src/changelog/section/from_history.rs +3 −0
  5. cargo-smart-release/src/changelog/write.rs +16 −5
  6. cargo-smart-release/tests/changelog/merge.rs +22 −0
  7. cargo-smart-release/tests/changelog/parse.rs +5 −0
  8. cargo-smart-release/tests/changelog/write_and_parse/mod.rs +3 −0
  9. cargo-smart-release/tests/changelog/write_and_parse/snapshots/integration__changelog__write_and_parse__all_section_types_round_trips_lossy-2.snap +2 −1
  10. cargo-smart-release/tests/changelog/write_and_parse/snapshots/integration__changelog__write_and_parse__all_section_types_round_trips_lossy-8.snap +1 −1
  11. cargo-smart-release/tests/changelog/write_and_parse/snapshots/integration__changelog__write_and_parse__all_section_types_round_trips_lossy.snap +2 −1
cargo-smart-release/src/changelog/merge.rs+27−17
@@ -24,12 +24,16 @@ impl ChangeLog { · 23 unmodified lines
2424
2525 merge_generated_verbatim_section_if_there_is_only_releases_on_lhs(&mut sections_to_merge, sections);
2626
27− let (first_release_pos, first_release_indentation) =
27+ let (first_release_pos, first_release_indentation, first_version_prefix) =
2828 match sections.iter().enumerate().find_map(|(idx, s)| match s {
29− Section::Release { heading_level, .. } => Some((idx, heading_level)),
29+ Section::Release {
30+ heading_level,
31+ version_prefix,
32+ ..
33+ } => Some((idx, heading_level, version_prefix)),
3034 _ => None,
3135 }) {
32− Some((idx, level)) => (idx, *level),
36+ Some((idx, level, prefix)) => (idx, *level, prefix.to_owned()),
3337 None => {
3438 sections.extend(sections_to_merge);
3539 return self;
@@ -44,8 +48,14 @@ impl ChangeLog { · 8 unmodified lines
4448 Section::Release { ref name, .. } => match find_target_section(name, sections, first_release_pos) {
4549 Insertion::MergeWith(pos) => sections[pos].merge(section_to_merge),
4650 Insertion::At(pos) => {
47− if let Section::Release { heading_level, .. } = &mut section_to_merge {
51+ if let Section::Release {
52+ heading_level,
53+ version_prefix,
54+ ..
55+ } = &mut section_to_merge
56+ {
4857 *heading_level = first_release_indentation;
58+ *version_prefix = first_version_prefix.clone();
4959 }
5060 sections.insert(pos, section_to_merge);
5161 }
@@ -66,26 +76,26 @@ impl Section { · 14 unmodified lines
6676 }
6777 (
6878 Section::Release {
69− date: lhs_date,
70− segments: lhs_segments,
79+ date: dest_date,
80+ segments: dest_segments,
7181 removed_messages,
7282 ..
7383 },
7484 Section::Release {
75− date: rhs_date,
76− segments: rhs_segments,
77− unknown: rhs_unknown,
85+ date: src_date,
86+ segments: src_segments,
87+ unknown: src_unknown,
7888 ..
7989 },
8090 ) => {
81− assert!(rhs_unknown.is_empty(), "shouldn't ever generate 'unknown' portions");
82− let has_no_read_only_segments = !lhs_segments.iter().any(|s| s.is_read_only());
91+ assert!(src_unknown.is_empty(), "shouldn't ever generate 'unknown' portions");
92+ let has_no_read_only_segments = !dest_segments.iter().any(|s| s.is_read_only());
8393 let mode = if has_no_read_only_segments {
8494 ReplaceMode::ReplaceAllOrAppend
8595 } else {
8696 ReplaceMode::ReplaceAllOrAppendIfPresentInLhs
8797 };
88− for rhs_segment in rhs_segments {
98+ for rhs_segment in src_segments {
8999 match rhs_segment {
90100 Segment::User { .. } => unreachable!("BUG: User segments are never auto-generated"),
91101 Segment::Details(section::Data::Parsed)
@@ -94,20 +104,20 @@ impl Section { · 2 unmodified lines
94104 unreachable!("BUG: Clippy, statistics, and details are set if generated, or not present")
95105 }
96106 Segment::Conventional(conventional) => {
97− merge_conventional(removed_messages, lhs_segments, conventional)
107+ merge_conventional(removed_messages, dest_segments, conventional)
98108 }
99109 clippy @ Segment::Clippy(_) => {
100− merge_read_only_segment(lhs_segments, |s| matches!(s, Segment::Clippy(_)), clippy, mode)
110+ merge_read_only_segment(dest_segments, |s| matches!(s, Segment::Clippy(_)), clippy, mode)
101111 }
102112 stats @ Segment::Statistics(_) => {
103− merge_read_only_segment(lhs_segments, |s| matches!(s, Segment::Statistics(_)), stats, mode)
113+ merge_read_only_segment(dest_segments, |s| matches!(s, Segment::Statistics(_)), stats, mode)
104114 }
105115 details @ Segment::Details(_) => {
106− merge_read_only_segment(lhs_segments, |s| matches!(s, Segment::Details(_)), details, mode)
116+ merge_read_only_segment(dest_segments, |s| matches!(s, Segment::Details(_)), details, mode)
107117 }
108118 }
109119 }
110− *lhs_date = rhs_date;
120+ *dest_date = src_date;
111121 }
112122 }
113123 }
cargo-smart-release/src/changelog/mod.rs+2−0
@@ -27,6 +27,8 @@ pub enum Section { · 26 unmodified lines
2727 date: Option<time::OffsetDateTime>,
2828 /// the amount of # in front of the heading denoting the release name
2929 heading_level: usize,
30+ /// What came right before the version
31+ version_prefix: String,
3032 /// text of events of everything we couldn't parse
3133 unknown: String,
3234 /// Removed git conventional messages parsed back from html tags. These may live without a headline, to delete the headline.
cargo-smart-release/src/changelog/parse.rs+17−6
@@ -106,7 +106,15 @@ impl ChangeLog { · 105 unmodified lines
106106 }
107107
108108 impl Section {
109− fn from_headline_and_body(Headline { level, version, date }: Headline, body: String) -> Self {
109+ fn from_headline_and_body(
110+ Headline {
111+ level,
112+ version_prefix,
113+ version,
114+ date,
115+ }: Headline,
116+ body: String,
117+ ) -> Self {
110118 let mut events = pulldown_cmark::Parser::new_ext(&body, pulldown_cmark::Options::all())
111119 .into_offset_iter()
112120 .peekable();
@@ -215,6 +223,7 @@ impl Section { · 102 unmodified lines
215223 Some(version) => changelog::Version::Semantic(version),
216224 None => changelog::Version::Unreleased,
217225 },
226+ version_prefix,
218227 date,
219228 removed_messages,
220229 heading_level: level,
@@ -443,6 +452,7 @@ fn skip_to_next_section_title(events: &mut Peekable<OffsetIter<'_>>, level: u32) · 222 unmodified lines
443452
444453 struct Headline {
445454 level: usize,
455+ version_prefix: String,
446456 version: Option<semver::Version>,
447457 date: Option<time::OffsetDateTime>,
448458 }
@@ -470,13 +480,13 @@ fn headline<'a, E: ParseError<&'a str> + FromExternalError<&'a str, ()>>(i: &'a · 21 unmodified lines
470480 hashes,
471481 greedy_whitespace,
472482 alt((
473− preceded(
474− tag("v"),
483+ tuple((
484+ opt(tag("v")),
475485 map_res(take_till(|c: char| c.is_whitespace()), |v| {
476486 semver::Version::parse(v).map_err(|_| ()).map(Some)
477487 }),
478− ),
479− map(tag_no_case("unreleased"), |_| None),
488+ )),
489+ map(tag_no_case("unreleased"), |_| (None, None)),
480490 )),
481491 ),
482492 opt(preceded(
@@ -499,8 +509,9 @@ fn headline<'a, E: ParseError<&'a str> + FromExternalError<&'a str, ()>>(i: &'a · 16 unmodified lines
499509 )),
500510 greedy_whitespace,
501511 ),
502− |((hashes, version), date)| Headline {
512+ |((hashes, (prefix, version)), date)| Headline {
503513 level: hashes.len(),
514+ version_prefix: prefix.map(ToOwned::to_owned).unwrap_or_else(String::new),
504515 version,
505516 date,
506517 },
cargo-smart-release/src/changelog/section/from_history.rs+3−0
@@ -16,6 +16,8 @@ use crate::{ · 15 unmodified lines
1616 };
1717
1818 impl Section {
19+ pub const DEFAULT_PREFIX: &'static str = "v";
20+
1921 pub fn from_history_segment(
2022 package: &Package,
2123 segment: &commit::history::Segment<'_>,
@@ -153,6 +155,7 @@ impl Section { · 131 unmodified lines
153155 name: version,
154156 date,
155157 heading_level: changelog::DEFAULT_HEADING_LEVEL,
158+ version_prefix: Self::DEFAULT_PREFIX.to_owned(),
156159 segments,
157160 removed_messages: Default::default(),
158161 unknown: Default::default(),
cargo-smart-release/src/changelog/write.rs+16−5
@@ -11,11 +11,16 @@ use crate::{ · 10 unmodified lines
1111 ChangeLog,
1212 };
1313
14−impl std::fmt::Display for changelog::Version {
14+struct PrefixedVersion<'a> {
15+ version_prefix: &'a str,
16+ name: &'a changelog::Version,
17+}
18+
19+impl<'a> std::fmt::Display for PrefixedVersion<'a> {
1520 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16− match self {
21+ match self.name {
1722 changelog::Version::Unreleased => f.write_str("Unreleased"),
18− changelog::Version::Semantic(v) => write!(f, "v{}", v),
23+ changelog::Version::Semantic(v) => write!(f, "{}{}", self.version_prefix, v),
1924 }
2025 }
2126 }
@@ -105,12 +110,18 @@ impl Section { · 83 unmodified lines
105110 name,
106111 date,
107112 heading_level,
113+ version_prefix,
108114 segments,
109115 removed_messages,
110116 unknown,
111117 } => {
112118 if components.contains(Components::SECTION_TITLE) {
113− write!(out, "{} {}", heading(*heading_level), name)?;
119+ write!(
120+ out,
121+ "{} {}",
122+ heading(*heading_level),
123+ PrefixedVersion { version_prefix, name }
124+ )?;
114125 match date {
115126 None => out.write_str("\n\n"),
116127 Some(date) => writeln!(
@@ -136,7 +147,7 @@ impl Section { · 19 unmodified lines
136147 if !unknown.is_empty() && components.contains(Components::HTML_TAGS) {
137148 writeln!(out, "{}", Section::UNKNOWN_TAG_START)?;
138149 out.write_str(unknown)?;
139− writeln!(out, "{}", Section::UNKNOWN_TAG_END)?;
150+ writeln!(out, "{}\n", Section::UNKNOWN_TAG_END)?;
140151 }
141152 Ok(())
142153 }
cargo-smart-release/tests/changelog/merge.rs+22−0
@@ -16,6 +16,7 @@ fn sections() { · 15 unmodified lines
1616 },
1717 Section::Release {
1818 heading_level: 3,
19+ version_prefix: "".into(),
1920 removed_messages: vec![],
2021 date: Some(
2122 time::Date::from_calendar_date(2021, time::Month::September, 14)
@@ -33,6 +34,7 @@ fn sections() { · 11 unmodified lines
3334 },
3435 Section::Release {
3536 heading_level: 3,
37+ version_prefix: Section::DEFAULT_PREFIX.into(),
3638 removed_messages: vec![],
3739 date: None,
3840 name: changelog::Version::Semantic("0.9.0".parse().unwrap()),
@@ -51,6 +53,7 @@ fn sections() { · 12 unmodified lines
5153 date: None,
5254 removed_messages: vec![],
5355 name: changelog::Version::Unreleased,
56+ version_prefix: Section::DEFAULT_PREFIX.into(),
5457 heading_level: 2,
5558 segments: vec![section::Segment::Clippy(section::Data::Generated(
5659 section::segment::ThanksClippy { count: 4 },
@@ -62,6 +65,7 @@ fn sections() { · 5 unmodified lines
6265 name: changelog::Version::Semantic("1.0.0".parse().unwrap()),
6366 removed_messages: vec![],
6467 heading_level: 2,
68+ version_prefix: Section::DEFAULT_PREFIX.into(),
6569 segments: vec![section::Segment::Clippy(section::Data::Generated(
6670 section::segment::ThanksClippy { count: 3 },
6771 ))],
@@ -73,6 +77,7 @@ fn sections() { · 5 unmodified lines
7377 unknown: String::new(),
7478 removed_messages: vec![],
7579 heading_level: 2,
80+ version_prefix: Section::DEFAULT_PREFIX.into(),
7681 segments: vec![section::Segment::Clippy(section::Data::Generated(
7782 section::segment::ThanksClippy { count: 2 },
7883 ))],
@@ -83,6 +88,7 @@ fn sections() { · 4 unmodified lines
8388 unknown: "undocumented".into(),
8489 removed_messages: vec![],
8590 heading_level: 2,
91+ version_prefix: Section::DEFAULT_PREFIX.into(),
8692 segments: Vec::new(),
8793 },
8894 ],
@@ -101,6 +107,7 @@ fn sections() { · 12 unmodified lines
101107 date: None,
102108 name: changelog::Version::Unreleased,
103109 heading_level: 3,
110+ version_prefix: "".into(),
104111 removed_messages: vec![],
105112 segments: vec![section::Segment::Clippy(section::Data::Generated(
106113 section::segment::ThanksClippy { count: 4 }
@@ -110,6 +117,7 @@ fn sections() { · 3 unmodified lines
110117 Section::Release {
111118 heading_level: 3,
112119 removed_messages: vec![],
120+ version_prefix: "".into(),
113121 date: Some(
114122 time::Date::from_calendar_date(2021, time::Month::September, 15)
115123 .unwrap()
@@ -131,6 +139,7 @@ fn sections() { · 15 unmodified lines
131139 name: changelog::Version::Semantic("0.9.0".parse().unwrap()),
132140 unknown: String::new(),
133141 heading_level: 3,
142+ version_prefix: Section::DEFAULT_PREFIX.into(),
134143 removed_messages: vec![],
135144 segments: vec![section::Segment::Clippy(section::Data::Generated(
136145 section::segment::ThanksClippy { count: 2 }
@@ -141,6 +150,7 @@ fn sections() { · 4 unmodified lines
141150 name: changelog::Version::Semantic("0.8.0".parse().unwrap()),
142151 unknown: "undocumented".into(),
143152 heading_level: 3,
153+ version_prefix: "".into(),
144154 removed_messages: vec![],
145155 segments: Vec::new(),
146156 },
@@ -165,6 +175,7 @@ fn segments() { · 18 unmodified lines
165175 name: changelog::Version::Semantic("0.7.0".parse().unwrap()),
166176 unknown: "".into(),
167177 heading_level: 3,
178+ version_prefix: Section::DEFAULT_PREFIX.into(),
168179 removed_messages: vec![],
169180 segments: vec![
170181 section::Segment::Conventional(section::segment::Conventional {
@@ -189,12 +200,14 @@ fn segments() { · 18 unmodified lines
189200 date: None,
190201 name: changelog::Version::Unreleased,
191202 heading_level: 3,
203+ version_prefix: Section::DEFAULT_PREFIX.into(),
192204 removed_messages: vec![],
193205 segments: vec![section::Segment::Clippy(section::Data::Parsed)], // only clippy still available
194206 unknown: Default::default(),
195207 },
196208 Section::Release {
197209 heading_level: 3,
210+ version_prefix: Section::DEFAULT_PREFIX.into(),
198211 removed_messages: vec![],
199212 date: Some(
200213 time::Date::from_calendar_date(2021, time::Month::September, 15)
@@ -213,6 +226,7 @@ fn segments() { · 12 unmodified lines
213226 name: changelog::Version::Semantic("0.8.0".parse().unwrap()),
214227 unknown: "".into(),
215228 heading_level: 3,
229+ version_prefix: Section::DEFAULT_PREFIX.into(),
216230 removed_messages: vec![],
217231 segments: vec![
218232 section::Segment::Details(section::Data::Parsed),
@@ -265,12 +279,14 @@ fn segments() { · 46 unmodified lines
265279 date: None,
266280 name: changelog::Version::Unreleased,
267281 heading_level: 3,
282+ version_prefix: Section::DEFAULT_PREFIX.into(),
268283 removed_messages: vec![],
269284 segments: segments.clone(),
270285 unknown: Default::default(),
271286 },
272287 Section::Release {
273288 heading_level: 3,
289+ version_prefix: Section::DEFAULT_PREFIX.into(),
274290 removed_messages: vec![],
275291 date: Some(
276292 time::Date::from_calendar_date(2021, time::Month::September, 15)
@@ -287,6 +303,7 @@ fn segments() { · 10 unmodified lines
287303 name: changelog::Version::Semantic("0.8.0".parse().unwrap()),
288304 unknown: "".into(),
289305 heading_level: 3,
306+ version_prefix: Section::DEFAULT_PREFIX.into(),
290307 removed_messages: vec![],
291308 segments: segments.clone(),
292309 },
@@ -295,6 +312,7 @@ fn segments() { · 2 unmodified lines
295312 name: changelog::Version::Semantic("0.7.0".parse().unwrap()),
296313 unknown: "".into(),
297314 heading_level: 3,
315+ version_prefix: Section::DEFAULT_PREFIX.into(),
298316 removed_messages: vec![],
299317 segments: {
300318 let mut v = segments.clone();
@@ -318,6 +336,7 @@ fn segments() { · 17 unmodified lines
318336 name: changelog::Version::Semantic("0.7.0".parse().unwrap()),
319337 unknown: "".into(),
320338 heading_level: 3,
339+ version_prefix: Section::DEFAULT_PREFIX.into(),
321340 removed_messages: vec![],
322341 segments: vec![
323342 section::Segment::Conventional(section::segment::Conventional {
@@ -347,12 +366,14 @@ fn segments() { · 23 unmodified lines
347366 date: None,
348367 name: changelog::Version::Unreleased,
349368 heading_level: 3,
369+ version_prefix: Section::DEFAULT_PREFIX.into(),
350370 removed_messages: vec![],
351371 segments: vec![clippy],
352372 unknown: Default::default(),
353373 },
354374 Section::Release {
355375 heading_level: 3,
376+ version_prefix: Section::DEFAULT_PREFIX.into(),
356377 removed_messages: vec![],
357378 date: Some(
358379 time::Date::from_calendar_date(2021, time::Month::September, 15)
@@ -378,6 +399,7 @@ fn segments() { · 19 unmodified lines
378399 name: changelog::Version::Semantic("0.8.0".parse().unwrap()),
379400 unknown: "".into(),
380401 heading_level: 3,
402+ version_prefix: Section::DEFAULT_PREFIX.into(),
381403 removed_messages: vec![],
382404 segments: vec![details, statistics],
383405 },
cargo-smart-release/tests/changelog/parse.rs+5−0
@@ -36,6 +36,7 @@ fn all_unknown_in_section() { · 35 unmodified lines
3636 removed_messages: vec![],
3737 date: None,
3838 heading_level: 3,
39+ version_prefix: "".into(),
3940 segments: vec![Segment::User {
4041 markdown: "- hello ~~this is not understood~~\n* this isn't either\n\n".into()
4142 }],
@@ -46,6 +47,7 @@ fn all_unknown_in_section() { · 4 unmodified lines
4647 removed_messages: vec![],
4748 date: None,
4849 heading_level: 4,
50+ version_prefix: Section::DEFAULT_PREFIX.into(),
4951 segments: vec![Segment::User {
5052 markdown: "Some free text in a paragraph\nthat won't parse.\n".into()
5153 }],
@@ -66,6 +68,7 @@ fn unknown_link_and_headling() { · 14 unmodified lines
6668 removed_messages: vec![],
6769 date: None,
6870 heading_level: 4,
71+ version_prefix: "".into(),
6972 segments: vec![Segment::User {
7073 markdown: "##### Special\n\nHello [there][194] period.\n".into()
7174 }],
@@ -90,6 +93,7 @@ fn known_and_unknown_sections_are_sorted() { · 18 unmodified lines
9093 removed_messages: vec![],
9194 date: None,
9295 heading_level: 3,
96+ version_prefix: "".into(),
9397 unknown: "".into(),
9498 segments: vec![Segment::User {
9599 markdown: "TBD\n".into()
@@ -100,6 +104,7 @@ fn known_and_unknown_sections_are_sorted() { · 4 unmodified lines
100104 removed_messages: vec![],
101105 date: None,
102106 heading_level: 3,
107+ version_prefix: Section::DEFAULT_PREFIX.into(),
103108 unknown: "".into(),
104109 segments: vec![
105110 Segment::User {
cargo-smart-release/tests/changelog/write_and_parse/mod.rs+3−0
@@ -18,6 +18,7 @@ fn conventional_write_empty_messages() -> Result { · 17 unmodified lines
1818 let log = ChangeLog {
1919 sections: vec![Section::Release {
2020 heading_level: 4,
21+ version_prefix: Section::DEFAULT_PREFIX.into(),
2122 date: Some(time::OffsetDateTime::from_unix_timestamp(0)?),
2223 name: changelog::Version::Semantic("1.0.2-beta.2".parse()?),
2324 removed_messages: vec![second_message],
@@ -92,11 +93,13 @@ fn all_section_types_round_trips_lossy() -> Result { · 68 unmodified lines
9293 removed_messages: vec![],
9394 date: None,
9495 name: changelog::Version::Unreleased,
96+ version_prefix: "".into(),
9597 segments: Vec::new(),
9698 unknown: "hello\nworld\n".into(),
9799 },
98100 Section::Release {
99101 heading_level: 4,
102+ version_prefix: "".into(),
100103 removed_messages: vec![],
101104 date: Some(time::OffsetDateTime::from_unix_timestamp(0)?),
102105 name: changelog::Version::Semantic("1.0.2-beta.2".parse()?),
cargo-smart-release/tests/changelog/write_and_parse/snapshots/integration__changelog__write_and_parse__all_section_types_round_trips_lossy-2.snap+2−1
@@ -13,7 +13,8 @@ my very own header · 12 unmodified lines
1313 hello
1414 world
1515 <csr-unknown/>
16−#### v1.0.2-beta.2 (1970-01-01)
16+
17+#### 1.0.2-beta.2 (1970-01-01)
1718
1819 * hello world
1920 this
cargo-smart-release/tests/changelog/write_and_parse/snapshots/integration__changelog__write_and_parse__all_section_types_round_trips_lossy-8.snap+1−1
@@ -3,7 +3,7 @@ source: cargo-smart-release/tests/changelog/write_and_parse/mod.rs · 2 unmodified lines
33 expression: buf
44
55 ---
6−#### v1.0.2-beta.2 (1970-01-01)
6+#### 1.0.2-beta.2 (1970-01-01)
77
88 * hello world
99 this
cargo-smart-release/tests/changelog/write_and_parse/snapshots/integration__changelog__write_and_parse__all_section_types_round_trips_lossy.snap+2−1
@@ -13,7 +13,8 @@ my very own header · 12 unmodified lines
1313 hello
1414 world
1515 <csr-unknown/>
16−#### v1.0.2-beta.2 (1970-01-01)
16+
17+#### 1.0.2-beta.2 (1970-01-01)
1718
1819 * hello world
1920 this

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t