Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zvv/changelog internalize path #669

Merged
merged 8 commits into from
Nov 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 55 additions & 38 deletions crates/cli-tools/src/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,23 @@ impl Display for Severity {

#[derive(Debug, Default, PartialEq, Eq)]
struct Changelog {
crate_path: String,
exzachlyvv marked this conversation as resolved.
Show resolved Hide resolved
releases: Vec<Release>,
skip_counter: u32,
}

impl Changelog {
async fn read_file(path: &str) -> Result<Changelog> {
Self::parse(&String::from_utf8(fs::read(path).await?)?)
fn changelog_path(&self) -> String {
format!("{}/CHANGELOG.md", self.crate_path)
}

async fn write_file(&self, path: &str) -> Result<()> {
fs::write(path, self.to_string().as_bytes()).await
async fn read(path: &str) -> Result<Changelog> {
let changelog_path = format!("{path}/CHANGELOG.md");
Self::parse(path, &String::from_utf8(fs::read(changelog_path).await?)?)
}

async fn write(&self) -> Result<()> {
fs::write(self.changelog_path(), self.to_string().as_bytes()).await
}

fn push_description(&mut self, severity: Severity, content: &str) -> Result<()> {
Expand Down Expand Up @@ -91,7 +97,7 @@ impl Changelog {
}

/// Parses and validates a changelog.
fn parse(input: &str) -> Result<Changelog> {
fn parse(crate_path: impl Into<String>, input: &str) -> Result<Changelog> {
let mut releases: Vec<Release> = Vec::new();
let mut parser = Parser::new(input.lines());
parser.read_exact("# Changelog")?;
Expand Down Expand Up @@ -166,12 +172,13 @@ impl Changelog {
.parse()
.with_context(|| anyhow!("Invalid skip counter {parser}"))?;
parser.done()?;
let result = Changelog { releases, skip_counter };
let result = Changelog { crate_path: crate_path.into(), releases, skip_counter };
assert_eq!(format!("{result}"), input);
Ok(result)
}

async fn validate_cargo_toml(&self, path: &str) -> Result<()> {
async fn validate_cargo_toml(&self) -> Result<()> {
let path = &self.crate_path;
let metadata = metadata(path).await?;
ensure!(
self.releases.first().unwrap().version == metadata.packages[0].version,
Expand All @@ -180,19 +187,19 @@ impl Changelog {
Ok(())
}

async fn sync_cargo_toml(&self, path: &str) -> Result<()> {
async fn sync_cargo_toml(&self) -> Result<()> {
let expected_version = &self.releases.first().unwrap().version;

let mut sed = Command::new("sed");
sed.arg("-i");
sed.arg(format!("s#^version = .*#version = \"{expected_version}\"#"));
sed.arg("Cargo.toml");
cmd::execute(sed.current_dir(path)).await?;
cmd::execute(sed.current_dir(&self.crate_path)).await?;

Ok(())
}

async fn sync_dependencies(&self, _path: &str) -> Result<()> {
async fn sync_dependencies(&self) -> Result<()> {
// TODO

Ok(())
Expand All @@ -201,7 +208,7 @@ impl Changelog {

impl Display for Changelog {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Changelog { releases, skip_counter } = self;
let Changelog { releases, skip_counter, .. } = self;
writeln!(f, "# Changelog\n")?;
for release in releases {
write!(f, "{release}")?;
Expand Down Expand Up @@ -316,23 +323,19 @@ pub async fn execute_ci() -> Result<()> {
let paths = cmd::output(Command::new("git").args(["ls-files", "*/CHANGELOG.md"])).await?;
for path in paths.stdout.lines() {
let path = path?;
let changelog = Changelog::read_file(&path).await?;
changelog.validate_cargo_toml(path.strip_suffix("/CHANGELOG.md").unwrap()).await?;
let changelog = Changelog::read(path.strip_suffix("/CHANGELOG.md").unwrap()).await?;
changelog.validate_cargo_toml().await?;
}
Ok(())
}

/// Updates a changelog file and changelog files of dependencies.
pub async fn execute_change(path: &str, severity: Severity, description: &str) -> Result<()> {
let changelog_file_path = format!("{path}/CHANGELOG.md");

let mut changelog = Changelog::read_file(&changelog_file_path).await?;

let mut changelog = Changelog::read(path).await?;
changelog.push_description(severity, description)?;
changelog.write_file(&changelog_file_path).await?;
changelog.sync_cargo_toml(path).await?;
changelog.sync_dependencies(path).await?;

changelog.write().await?;
changelog.sync_cargo_toml().await?;
changelog.sync_dependencies().await?;
Ok(())
}

Expand Down Expand Up @@ -384,8 +387,9 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap(),
Changelog::parse("path", changelog).unwrap(),
Changelog {
crate_path: "path".to_string(),
releases: vec![
Release {
version: Version::parse("0.3.0").unwrap(),
Expand Down Expand Up @@ -492,7 +496,7 @@ mod tests {
<!-- Increment to skip CHANGELOG.md test: 0 -->
";

assert_eq!(format!("{}", Changelog::parse(changelog).unwrap()), changelog);
assert_eq!(format!("{}", Changelog::parse("", changelog).unwrap()), changelog);
}

#[test]
Expand Down Expand Up @@ -526,8 +530,9 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap(),
Changelog::parse("path", changelog).unwrap(),
Changelog {
crate_path: "path".to_string(),
releases: vec![
Release {
version: Version::parse("0.2.0").unwrap(),
Expand Down Expand Up @@ -579,8 +584,9 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap(),
Changelog::parse("path", changelog).unwrap(),
Changelog {
crate_path: "path".to_string(),
releases: vec![
Release {
version: Version::parse("0.2.0").unwrap(),
Expand Down Expand Up @@ -619,7 +625,7 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap_err().to_string(),
Changelog::parse("", changelog).unwrap_err().to_string(),
"Description ends with dot line 7"
);
}
Expand All @@ -634,8 +640,9 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap(),
Changelog::parse("path", changelog).unwrap(),
Changelog {
crate_path: "path".to_string(),
releases: vec![Release {
version: Version::parse("0.1.0").unwrap(),
contents: BTreeMap::new(),
Expand All @@ -655,8 +662,9 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap(),
Changelog::parse("path", changelog).unwrap(),
Changelog {
crate_path: "path".to_string(),
releases: vec![Release {
version: Version::parse("0.1.0").unwrap(),
contents: BTreeMap::new(),
Expand All @@ -675,7 +683,7 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap_err().to_string(),
Changelog::parse("", changelog).unwrap_err().to_string(),
"Unexpected end of file after line 4"
);
}
Expand All @@ -686,7 +694,7 @@ mod tests {
## 0.1.0";

assert_eq!(
Changelog::parse(changelog).unwrap_err().to_string(),
Changelog::parse("", changelog).unwrap_err().to_string(),
"Line 1 should be \"# Changelog\""
);
}
Expand All @@ -711,7 +719,7 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap_err().to_string(),
Changelog::parse("", changelog).unwrap_err().to_string(),
"Release 0.1.1 should be 0.3.0 due to major bump from 0.2.0"
);
}
Expand All @@ -723,7 +731,10 @@ mod tests {
<!-- Increment to skip CHANGELOG.md test: 0 -->
";

assert_eq!(Changelog::parse(changelog).unwrap_err().to_string(), "Expected release line 3");
assert_eq!(
Changelog::parse("", changelog).unwrap_err().to_string(),
"Expected release line 3"
);
}

#[test]
Expand All @@ -739,7 +750,10 @@ mod tests {
<!-- Increment to skip CHANGELOG.md test: 0 -->
";

assert_eq!(Changelog::parse(changelog).unwrap_err().to_string(), "Expected release line 9");
assert_eq!(
Changelog::parse("", changelog).unwrap_err().to_string(),
"Expected release line 9"
);
}

#[test]
Expand All @@ -756,7 +770,7 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap_err().to_string(),
Changelog::parse("", changelog).unwrap_err().to_string(),
"Invalid skip counter prefix line 5"
);
}
Expand All @@ -781,7 +795,7 @@ mod tests {
";

assert_eq!(
Changelog::parse(changelog).unwrap_err().to_string(),
Changelog::parse("", changelog).unwrap_err().to_string(),
"Unexpected prerelease line 9"
);
}
Expand All @@ -801,7 +815,8 @@ mod tests {
<!-- Increment to skip CHANGELOG.md test: 0 -->
";

let mut changelog = Changelog::parse(changelog_str).expect("Failed to parse changelog.");
let mut changelog =
Changelog::parse("", changelog_str).expect("Failed to parse changelog.");

changelog.push_description(Severity::Major, "testing no dash").unwrap();
changelog.push_description(Severity::Major, "- testing with dash").unwrap();
Expand Down Expand Up @@ -831,7 +846,8 @@ mod tests {
<!-- Increment to skip CHANGELOG.md test: 0 -->
";

let mut changelog = Changelog::parse(changelog_str).expect("Failed to parse changelog.");
let mut changelog =
Changelog::parse("", changelog_str).expect("Failed to parse changelog.");

let current_release = changelog.get_or_create_release_mut();

Expand All @@ -853,7 +869,8 @@ mod tests {
<!-- Increment to skip CHANGELOG.md test: 0 -->
";

let mut changelog = Changelog::parse(changelog_str).expect("Failed to parse changelog.");
let mut changelog =
Changelog::parse("", changelog_str).expect("Failed to parse changelog.");

let current_release = changelog.get_or_create_release_mut();

Expand Down
Loading