fix(issue)!: make subject mandatory and optional content
BREAKING CHANGE: When the editor contains only one line, it is now treated as the subject instead of being used as the issue content. Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
14
CHANGELOG.md
14
CHANGELOG.md
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- New command `repo state` - by Awiteb
|
||||||
|
|
||||||
|
### Breaking Change
|
||||||
|
|
||||||
|
- Make subject mandatory and optional content - by Awiteb
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Check the nip07 signer in `CliOptions::ensure_signer` - by Awiteb
|
||||||
|
|
||||||
## [0.4.0] - 2025-08-08
|
## [0.4.0] - 2025-08-08
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -37,14 +37,9 @@ use crate::{
|
|||||||
/// Arguments for the `issue new` command
|
/// Arguments for the `issue new` command
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
#[clap(
|
#[clap(
|
||||||
group(
|
|
||||||
ArgGroup::new("issue-content")
|
|
||||||
.args(["content", "editor"])
|
|
||||||
.required(true)
|
|
||||||
),
|
|
||||||
group(
|
group(
|
||||||
ArgGroup::new("issue-subject")
|
ArgGroup::new("issue-subject")
|
||||||
.args(["editor", "subject"])
|
.required(true)
|
||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
pub struct NewArgs {
|
pub struct NewArgs {
|
||||||
@@ -56,14 +51,14 @@ pub struct NewArgs {
|
|||||||
naddrs: Option<Vec<NaddrOrSet>>,
|
naddrs: Option<Vec<NaddrOrSet>>,
|
||||||
/// Markdown content for the issue. Cannot be used together with the
|
/// Markdown content for the issue. Cannot be used together with the
|
||||||
/// `--editor` flag.
|
/// `--editor` flag.
|
||||||
#[arg(short, long)]
|
#[arg(short, long, group = "issue-content")]
|
||||||
content: Option<String>,
|
content: Option<String>,
|
||||||
/// Opens the user's default editor to write issue content. The first line
|
/// Opens the user's default editor to write issue content. The first line
|
||||||
/// will be used as the issue subject.
|
/// will be used as the issue subject.
|
||||||
#[arg(short, long)]
|
#[arg(short, long, group = "issue-subject", group = "issue-content")]
|
||||||
editor: bool,
|
editor: bool,
|
||||||
/// The issue subject. Cannot be used together with the `--editor` flag.
|
/// The issue subject. Cannot be used together with the `--editor` flag.
|
||||||
#[arg(long)]
|
#[arg(long, group = "issue-subject")]
|
||||||
subject: Option<String>,
|
subject: Option<String>,
|
||||||
/// Labels for the issue. Can be specified as arguments (-l bug) or hashtags
|
/// Labels for the issue. Can be specified as arguments (-l bug) or hashtags
|
||||||
/// in content (#bug).
|
/// in content (#bug).
|
||||||
@@ -71,29 +66,6 @@ pub struct NewArgs {
|
|||||||
label: Vec<String>,
|
label: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NewArgs {
|
|
||||||
/// Returns the subject and the content of the issue. (subject, content)
|
|
||||||
pub fn issue_content(&self) -> N34Result<(Option<String>, String)> {
|
|
||||||
if let Some(content) = self.content.as_ref() {
|
|
||||||
if let Some(subject) = self.subject.as_ref() {
|
|
||||||
return Ok((Some(subject.trim().to_owned()), content.trim().to_owned()));
|
|
||||||
}
|
|
||||||
return Ok((None, content.trim().to_owned()));
|
|
||||||
}
|
|
||||||
// If the `self.content` is `None` then the `self.editor` is `true`
|
|
||||||
let file_content = utils::read_editor(None, ".md")?;
|
|
||||||
if file_content.contains('\n') {
|
|
||||||
Ok(file_content
|
|
||||||
.split_once('\n')
|
|
||||||
.map(|(s, c)| (Some(s.trim().to_owned()), c.trim().to_owned()))
|
|
||||||
.expect("There is a new line"))
|
|
||||||
} else {
|
|
||||||
tracing::info!("File content contains only issue body without a subject line");
|
|
||||||
Ok((None, file_content))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CommandRunner for NewArgs {
|
impl CommandRunner for NewArgs {
|
||||||
async fn run(self, options: CliOptions) -> N34Result<()> {
|
async fn run(self, options: CliOptions) -> N34Result<()> {
|
||||||
let naddrs = utils::check_empty_naddrs(utils::naddrs_or_file(
|
let naddrs = utils::check_empty_naddrs(utils::naddrs_or_file(
|
||||||
@@ -113,16 +85,30 @@ impl CommandRunner for NewArgs {
|
|||||||
.add_relays(&utils::add_read_relays(relays_list.as_ref()))
|
.add_relays(&utils::add_read_relays(relays_list.as_ref()))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let (subject, content) = self.issue_content()?;
|
let (subject, content) = utils::subject_and_body(self.subject, self.content, ".md")?;
|
||||||
let content_details = client.parse_content(&content).await;
|
|
||||||
|
|
||||||
let event =
|
let content_details = if let Some(content) = &content {
|
||||||
EventBuilder::new_git_issue(coordinates.as_slice(), content, subject, self.label)?
|
Some(client.parse_content(content).await)
|
||||||
.dedup_tags()
|
} else {
|
||||||
.pow(options.pow.unwrap_or_default())
|
None
|
||||||
.tags(maintainers.iter().map(|p| Tag::public_key(*p)))
|
};
|
||||||
.tags(content_details.clone().into_tags())
|
|
||||||
.build(user_pubk);
|
let event = EventBuilder::new_git_issue(
|
||||||
|
coordinates.as_slice(),
|
||||||
|
content.unwrap_or_default(),
|
||||||
|
Some(subject),
|
||||||
|
self.label,
|
||||||
|
)?
|
||||||
|
.dedup_tags()
|
||||||
|
.pow(options.pow.unwrap_or_default())
|
||||||
|
.tags(maintainers.iter().map(|p| Tag::public_key(*p)))
|
||||||
|
.tags(
|
||||||
|
content_details
|
||||||
|
.clone()
|
||||||
|
.map(|c| c.into_tags())
|
||||||
|
.unwrap_or_default(),
|
||||||
|
)
|
||||||
|
.build(user_pubk);
|
||||||
let event_id = event.id.expect("There is an id");
|
let event_id = event.id.expect("There is an id");
|
||||||
|
|
||||||
let write_relays = [
|
let write_relays = [
|
||||||
@@ -135,7 +121,9 @@ impl CommandRunner for NewArgs {
|
|||||||
.extract_relays(),
|
.extract_relays(),
|
||||||
// Include read relays for each maintainer (if found)
|
// Include read relays for each maintainer (if found)
|
||||||
client.read_relays_from_users(&maintainers).await,
|
client.read_relays_from_users(&maintainers).await,
|
||||||
content_details.write_relays.clone().into_iter().collect(),
|
content_details
|
||||||
|
.map(|c| c.write_relays.into_iter().collect())
|
||||||
|
.unwrap_or_default(),
|
||||||
]
|
]
|
||||||
.concat();
|
.concat();
|
||||||
|
|
||||||
|
|||||||
@@ -309,3 +309,32 @@ pub fn check_empty_naddrs(naddrs: Vec<Nip19Coordinate>) -> N34Result<Vec<Nip19Co
|
|||||||
|
|
||||||
Ok(naddrs)
|
Ok(naddrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Extracts the subject and body from the provided inputs or an editor.
|
||||||
|
///
|
||||||
|
/// If no subject is provided, it opens an editor where the first line is used
|
||||||
|
/// as the subject and the remaining lines as the body. If the editor output
|
||||||
|
/// contains only one line, it is used as the subject.
|
||||||
|
pub fn subject_and_body(
|
||||||
|
subject: Option<String>,
|
||||||
|
body: Option<String>,
|
||||||
|
file_suffix: &str,
|
||||||
|
) -> N34Result<(String, Option<String>)> {
|
||||||
|
if let Some(subject) = subject {
|
||||||
|
return Ok((subject, body));
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is no subject, so we need to get it from the editor
|
||||||
|
let file_content = read_editor(None, file_suffix)?;
|
||||||
|
// if there is a subject and body
|
||||||
|
if file_content.contains('\n') {
|
||||||
|
Ok(file_content
|
||||||
|
.split_once("\n")
|
||||||
|
.map(|(subject, body)| (subject.trim().to_owned(), Some(body.trim().to_owned())))
|
||||||
|
.expect("There is a newline"))
|
||||||
|
} else {
|
||||||
|
tracing::info!("File content contains only the subject");
|
||||||
|
Ok((file_content.trim().to_owned(), None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user