diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index 494b1ba..ac55045 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -86,6 +86,12 @@ enum Commands { #[arg(allow_hyphen_values = true)] tag: Option, }, + + /// Get or set the `done_time` of the Issue. + DoneTime { + issue_id: String, + done_time: Option, + }, } fn handle_command( @@ -263,6 +269,9 @@ fn handle_command( println!("issue {}", issue_id); println!("author: {}", issue.author); println!("creation_time: {}", issue.creation_time); + if let Some(done_time) = &issue.done_time { + println!("done_time: {}", done_time); + } println!("state: {:?}", issue.state); if let Some(dependencies) = &issue.dependencies { println!("dependencies: {:?}", dependencies); @@ -448,6 +457,38 @@ fn handle_command( } } } + + Commands::DoneTime { + issue_id, + done_time, + } => { + let issues = entomologist::database::read_issues_database(issues_database_source)?; + let Some(issue) = issues.issues.get(issue_id) else { + return Err(anyhow::anyhow!("issue {} not found", issue_id)); + }; + match done_time { + Some(done_time) => { + // Add or remove tag. + let issues_database = entomologist::database::make_issues_database( + issues_database_source, + entomologist::database::IssuesDatabaseAccess::ReadWrite, + )?; + let mut issues = + entomologist::issues::Issues::new_from_dir(&issues_database.dir)?; + let Some(issue) = issues.get_mut_issue(issue_id) else { + return Err(anyhow::anyhow!("issue {} not found", issue_id)); + }; + let done_time = chrono::DateTime::parse_from_rfc3339(done_time) + .unwrap() + .with_timezone(&chrono::Local); + issue.set_done_time(done_time)?; + } + None => match &issue.done_time { + Some(done_time) => println!("done_time: {}", done_time), + None => println!("None"), + }, + }; + } } Ok(()) diff --git a/src/issue.rs b/src/issue.rs index 927eb7f..bc3d959 100644 --- a/src/issue.rs +++ b/src/issue.rs @@ -283,7 +283,8 @@ impl Issue { } } - /// Change the State of the Issue. + /// Change the State of the Issue. If the new state is `Done`, + /// set the Issue `done_time`. Commits. pub fn set_state(&mut self, new_state: State) -> Result<(), IssueError> { let old_state = self.state.clone(); let mut state_filename = std::path::PathBuf::from(&self.dir); @@ -296,6 +297,9 @@ impl Issue { old_state, new_state, ))?; + if new_state == State::Done { + self.set_done_time(chrono::Local::now())?; + } Ok(()) } @@ -307,6 +311,24 @@ impl Issue { Ok(()) } + /// Set the `done_time` of the Issue. Commits. + pub fn set_done_time( + &mut self, + done_time: chrono::DateTime, + ) -> Result<(), IssueError> { + let mut done_time_filename = std::path::PathBuf::from(&self.dir); + done_time_filename.push("done_time"); + let mut done_time_file = std::fs::File::create(&done_time_filename)?; + write!(done_time_file, "{}", done_time.to_rfc3339())?; + self.done_time = Some(done_time.clone()); + self.commit(&format!( + "set done-time of issue {} to {}", + self.dir.file_name().unwrap().to_string_lossy(), + done_time, + ))?; + Ok(()) + } + /// Set the Assignee of an Issue. pub fn set_assignee(&mut self, new_assignee: &str) -> Result<(), IssueError> { let old_assignee = match &self.assignee {