Skip to content

Commit

Permalink
Add "show" command
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
  • Loading branch information
matthiasbeyer committed Mar 2, 2023
1 parent d28e81e commit 39d3c28
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ pub enum Command {
#[clap(long, default_value_t = false)]
allow_dirty: bool,
},

Show {
#[clap(long)]
format: Option<ShowFormat>,
#[clap(subcommand)]
range: Option<ShowRange>,
},
}

fn text_provider_parser(s: &str) -> Result<TextProvider, String> {
Expand Down Expand Up @@ -159,3 +166,16 @@ pub enum VersionSpec {
custom: String,
},
}

#[derive(Debug, Clone, PartialEq, Eq, clap::ValueEnum)]
pub enum ShowFormat {
Text,
Json,
}

#[derive(Clone, Debug, Subcommand)]
pub enum ShowRange {
Unreleased,
Exact { exact: String },
Range { from: String, until: String },
}
3 changes: 3 additions & 0 deletions src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ mod release_command;
pub use self::release_command::ReleaseCommand;
pub use self::release_command::VersionData;

mod show;
pub use self::show::Show;

mod verify_metadata_command;
pub use self::verify_metadata_command::VerifyMetadataCommand;

Expand Down
120 changes: 120 additions & 0 deletions src/command/show.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use std::{path::{Path, PathBuf}, io::BufReader};

use crate::{cli::{ShowRange, ShowFormat}, config::Configuration, error::{Error, FragmentError}, fragment::Fragment};

#[derive(Debug, typed_builder::TypedBuilder)]
pub struct Show {
format: Option<crate::cli::ShowFormat>,
range: Option<ShowRange>,
}

impl crate::command::Command for Show {
fn execute(self, workdir: &Path, config: &Configuration) -> Result<(), Error> {
fn walk_directory(path: &Path, filter_version: Option<&(semver::Version, semver::Version)>) -> Result<Vec<PathBuf>, Error> {
walkdir::WalkDir::new(path)
.follow_links(false)
.max_open(100)
.same_file_system(true)
.into_iter()
.filter_entry(|de| {
log::debug!("Looking at {de:?}");
if de.path().is_dir() {
true
} else if de.path().is_file() {
de.path().components().any(|comp| match comp {
std::path::Component::Normal(osstr) => osstr.to_str()
.map(|s| {
if let Ok(version) = semver::Version::parse(s) {
if let Some((from, until)) = filter_version {
version > *from && version < *until
} else {
true
}
}
else {
false
}
})
.unwrap_or(false),
_ => false,
})
} else {
false
}
})
.filter_map(|rde| match rde {
Ok(de) => de.path().is_file().then(|| de.path().to_path_buf()).map(Ok),
Err(e) => Some(Err(Error::from(e))),
})
.collect::<Result<Vec<PathBuf>, Error>>()
}

let pathes = match self.range {
None | Some(ShowRange::Unreleased) => {
let unreleased_dir_path = workdir
.join(config.fragment_dir())
.join(crate::consts::UNRELEASED_DIR_NAME);
walk_directory(&unreleased_dir_path, None)?
}
Some(ShowRange::Exact { exact }) => {
let path = workdir.join(config.fragment_dir()).join(&exact);
if !path.exists() {
return Err(Error::ExactVersionDoesNotExist { version: exact });
}
walk_directory(&path, None)?
}
Some(ShowRange::Range { from, until }) => {
let from = semver::Version::parse(&from)?;
let until = semver::Version::parse(&until)?;

let fragment_dir_path = workdir.join(config.fragment_dir());
walk_directory(&fragment_dir_path, Some(&(from, until)))?
}
};

let fragments = pathes
.into_iter()
.map(|path| {
std::fs::OpenOptions::new()
.read(true)
.create(false)
.write(false)
.open(&path)
.map_err(FragmentError::from)
.map(BufReader::new)
.and_then(|mut reader| Fragment::from_reader(&mut reader))
.map_err(|e| Error::FragmentError(e, path.to_path_buf()))
});

match self.format {
None | Some(ShowFormat::Text) => pretty_print(fragments),
Some(ShowFormat::Json) => json_print(fragments),
}
}
}

fn pretty_print(iter: impl Iterator<Item = Result<Fragment, Error>>) -> Result<(), Error> {
use std::io::Write;

let out = std::io::stdout();
let mut output = out.lock();

iter.map(|fragment| {
let fragment = fragment?;
fragment.header()
.iter()
.map(|(key, value)| {
writeln!(output, "{key}: {value}", value = value.display())?;
Ok(()) as Result<(), Error>
})
.collect::<Result<_, _>>()?;

writeln!(output, "{text}", text = fragment.text())?;
Ok(())
})
.collect::<Result<(), _>>()
}

fn json_print(_iter: impl Iterator<Item = Result<Fragment, Error>>) -> Result<(), Error> {
unimplemented!()
}
6 changes: 6 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ fn main() -> miette::Result<()> {
.allow_dirty(allow_dirty)
.build()
.execute(&repo_workdir_path, &config)?,

Command::Show { format, range } => crate::command::Show::builder()
.format(format)
.range(range)
.build()
.execute(&repo_workdir_path, &config)?,
}

Ok(())
Expand Down

0 comments on commit 39d3c28

Please sign in to comment.