|
|
@ -17,6 +17,7 @@ pub struct Project {
|
|
|
|
path: PathBuf,
|
|
|
|
path: PathBuf,
|
|
|
|
name: String,
|
|
|
|
name: String,
|
|
|
|
msrv: Option<Version>,
|
|
|
|
msrv: Option<Version>,
|
|
|
|
|
|
|
|
crate_version: Version,
|
|
|
|
pub repo: Box<dyn Repository>,
|
|
|
|
pub repo: Box<dyn Repository>,
|
|
|
|
profile_map: HashMap<String, String>, // vcs profile name to branch names
|
|
|
|
profile_map: HashMap<String, String>, // vcs profile name to branch names
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -48,12 +49,17 @@ impl Project {
|
|
|
|
.to_owned();
|
|
|
|
.to_owned();
|
|
|
|
|
|
|
|
|
|
|
|
let repo = GitRepository::open(&path)?;
|
|
|
|
let repo = GitRepository::open(&path)?;
|
|
|
|
let msrv = Self::parse_msrv(&path)?;
|
|
|
|
let msrv = Self::parse_version(&path, "rust-version")?;
|
|
|
|
|
|
|
|
let crate_version = match Self::parse_version(&path, "version")? {
|
|
|
|
|
|
|
|
Some(v) => v,
|
|
|
|
|
|
|
|
None => return Err(Error::cargo_error("Crate version not found")),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
Ok(Self {
|
|
|
|
path,
|
|
|
|
path,
|
|
|
|
name,
|
|
|
|
name,
|
|
|
|
msrv,
|
|
|
|
msrv,
|
|
|
|
|
|
|
|
crate_version,
|
|
|
|
repo,
|
|
|
|
repo,
|
|
|
|
profile_map,
|
|
|
|
profile_map,
|
|
|
|
})
|
|
|
|
})
|
|
|
@ -67,9 +73,25 @@ impl Project {
|
|
|
|
&self.path
|
|
|
|
&self.path
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn current_ref(&self) -> Result<Option<String>, Error> {
|
|
|
|
|
|
|
|
match self.repo.current_ref() {
|
|
|
|
|
|
|
|
Ok(val) => Ok(Some(val)),
|
|
|
|
|
|
|
|
Err(err) => {
|
|
|
|
|
|
|
|
eprintln!("{}: {}\n", self.name(), err);
|
|
|
|
|
|
|
|
Ok(None)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn current_profile(&self) -> Result<Option<String>, Error> {
|
|
|
|
pub fn current_profile(&self) -> Result<Option<String>, Error> {
|
|
|
|
let current_ref = self.repo.current_ref()?;
|
|
|
|
// repo.current_ref can fail if repo has no head yet (e.g. post init)
|
|
|
|
if let Some(val) = self.profile_map.iter().find(|v| v.1 == ¤t_ref) {
|
|
|
|
let current_ref = self.current_ref()?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(val) = self
|
|
|
|
|
|
|
|
.profile_map
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.find(|v| Some(v.1) == current_ref.as_ref())
|
|
|
|
|
|
|
|
{
|
|
|
|
return Ok(Some(val.0.clone()));
|
|
|
|
return Ok(Some(val.0.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -92,18 +114,18 @@ impl Project {
|
|
|
|
self.msrv.as_ref()
|
|
|
|
self.msrv.as_ref()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn parse_msrv(path: &Path) -> Result<Option<Version>, Error> {
|
|
|
|
fn parse_version(path: &Path, key: &str) -> Result<Option<Version>, Error> {
|
|
|
|
let toml_path = path.join("Cargo.toml");
|
|
|
|
let toml_path = path.join("Cargo.toml");
|
|
|
|
let toml_contents = std::fs::read_to_string(toml_path)?;
|
|
|
|
let toml_contents = std::fs::read_to_string(toml_path)?;
|
|
|
|
|
|
|
|
|
|
|
|
let cargo: toml::Value = toml::from_str(&toml_contents)?;
|
|
|
|
let cargo: toml::Value = toml::from_str(&toml_contents)?;
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(pkg) = cargo.get("package") {
|
|
|
|
if let Some(pkg) = cargo.get("package") {
|
|
|
|
if let Some(value) = pkg.get("rust-version") {
|
|
|
|
if let Some(value) = pkg.get(key) {
|
|
|
|
if value.is_str() {
|
|
|
|
if value.is_str() {
|
|
|
|
let mut ver_str = value
|
|
|
|
let mut ver_str = value
|
|
|
|
.as_str()
|
|
|
|
.as_str()
|
|
|
|
.ok_or_else(|| Error::cargo_error("Unparsable rust-version in Cargo.toml"))?
|
|
|
|
.ok_or_else(|| Error::cargo_error("Unparsable version in Cargo.toml"))?
|
|
|
|
.to_owned();
|
|
|
|
.to_owned();
|
|
|
|
let dots = ver_str.chars().filter(|c| *c == '.').count();
|
|
|
|
let dots = ver_str.chars().filter(|c| *c == '.').count();
|
|
|
|
if !(1..=2).contains(&dots) {
|
|
|
|
if !(1..=2).contains(&dots) {
|
|
|
@ -125,9 +147,12 @@ impl Project {
|
|
|
|
|
|
|
|
|
|
|
|
pub fn display(&self, options: EnumSet<ProjectDisplayOptions>) -> Result<Tree<String>, Error> {
|
|
|
|
pub fn display(&self, options: EnumSet<ProjectDisplayOptions>) -> Result<Tree<String>, Error> {
|
|
|
|
let title = format!(
|
|
|
|
let title = format!(
|
|
|
|
"{}: {} [{}]",
|
|
|
|
"{}@{}: {} [{}]",
|
|
|
|
self.name().bold().with(PROJECT_COLOR),
|
|
|
|
self.name().bold().with(PROJECT_COLOR),
|
|
|
|
self.repo.current_ref()?.with(REFS_COLOR),
|
|
|
|
format!("v{}", self.crate_version).with(VERSION_COLOR),
|
|
|
|
|
|
|
|
self.current_ref()?
|
|
|
|
|
|
|
|
.unwrap_or_else(|| "???".into())
|
|
|
|
|
|
|
|
.with(REFS_COLOR),
|
|
|
|
format!("{}", self.path().display()).italic(),
|
|
|
|
format!("{}", self.path().display()).italic(),
|
|
|
|
);
|
|
|
|
);
|
|
|
|
let mut root = Tree::new(title);
|
|
|
|
let mut root = Tree::new(title);
|
|
|
|