Skip to content

Commit

Permalink
feat(cli/bump): persist changes to disk
Browse files Browse the repository at this point in the history
  • Loading branch information
justinrubek committed May 13, 2024
1 parent 34b0deb commit 6e20c30
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 48 deletions.
157 changes: 109 additions & 48 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ use bomper::{
config::Config,
error::{Error, Result},
replacers::{
cargo::CargoReplacer, search::SearchReplacer, simple::SimpleReplacer, Replacer,
VersionReplacement,
cargo::CargoReplacer, file::FileReplacer, search::SearchReplacer, simple::SimpleReplacer,
Replacer, VersionReplacement,
},
versioning::{
determine_increment, get_commits_since_tag, get_latest_tag, increment_version,
VersionIncrement,
},
};
use std::io::Write;

pub struct App {
pub args: BaseArgs,
Expand Down Expand Up @@ -55,66 +56,126 @@ impl App {
_ => unreachable!(),
};
let new_version = increment_version(tag.version.clone(), increment);
println!("New version: {}", new_version);
let changelog_entry = generate_changelog_entry(&commits, &new_version);
println!("{}", changelog_entry);
todo!()

let replacement = VersionReplacement {
old_version: tag.version.to_string(),
new_version: new_version.to_string(),
};
let mut file_changes = determine_changes(&self.config, &replacement)?;
file_changes.push(apply_changelog(changelog_entry)?);
apply_changes(file_changes, &self.args)?;

Ok(())
}

pub fn raw_bump(&self, opts: &RawBump) -> Result<()> {
// self.config.file.clone().par_drain().for_each(|path| {
let versions = VersionReplacement {
let replacement = VersionReplacement {
old_version: opts.old_version.clone(),
new_version: opts.new_version.clone(),
};
let mut files_to_replace = Vec::new();

let by_file = &self.config.by_file;
if let Some(by_file) = by_file {
for (path, config) in by_file {
let mut replacers = match &config.search_value {
Some(value) => SearchReplacer::new(
path.clone(),
&opts.old_version,
value,
&opts.new_version,
)?
.determine_replacements()?,
None => {
SimpleReplacer::new(path.clone(), &opts.old_version, &opts.new_version)?
.determine_replacements()?
}
};

// append new replacers to the list
if let Some(replacers) = &mut replacers {
files_to_replace.append(replacers);
}
}
let file_changes = determine_changes(&self.config, &replacement)?;
apply_changes(file_changes, &self.args)?;

Ok(())
}
}

/// Persist file changes to the filesystem.
/// This function is responsible for respecting the `dry_run` flag, so it will only persist changes
/// if the flag is not set.
fn apply_changes(changes: Vec<FileReplacer>, args: &BaseArgs) -> Result<()> {
if args.dry_run {
println!("Dry run, not persisting changes");
for replacer in changes {
println!("Would have replaced: {}", replacer.path.display());
}

let cargo_lock = &self.config.cargo;
if let Some(cargo_lock) = cargo_lock {
let replacer = CargoReplacer::new(versions, cargo_lock.clone())?;
let mut files = replacer.determine_replacements()?;
if let Some(files) = &mut files {
files_to_replace.append(files);
}
return Ok(());
} else {
for replacer in changes {
replacer.persist()?;
}
}

if self.args.dry_run {
println!("Dry run, not persisting changes");
for replacer in files_to_replace {
println!("Would have replaced: {}", replacer.path.display());
}
Ok(())
}

/// Determine the changes to make to the repository to update the version.
fn determine_changes(
config: &Config,
replacement: &VersionReplacement,
) -> Result<Vec<FileReplacer>> {
let mut files_to_replace = Vec::new();

return Ok(());
} else {
for replacer in files_to_replace {
replacer.persist()?;
let by_file = &config.by_file;
if let Some(by_file) = by_file {
for (path, config) in by_file {
let mut replacers = match &config.search_value {
Some(value) => SearchReplacer::new(
path.clone(),
&replacement.old_version,
value,
&replacement.new_version,
)?
.determine_replacements()?,
None => SimpleReplacer::new(
path.clone(),
&replacement.old_version,
&replacement.new_version,
)?
.determine_replacements()?,
};

// append new replacers to the list
if let Some(replacers) = &mut replacers {
files_to_replace.append(replacers);
}
}
}

Ok(())
let cargo_lock = &config.cargo;
if let Some(cargo_lock) = cargo_lock {
let replacer = CargoReplacer::new(replacement.clone(), cargo_lock.clone())?;
let mut files = replacer.determine_replacements()?;
if let Some(files) = &mut files {
files_to_replace.append(files);
}
}

Ok(files_to_replace)
}

/// Stitch together the existing changelog with the new one.
/// This is done using `- - -` as a marker character.
/// The new changelog is composed of the changelog header (everything from the start to the first
/// marker`, the new entry (with a marker on top), and the remaining part of the previous changelog
fn create_changelog(path: &std::path::Path, contents: &str) -> Result<String> {
const MARKER: &str = "- - -";

match std::path::Path::try_exists(path) {
Ok(true) => {
let original_changelog = std::fs::read_to_string(path)?;
let start = original_changelog
.find(MARKER)
.ok_or(Error::ChangelogMarker)?;

let header = &original_changelog[..start];
let rest = &original_changelog[start..];
Ok(format!("{header}\n{MARKER}\n{contents}\n{rest}"))
}
Ok(false) => Ok(format!("# Changelog\n\n{MARKER}\n{contents}")),
Err(e) => Err(e.into()),
}
}

fn apply_changelog(entry: String) -> Result<FileReplacer> {
let path = std::path::PathBuf::from("CHANGELOG.md");
let new_changelog = create_changelog(&path, &entry)?;

let temp_file = tempfile::NamedTempFile::new_in(".")?;
let mut file = temp_file.as_file();
file.write_all(new_changelog.as_bytes())?;

Ok(FileReplacer { path, temp_file })
}
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub enum Error {
ProjectBaseDirectory,
#[error("unable to determine the most recent tag")]
TagError,
#[error("changelog does not contain marker character")]
ChangelogMarker,
}

impl std::fmt::Debug for Error {
Expand Down
1 change: 1 addition & 0 deletions src/replacers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub trait Replacer {
fn determine_replacements(self) -> Result<Option<Vec<FileReplacer>>>;
}

#[derive(Clone, Debug)]
pub struct VersionReplacement {
pub old_version: String,
pub new_version: String,
Expand Down

0 comments on commit 6e20c30

Please sign in to comment.