git-ents.gitmain
⌘K
foforge
issue.rs114 lines · 2.9 KB · rusthistorycomment on this file
1//! `git ents issue`: a thin wrapper around `ents_forge::issue`'s business
2//! logic — the `$GIT_EDITOR` fallback for an omitted `--title` lives in
3//! [`crate::compose`], driven by the `ents::compose` attributes on
4//! [`ents_forge::issue::IssueAction`], not here (`lens.parity`).
5
6use std::path::PathBuf;
7
8use ents_forge::Issue;
9use ents_forge::issue::{self, EditIssue, NewIssue};
10use ents_model::MemberId;
11use ents_receive::Identity;
12
13use super::{actor, signer};
14use crate::error::Result;
15use crate::mutate::outcome_to_result;
16use crate::root::LocalRoot;
17
18/// `git ents issue list`: every issue recorded in this repository.
19///
20/// # Errors
21///
22/// Propagates a ref-store or object read failure.
23pub fn list(root: &LocalRoot) -> Result<Vec<(String, Issue)>> {
24 Ok(issue::list(&root.refs, &root.objects)?)
25}
26
27/// `git ents issue show`: `id`'s issue.
28///
29/// # Errors
30///
31/// [`crate::error::Error::Forge`] (wrapping [`ents_forge::Error::NotFound`])
32/// if `id` has no issue ref.
33pub fn show(root: &LocalRoot, id: &str) -> Result<Issue> {
34 Ok(issue::show(&root.refs, &root.objects, id)?)
35}
36
37/// `git ents issue new`: create an issue.
38///
39/// # Errors
40///
41/// See [`crate::mutate::outcome_to_result`].
42pub fn new(
43 root: &LocalRoot,
44 title: String,
45 body: String,
46 state: String,
47 labels: Vec<String>,
48 assignees: Vec<String>,
49 key: Option<PathBuf>,
50) -> Result<String> {
51 let signer = signer(root, key)?;
52 let identity = Identity {
53 actor: actor(&signer),
54 author: None,
55 sign: &|payload| signer.sign(payload),
56 };
57 let new = NewIssue {
58 title,
59 body,
60 state,
61 assignees: assignees.into_iter().map(MemberId::new).collect(),
62 labels,
63 };
64 let (id, outcome) = issue::new(
65 &root.refs,
66 &root.objects,
67 &root.events,
68 new,
69 &identity,
70 root.mode(),
71 )?;
72 outcome_to_result(outcome, None)?;
73 Ok(id)
74}
75
76/// `git ents issue edit`: mutate `id`'s state, assignees, and/or labels.
77/// Assignees/labels replace the previous set entirely when at least one
78/// value is given; an empty list leaves that field unchanged.
79///
80/// # Errors
81///
82/// See [`crate::mutate::outcome_to_result`].
83pub fn edit(
84 root: &LocalRoot,
85 id: &str,
86 state: Option<String>,
87 labels: Vec<String>,
88 assignees: Vec<String>,
89 key: Option<PathBuf>,
90) -> Result<()> {
91 let signer = signer(root, key)?;
92 let identity = Identity {
93 actor: actor(&signer),
94 author: None,
95 sign: &|payload| signer.sign(payload),
96 };
97 let edit = EditIssue {
98 state,
99 labels: (!labels.is_empty()).then_some(labels),
100 assignees: (!assignees.is_empty())
101 .then(|| assignees.into_iter().map(MemberId::new).collect()),
102 };
103 let outcome = issue::edit(
104 &root.refs,
105 &root.objects,
106 &root.events,
107 id,
108 edit,
109 &identity,
110 root.mode(),
111 )?;
112 outcome_to_result(outcome, None)?;
113 Ok(())
114}