From 09373cda56ecc1b00478a28a55a1cb7e8a76d341 Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Sun, 6 Jul 2025 00:12:22 -0600 Subject: [PATCH] add `ent new` --- src/bin/ent/main.rs | 21 ++++++++++-------- src/issue.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index 65e36dc..e0dca3c 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -22,10 +22,7 @@ enum Commands { List, /// Create a new issue. - New { - title: Option, - description: Option, - }, + New { description: Option }, } fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<()> { @@ -37,11 +34,17 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( println!("{} {} ({:?})", uuid, issue.title(), issue.state); } } - Commands::New { title, description } => { - println!( - "should make a new issue, title={:?}, description={:?}", - title, description - ); + Commands::New { + description: Some(description), + } => { + let mut issue = entomologist::issue::Issue::new(issues_dir)?; + issue.set_description(description)?; + println!("created new issue '{}'", issue.title()); + } + Commands::New { description: None } => { + let mut issue = entomologist::issue::Issue::new(issues_dir)?; + issue.edit_description()?; + println!("created new issue '{}'", issue.title()); } } diff --git a/src/issue.rs b/src/issue.rs index 753454b..b91d3c6 100644 --- a/src/issue.rs +++ b/src/issue.rs @@ -1,3 +1,4 @@ +use std::io::Write; use std::str::FromStr; #[derive(Debug, PartialEq, serde::Deserialize)] @@ -30,6 +31,10 @@ pub enum IssueError { StdIoError(#[from] std::io::Error), #[error("Failed to parse issue")] IssueParseError, + #[error("Failed to run git")] + GitError(#[from] crate::git::GitError), + #[error("Failed to run editor")] + EditorError, } impl FromStr for State { @@ -95,6 +100,53 @@ impl Issue { }) } + pub fn new(dir: &std::path::Path) -> Result { + let mut issue_dir = std::path::PathBuf::from(dir); + let rnd: u128 = rand::random(); + issue_dir.push(&format!("{:0x}", rnd)); + std::fs::create_dir(&issue_dir)?; + Ok(Self { + description: String::from(""), // FIXME: kind of bogus to use the empty string as None + state: State::New, + dependencies: None, + dir: issue_dir, + }) + } + + pub fn set_description(&mut self, description: &str) -> Result<(), IssueError> { + self.description = String::from(description); + let mut description_filename = std::path::PathBuf::from(&self.dir); + description_filename.push("description"); + let mut description_file = std::fs::File::create(&description_filename)?; + write!(description_file, "{}", description)?; + crate::git::git_commit_file(&description_filename)?; + Ok(()) + } + + pub fn read_description(&mut self) -> Result<(), IssueError> { + let mut description_filename = std::path::PathBuf::from(&self.dir); + description_filename.push("description"); + self.description = std::fs::read_to_string(description_filename)?; + Ok(()) + } + + pub fn edit_description(&mut self) -> Result<(), IssueError> { + let mut description_filename = std::path::PathBuf::from(&self.dir); + description_filename.push("description"); + let result = std::process::Command::new("vi") + .arg(&description_filename.as_mut_os_str()) + .spawn()? + .wait_with_output()?; + if !result.status.success() { + println!("stdout: {}", std::str::from_utf8(&result.stdout).unwrap()); + println!("stderr: {}", std::str::from_utf8(&result.stderr).unwrap()); + return Err(IssueError::EditorError); + } + crate::git::git_commit_file(&description_filename)?; + self.read_description()?; + Ok(()) + } + pub fn title<'a>(&'a self) -> &'a str { match self.description.find("\n") { Some(index) => &self.description.as_str()[..index],