Compare commits
3 commits
6a1e438c94
...
24a99d2957
| Author | SHA1 | Date | |
|---|---|---|---|
| 24a99d2957 | |||
| 8a92bf2637 | |||
| 8319a4f118 |
5 changed files with 109 additions and 12 deletions
|
|
@ -99,6 +99,12 @@ enum Commands {
|
||||||
issue_id: String,
|
issue_id: String,
|
||||||
done_time: Option<String>,
|
done_time: Option<String>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// get or add a dependency to the issue
|
||||||
|
Depend {
|
||||||
|
issue_id: String,
|
||||||
|
dependency_id: Option<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_command(
|
fn handle_command(
|
||||||
|
|
@ -510,6 +516,43 @@ fn handle_command(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Commands::Depend {
|
||||||
|
issue_id,
|
||||||
|
dependency_id,
|
||||||
|
} => match dependency_id {
|
||||||
|
Some(dep_id) => {
|
||||||
|
let ent_db = entomologist::database::make_issues_database(
|
||||||
|
issues_database_source,
|
||||||
|
entomologist::database::IssuesDatabaseAccess::ReadWrite,
|
||||||
|
)?;
|
||||||
|
let mut issues = entomologist::issues::Issues::new_from_dir(&ent_db.dir)?;
|
||||||
|
if issues.issues.contains_key(dep_id) {
|
||||||
|
if let Some(issue) = issues.issues.get_mut(issue_id) {
|
||||||
|
issue.add_dependency(dep_id.clone())?;
|
||||||
|
} else {
|
||||||
|
Err(anyhow::anyhow!("issue {} not found", issue_id))?;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
Err(anyhow::anyhow!("dependency {} not found", dep_id))?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let ent_db = entomologist::database::read_issues_database(issues_database_source)?;
|
||||||
|
|
||||||
|
let Some(issue) = ent_db.issues.get(issue_id) else {
|
||||||
|
Err(anyhow::anyhow!("issue {} not found", issue_id))?
|
||||||
|
};
|
||||||
|
println!("DEPENDENCIES:");
|
||||||
|
if let Some(list) = &issue.dependencies {
|
||||||
|
for dependency in list {
|
||||||
|
println!("{}", dependency);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("NONE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -531,7 +574,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
(Some(_), Some(_)) => {
|
(Some(_), Some(_)) => {
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
"don't specify both `--issues-dir` and `--issues-branch`"
|
"don't specify both `--issues-dir` and `--issues-branch`"
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
74
src/issue.rs
74
src/issue.rs
|
|
@ -62,6 +62,12 @@ pub enum IssueError {
|
||||||
StdioIsNotTerminal,
|
StdioIsNotTerminal,
|
||||||
#[error("Failed to parse issue ID")]
|
#[error("Failed to parse issue ID")]
|
||||||
IdError,
|
IdError,
|
||||||
|
#[error("Dependency not found")]
|
||||||
|
DepNotFound,
|
||||||
|
#[error("Dependency already exists")]
|
||||||
|
DepExists,
|
||||||
|
#[error("Self-dependency not allowed")]
|
||||||
|
DepSelf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for State {
|
impl FromStr for State {
|
||||||
|
|
@ -128,15 +134,8 @@ impl Issue {
|
||||||
std::fs::read_to_string(direntry.path())?.trim(),
|
std::fs::read_to_string(direntry.path())?.trim(),
|
||||||
)?;
|
)?;
|
||||||
done_time = Some(raw_done_time.into());
|
done_time = Some(raw_done_time.into());
|
||||||
} else if file_name == "dependencies" {
|
} else if file_name == "dependencies" && direntry.metadata()?.is_dir() {
|
||||||
let dep_strings = std::fs::read_to_string(direntry.path())?;
|
dependencies = Self::read_dependencies(&direntry.path())?;
|
||||||
let deps: Vec<IssueHandle> = dep_strings
|
|
||||||
.lines()
|
|
||||||
.map(|dep| IssueHandle::from(dep))
|
|
||||||
.collect();
|
|
||||||
if deps.len() > 0 {
|
|
||||||
dependencies = Some(deps);
|
|
||||||
}
|
|
||||||
} else if file_name == "tags" {
|
} else if file_name == "tags" {
|
||||||
let contents = std::fs::read_to_string(direntry.path())?;
|
let contents = std::fs::read_to_string(direntry.path())?;
|
||||||
tags = contents
|
tags = contents
|
||||||
|
|
@ -199,6 +198,23 @@ impl Issue {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_dependencies(dir: &std::path::Path) -> Result<Option<Vec<IssueHandle>>, IssueError> {
|
||||||
|
let mut dependencies: Option<Vec<String>> = None;
|
||||||
|
for direntry in dir.read_dir()? {
|
||||||
|
if let Ok(direntry) = direntry {
|
||||||
|
match &mut dependencies {
|
||||||
|
Some(deps) => {
|
||||||
|
deps.push(direntry.file_name().into_string().unwrap());
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
dependencies = Some(vec![direntry.file_name().into_string().unwrap()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(dependencies)
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a new Comment to the Issue. Commits.
|
/// Add a new Comment to the Issue. Commits.
|
||||||
pub fn add_comment(
|
pub fn add_comment(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -407,6 +423,46 @@ impl Issue {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_dependency(&mut self, dep: IssueHandle) -> Result<(), IssueError> {
|
||||||
|
if self.id == dep {
|
||||||
|
Err(IssueError::DepSelf)?;
|
||||||
|
}
|
||||||
|
match &mut self.dependencies {
|
||||||
|
Some(v) => v.push(dep.clone()),
|
||||||
|
None => self.dependencies = Some(vec![dep.clone()]),
|
||||||
|
}
|
||||||
|
let mut dir = std::path::PathBuf::from(&self.dir);
|
||||||
|
dir.push("dependencies");
|
||||||
|
if !dir.exists() {
|
||||||
|
std::fs::create_dir(&dir)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir.push(dep.clone());
|
||||||
|
|
||||||
|
if !dir.exists() {
|
||||||
|
std::fs::File::create(&dir)?;
|
||||||
|
self.commit(&format!("add dep {} to issue {}", dep, self.id))?;
|
||||||
|
} else {
|
||||||
|
Err(IssueError::DepExists)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_dependency(&mut self, dep: IssueHandle) -> Result<(), IssueError> {
|
||||||
|
match &mut self.dependencies {
|
||||||
|
Some(v) => {
|
||||||
|
if let Some(i) = v.iter().position(|d| d == &dep) {
|
||||||
|
v.remove(i);
|
||||||
|
} else {
|
||||||
|
Err(IssueError::DepNotFound)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => Err(IssueError::DepNotFound)?,
|
||||||
|
}
|
||||||
|
self.commit(&format!("remove dep {} from issue {}", dep, self.id))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the internal/private API of Issue.
|
// This is the internal/private API of Issue.
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
3fa5bfd93317ad25772680071d5ac3259cd2384f
|
|
||||||
dd79c8cfb8beeacd0460429944b4ecbe95a31561
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue