From 7acd94f7c0e403260b336a7a7998d400b69c14d2 Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Tue, 8 Jul 2025 14:08:21 -0600 Subject: [PATCH 1/7] add author to Comment --- src/bin/ent/main.rs | 1 + src/comment.rs | 4 ++++ src/git.rs | 22 ++++++++++++++++++++++ src/issue.rs | 1 + src/issues.rs | 3 ++- 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index 2d0f56a..ac15eb4 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -115,6 +115,7 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( for comment in &issue.comments { println!(""); println!("comment: {}", comment.uuid); + println!("author: {}", comment.author); println!("timestamp: {}", comment.timestamp); println!("{}", comment.description); } diff --git a/src/comment.rs b/src/comment.rs index 8cd00a0..d6ed66e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -3,6 +3,7 @@ use std::io::Write; #[derive(Debug, PartialEq)] pub struct Comment { pub uuid: String, + pub author: String, pub timestamp: chrono::DateTime, pub description: String, @@ -45,11 +46,13 @@ impl Comment { return Err(CommentError::CommentParseError); } + let author = crate::git::git_log_oldest_author(comment_dir)?; let timestamp = crate::git::git_log_oldest_timestamp(comment_dir)?; let dir = std::path::PathBuf::from(comment_dir); Ok(Self { uuid: String::from(dir.file_name().unwrap().to_string_lossy()), + author, timestamp, description: description.unwrap(), dir: std::path::PathBuf::from(comment_dir), @@ -102,6 +105,7 @@ mod tests { let comment = Comment::new_from_dir(comment_dir).unwrap(); let expected = Comment { uuid: String::from("9055dac36045fe36545bed7ae7b49347"), + author: String::from("Sebastian Kuzminsky "), timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-07T15:26:26-06:00") .unwrap() .with_timezone(&chrono::Local), diff --git a/src/git.rs b/src/git.rs index 28e8400..6018392 100644 --- a/src/git.rs +++ b/src/git.rs @@ -210,6 +210,28 @@ pub fn git_log_oldest_timestamp( Ok(timestamp) } +pub fn git_log_oldest_author(path: &std::path::Path) -> Result { + let mut git_dir = std::path::PathBuf::from(path); + git_dir.pop(); + let result = std::process::Command::new("git") + .args([ + "log", + "--pretty=format:%an <%ae>", + "--", + &path.file_name().unwrap().to_string_lossy(), + ]) + .current_dir(&git_dir) + .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(GitError::Oops); + } + let author_str = std::str::from_utf8(&result.stdout).unwrap(); + let author_last = author_str.split("\n").last().unwrap(); + Ok(String::from(author_last)) +} + pub fn create_orphan_branch(branch: &str) -> Result<(), GitError> { { let tmp_worktree = tempfile::tempdir().unwrap(); diff --git a/src/issue.rs b/src/issue.rs index cdbac1f..0e83297 100644 --- a/src/issue.rs +++ b/src/issue.rs @@ -156,6 +156,7 @@ impl Issue { Ok(crate::comment::Comment { uuid, + author: String::from("Sebastian Kuzminsky "), timestamp: chrono::Local::now(), description: String::from(""), // FIXME dir, diff --git a/src/issues.rs b/src/issues.rs index 06af867..3be405d 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -152,8 +152,9 @@ mod tests { expected_comments.push( crate::comment::Comment { uuid: comment_uuid, - description: String::from("This is a comment on issue dd79c8cfb8beeacd0460429944b4ecbe95a31561\n\nIt has multiple lines\n"), + author: String::from("Sebastian Kuzminsky "), timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-07T15:26:26-06:00").unwrap().with_timezone(&chrono::Local), + description: String::from("This is a comment on issue dd79c8cfb8beeacd0460429944b4ecbe95a31561\n\nIt has multiple lines\n"), dir: std::path::PathBuf::from(comment_dir), } ); From e8b37cd86a93aae72ee506fec77133027bc4b0c1 Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Tue, 8 Jul 2025 14:18:31 -0600 Subject: [PATCH 2/7] add author and timestamp to Issue --- src/bin/ent/main.rs | 2 ++ src/issue.rs | 27 ++++++++++++++++++++++----- src/issues.rs | 42 +++++++++++++++++++++++++++++++++++------- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index ac15eb4..81870e3 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -106,6 +106,8 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( match issues.get_issue(issue_id) { Some(issue) => { println!("issue {}", issue_id); + println!("author: {}", issue.author); + println!("timestamp: {}", issue.timestamp); println!("state: {:?}", issue.state); if let Some(dependencies) = &issue.dependencies { println!("dependencies: {:?}", dependencies); diff --git a/src/issue.rs b/src/issue.rs index 0e83297..97aa8f1 100644 --- a/src/issue.rs +++ b/src/issue.rs @@ -20,9 +20,11 @@ pub type IssueHandle = String; #[derive(Debug, PartialEq)] pub struct Issue { - pub description: String, + pub author: String, + pub timestamp: chrono::DateTime, pub state: State, pub dependencies: Option>, + pub description: String, pub comments: Vec, /// This is the directory that the issue lives in. Only used @@ -119,10 +121,15 @@ impl Issue { return Err(IssueError::IssueParseError); } + let author = crate::git::git_log_oldest_author(dir)?; + let timestamp = crate::git::git_log_oldest_timestamp(dir)?; + Ok(Self { - description: description.unwrap(), + author, + timestamp, state: state, dependencies, + description: description.unwrap(), comments, dir: std::path::PathBuf::from(dir), }) @@ -169,9 +176,11 @@ impl Issue { issue_dir.push(&format!("{:032x}", rnd)); std::fs::create_dir(&issue_dir)?; Ok(Self { - description: String::from(""), // FIXME: kind of bogus to use the empty string as None + author: String::from(""), + timestamp: chrono::Local::now(), state: State::New, dependencies: None, + description: String::from(""), // FIXME: kind of bogus to use the empty string as None comments: Vec::::new(), dir: issue_dir, }) @@ -245,9 +254,13 @@ mod tests { let issue_dir = std::path::Path::new("test/0000/3943fc5c173fdf41c0a22251593cd476d96e6c9f/"); let issue = Issue::new_from_dir(issue_dir).unwrap(); let expected = Issue { - description: String::from("this is the title of my issue\n\nThis is the description of my issue.\nIt is multiple lines.\n* Arbitrary contents\n* But let's use markdown by convention\n"), + author: String::from("Sebastian Kuzminsky "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: State::New, dependencies: None, + description: String::from("this is the title of my issue\n\nThis is the description of my issue.\nIt is multiple lines.\n* Arbitrary contents\n* But let's use markdown by convention\n"), comments: Vec::::new(), dir: std::path::PathBuf::from(issue_dir), }; @@ -259,9 +272,13 @@ mod tests { let issue_dir = std::path::Path::new("test/0000/7792b063eef6d33e7da5dc1856750c149ba678c6/"); let issue = Issue::new_from_dir(issue_dir).unwrap(); let expected = Issue { - description: String::from("minimal"), + author: String::from("Sebastian Kuzminsky "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: State::InProgress, dependencies: None, + description: String::from("minimal"), comments: Vec::::new(), dir: std::path::PathBuf::from(issue_dir), }; diff --git a/src/issues.rs b/src/issues.rs index 3be405d..ff6accb 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -96,9 +96,13 @@ mod tests { expected.add_issue( uuid, crate::issue::Issue { - description: String::from("minimal"), + author: String::from("Sebastian Kuzminsky "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: crate::issue::State::InProgress, dependencies: None, + description: String::from("minimal"), comments: Vec::::new(), dir, }, @@ -110,9 +114,13 @@ mod tests { expected.add_issue( uuid, crate::issue::Issue { - description: String::from("this is the title of my issue\n\nThis is the description of my issue.\nIt is multiple lines.\n* Arbitrary contents\n* But let's use markdown by convention\n"), + author: String::from("Sebastian Kuzminsky "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: crate::issue::State::New, dependencies: None, + description: String::from("this is the title of my issue\n\nThis is the description of my issue.\nIt is multiple lines.\n* Arbitrary contents\n* But let's use markdown by convention\n"), comments: Vec::::new(), dir, } @@ -133,9 +141,13 @@ mod tests { expected.add_issue( uuid, crate::issue::Issue { - description: String::from("oh yeah we got titles"), + author: String::from("Sebastian Kuzminsky "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-03T11:59:44-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: crate::issue::State::Done, dependencies: None, + description: String::from("oh yeah we got titles"), comments: Vec::::new(), dir, }, @@ -161,9 +173,13 @@ mod tests { expected.add_issue( uuid, crate::issue::Issue { - description: String::from("issues out the wazoo\n\nLots of words\nthat don't say much\nbecause this is just\na test\n"), + author: String::from("Sebastian Kuzminsky "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-03T11:59:44-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: crate::issue::State::WontDo, dependencies: None, + description: String::from("issues out the wazoo\n\nLots of words\nthat don't say much\nbecause this is just\na test\n"), comments: expected_comments, dir, }, @@ -184,9 +200,13 @@ mod tests { expected.add_issue( uuid, crate::issue::Issue { - description: String::from("oh yeah we got titles\n"), + author: String::from("sigil-03 "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: crate::issue::State::Done, dependencies: None, + description: String::from("oh yeah we got titles\n"), comments: Vec::::new(), dir, }, @@ -198,9 +218,13 @@ mod tests { expected.add_issue( uuid, crate::issue::Issue { - description: String::from("issues out the wazoo\n\nLots of words\nthat don't say much\nbecause this is just\na test\n"), + author: String::from("sigil-03 "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: crate::issue::State::WontDo, dependencies: None, + description: String::from("issues out the wazoo\n\nLots of words\nthat don't say much\nbecause this is just\na test\n"), comments: Vec::::new(), dir, }, @@ -212,12 +236,16 @@ mod tests { expected.add_issue( uuid, crate::issue::Issue { - description: String::from("issue with dependencies\n\na test has begun\nfor dependencies we seek\nintertwining life"), + author: String::from("sigil-03 "), + timestamp: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00") + .unwrap() + .with_timezone(&chrono::Local), state: crate::issue::State::WontDo, dependencies: Some(vec![ crate::issue::IssueHandle::from("3fa5bfd93317ad25772680071d5ac3259cd2384f"), crate::issue::IssueHandle::from("dd79c8cfb8beeacd0460429944b4ecbe95a31561"), ]), + description: String::from("issue with dependencies\n\na test has begun\nfor dependencies we seek\nintertwining life"), comments: Vec::::new(), dir, }, From ba57f629e38995d1973d9447e8d675b83b7af129 Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Tue, 8 Jul 2025 16:09:45 -0600 Subject: [PATCH 3/7] make `ent list` sort issues first by state, then by ctime --- src/bin/ent/main.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index 81870e3..aa15752 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -66,11 +66,44 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( let issues = entomologist::issues::Issues::new_from_dir(std::path::Path::new(issues_dir))?; let filter = entomologist::parse_filter(filter)?; + let mut uuids_by_state = std::collections::HashMap::< + entomologist::issue::State, + Vec<&entomologist::issue::IssueHandle>, + >::new(); for (uuid, issue) in issues.issues.iter() { if filter.include_states.contains(&issue.state) { - println!("{} {} ({:?})", uuid, issue.title(), issue.state); + uuids_by_state + .entry(issue.state.clone()) + .or_default() + .push(uuid); } } + + use entomologist::issue::State; + for state in [ + State::InProgress, + State::Blocked, + State::Backlog, + State::New, + State::Done, + State::WontDo, + ] { + let these_uuids = uuids_by_state.entry(state.clone()).or_default(); + if these_uuids.len() == 0 { + continue; + } + these_uuids.sort_by(|a_id, b_id| { + let a = issues.issues.get(*a_id).unwrap(); + let b = issues.issues.get(*b_id).unwrap(); + a.timestamp.cmp(&b.timestamp) + }); + println!("{:?}:", state); + for uuid in these_uuids { + let issue = issues.issues.get(*uuid).unwrap(); + println!("{} {}", uuid, issue.title()); + } + println!(""); + } } Commands::New { From 400e0ca26f893697ad5b3691b5117d37047a3fbe Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Tue, 8 Jul 2025 16:20:44 -0600 Subject: [PATCH 4/7] ent list: show comment count for each issue --- src/bin/ent/main.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index aa15752..952d178 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -100,7 +100,12 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( println!("{:?}:", state); for uuid in these_uuids { let issue = issues.issues.get(*uuid).unwrap(); - println!("{} {}", uuid, issue.title()); + let num_comments = issue.comments.len(); + if num_comments == 0 { + println!("{} {}", uuid, issue.title()); + } else { + println!("{} 🗩 {} {}", uuid, num_comments, issue.title()); + } } println!(""); } From 645062d10cbdd09c976fc675c6113165e814bef1 Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Tue, 8 Jul 2025 16:29:00 -0600 Subject: [PATCH 5/7] add optional 'assignee' to Issue --- src/bin/ent/main.rs | 3 +++ src/issue.rs | 10 ++++++++++ src/issues.rs | 7 +++++++ .../7792b063eef6d33e7da5dc1856750c149ba678c6/assignee | 1 + 4 files changed, 21 insertions(+) create mode 100644 test/0000/7792b063eef6d33e7da5dc1856750c149ba678c6/assignee diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index 952d178..cb8eb9d 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -150,6 +150,9 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( if let Some(dependencies) = &issue.dependencies { println!("dependencies: {:?}", dependencies); } + if let Some(assignee) = &issue.assignee { + println!("assignee: {}", assignee); + } println!(""); println!("{}", issue.description); for comment in &issue.comments { diff --git a/src/issue.rs b/src/issue.rs index 97aa8f1..096e497 100644 --- a/src/issue.rs +++ b/src/issue.rs @@ -24,6 +24,7 @@ pub struct Issue { pub timestamp: chrono::DateTime, pub state: State, pub dependencies: Option>, + pub assignee: Option, pub description: String, pub comments: Vec, @@ -90,6 +91,7 @@ impl Issue { let mut state = State::New; // default state, if not specified in the issue let mut dependencies: Option> = None; let mut comments = Vec::::new(); + let mut assignee: Option = None; for direntry in dir.read_dir()? { if let Ok(direntry) = direntry { @@ -99,6 +101,10 @@ impl Issue { } else if file_name == "state" { let state_string = std::fs::read_to_string(direntry.path())?; state = State::from_str(state_string.trim())?; + } else if file_name == "assignee" { + assignee = Some(String::from( + std::fs::read_to_string(direntry.path())?.trim(), + )); } else if file_name == "dependencies" { let dep_strings = std::fs::read_to_string(direntry.path())?; let deps: Vec = dep_strings @@ -129,6 +135,7 @@ impl Issue { timestamp, state: state, dependencies, + assignee, description: description.unwrap(), comments, dir: std::path::PathBuf::from(dir), @@ -180,6 +187,7 @@ impl Issue { timestamp: chrono::Local::now(), state: State::New, dependencies: None, + assignee: None, description: String::from(""), // FIXME: kind of bogus to use the empty string as None comments: Vec::::new(), dir: issue_dir, @@ -260,6 +268,7 @@ mod tests { .with_timezone(&chrono::Local), state: State::New, dependencies: None, + assignee: None, description: String::from("this is the title of my issue\n\nThis is the description of my issue.\nIt is multiple lines.\n* Arbitrary contents\n* But let's use markdown by convention\n"), comments: Vec::::new(), dir: std::path::PathBuf::from(issue_dir), @@ -278,6 +287,7 @@ mod tests { .with_timezone(&chrono::Local), state: State::InProgress, dependencies: None, + assignee: Some(String::from("beep boop")), description: String::from("minimal"), comments: Vec::::new(), dir: std::path::PathBuf::from(issue_dir), diff --git a/src/issues.rs b/src/issues.rs index ff6accb..16dab55 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -102,6 +102,7 @@ mod tests { .with_timezone(&chrono::Local), state: crate::issue::State::InProgress, dependencies: None, + assignee: Some(String::from("beep boop")), description: String::from("minimal"), comments: Vec::::new(), dir, @@ -120,6 +121,7 @@ mod tests { .with_timezone(&chrono::Local), state: crate::issue::State::New, dependencies: None, + assignee: None, description: String::from("this is the title of my issue\n\nThis is the description of my issue.\nIt is multiple lines.\n* Arbitrary contents\n* But let's use markdown by convention\n"), comments: Vec::::new(), dir, @@ -147,6 +149,7 @@ mod tests { .with_timezone(&chrono::Local), state: crate::issue::State::Done, dependencies: None, + assignee: None, description: String::from("oh yeah we got titles"), comments: Vec::::new(), dir, @@ -179,6 +182,7 @@ mod tests { .with_timezone(&chrono::Local), state: crate::issue::State::WontDo, dependencies: None, + assignee: None, description: String::from("issues out the wazoo\n\nLots of words\nthat don't say much\nbecause this is just\na test\n"), comments: expected_comments, dir, @@ -206,6 +210,7 @@ mod tests { .with_timezone(&chrono::Local), state: crate::issue::State::Done, dependencies: None, + assignee: None, description: String::from("oh yeah we got titles\n"), comments: Vec::::new(), dir, @@ -224,6 +229,7 @@ mod tests { .with_timezone(&chrono::Local), state: crate::issue::State::WontDo, dependencies: None, + assignee: None, description: String::from("issues out the wazoo\n\nLots of words\nthat don't say much\nbecause this is just\na test\n"), comments: Vec::::new(), dir, @@ -245,6 +251,7 @@ mod tests { crate::issue::IssueHandle::from("3fa5bfd93317ad25772680071d5ac3259cd2384f"), crate::issue::IssueHandle::from("dd79c8cfb8beeacd0460429944b4ecbe95a31561"), ]), + assignee: None, description: String::from("issue with dependencies\n\na test has begun\nfor dependencies we seek\nintertwining life"), comments: Vec::::new(), dir, diff --git a/test/0000/7792b063eef6d33e7da5dc1856750c149ba678c6/assignee b/test/0000/7792b063eef6d33e7da5dc1856750c149ba678c6/assignee new file mode 100644 index 0000000..fae06e3 --- /dev/null +++ b/test/0000/7792b063eef6d33e7da5dc1856750c149ba678c6/assignee @@ -0,0 +1 @@ +beep boop From d21b811bee46aa0749f964a74fead2923b40a060 Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Tue, 8 Jul 2025 17:16:17 -0600 Subject: [PATCH 6/7] add `ent assign ISSUE PERSON` --- src/bin/ent/main.rs | 37 +++++++++++++++++++++++++++++++++++++ src/issue.rs | 9 +++++++++ 2 files changed, 46 insertions(+) diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index cb8eb9d..5237281 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -58,6 +58,12 @@ enum Commands { #[arg(default_value_t = String::from("origin"))] remote: String, }, + + /// Get or set the Assignee field of an Issue. + Assign { + issue_id: String, + new_assignee: Option, + }, } fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<()> { @@ -234,6 +240,37 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( entomologist::git::sync(issues_dir, remote, branch)?; println!("synced {:?} with {:?}", branch, remote); } + + Commands::Assign { + issue_id, + new_assignee, + } => { + let mut issues = + entomologist::issues::Issues::new_from_dir(std::path::Path::new(issues_dir))?; + let Some(issue) = issues.issues.get_mut(issue_id) else { + return Err(anyhow::anyhow!("issue {} not found", issue_id)); + }; + match (&issue.assignee, new_assignee) { + (Some(old_assignee), Some(new_assignee)) => { + println!("issue: {}", issue_id); + println!("assignee: {} -> {}", old_assignee, new_assignee); + issue.set_assignee(new_assignee)?; + } + (Some(old_assignee), None) => { + println!("issue: {}", issue_id); + println!("assignee: {}", old_assignee); + } + (None, Some(new_assignee)) => { + println!("issue: {}", issue_id); + println!("assignee: None -> {}", new_assignee); + issue.set_assignee(new_assignee)?; + } + (None, None) => { + println!("issue: {}", issue_id); + println!("assignee: None"); + } + } + } } Ok(()) diff --git a/src/issue.rs b/src/issue.rs index 096e497..68cb8f9 100644 --- a/src/issue.rs +++ b/src/issue.rs @@ -251,6 +251,15 @@ impl Issue { self.state = State::from_str(state_string.trim())?; Ok(()) } + + pub fn set_assignee(&mut self, new_assignee: &str) -> Result<(), IssueError> { + let mut assignee_filename = std::path::PathBuf::from(&self.dir); + assignee_filename.push("assignee"); + let mut assignee_file = std::fs::File::create(&assignee_filename)?; + write!(assignee_file, "{}", new_assignee)?; + crate::git::git_commit_file(&assignee_filename)?; + Ok(()) + } } #[cfg(test)] From a676bd9cdd6876a7de520b5751576b0945f5c8ce Mon Sep 17 00:00:00 2001 From: Sebastian Kuzminsky Date: Tue, 8 Jul 2025 17:31:10 -0600 Subject: [PATCH 7/7] ent list: show assignee, if any --- src/bin/ent/main.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index 5237281..2a8f1f4 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -106,12 +106,15 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( println!("{:?}:", state); for uuid in these_uuids { let issue = issues.issues.get(*uuid).unwrap(); - let num_comments = issue.comments.len(); - if num_comments == 0 { - println!("{} {}", uuid, issue.title()); - } else { - println!("{} 🗩 {} {}", uuid, num_comments, issue.title()); - } + let comments = match issue.comments.len() { + 0 => String::from(" "), + n => format!("🗩 {}", n), + }; + let assignee = match &issue.assignee { + Some(assignee) => format!(" (👉 {})", assignee), + None => String::from(""), + }; + println!("{} {} {}{}", uuid, comments, issue.title(), assignee); } println!(""); }