use crate::errors::BumperError; use glob::glob; use log::{debug, info}; use std::path::{Path, PathBuf}; use std::process::Command; pub struct Python { dirname: PathBuf, version_pys: Vec, } impl Python { pub fn new(dirname: &Path) -> Result { let setup_py = dirname.join("setup.py"); debug!("does {} exist? {}", setup_py.display(), setup_py.exists()); if setup_py.exists() { let files = find_version_py_files(dirname); if files.is_empty() { debug!("no version.py files in {}", dirname.display()); Err(BumperError::NoVersionPy(dirname.to_path_buf())) } else { Ok(Self { dirname: dirname.to_path_buf(), version_pys: files, }) } } else { Err(BumperError::UnknownProjectKind(dirname.to_path_buf())) } } pub fn name(&mut self) -> Result { let output = Command::new("./setup.py") .arg("--name") .current_dir(&self.dirname) .output() .map_err(|err| BumperError::Setupnvoke(self.dirname.to_path_buf(), err))?; if output.status.success() { let name = String::from_utf8_lossy(&output.stdout).into_owned(); Ok(name.trim_end().to_string()) } else { let stderr = String::from_utf8_lossy(&output.stderr).into_owned(); Err(BumperError::Setup(self.dirname.to_path_buf(), stderr)) } } pub fn set_version(&mut self, version: &str) -> Result { for filename in self.version_pys.iter() { info!("writing Python version to {}", filename.display()); std::fs::write(filename, format!("__version__ = \"{}\"\n", version)) .map_err(|err| BumperError::PythonWrite(filename.to_path_buf(), err))?; } Ok(version.to_string()) } } fn find_version_py_files(dirname: &Path) -> Vec { glob(&dirname.join("*/version.py").display().to_string()) .expect("glob pattern error") .filter(|x| x.is_ok()) .map(|x| x.unwrap()) .collect() }