blob: def2ea5ae353699701ebc41e9eaeedf53f4f3681 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use core::fmt;
use anyhow::Result;
use serde::{Deserialize, Serialize};
pub trait Api {
fn create_issue(&mut self, request: CreateIssue) -> Result<IssueId>;
fn update_issue(&mut self, request: UpdateIssue) -> Result<()>;
fn list_components(&mut self) -> Result<Vec<Component>>;
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct IssueId(usize);
impl IssueId {
pub fn new(id: usize) -> Self {
Self(id)
}
}
impl fmt::Display for IssueId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
pub enum Status {
New,
Assigned,
Accepted,
Fixed,
Verified,
}
impl fmt::Display for Status {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::New => "NEW",
Self::Assigned => "ASSIGNED",
Self::Accepted => "ACCEPTED",
Self::Fixed => "FIXED",
Self::Verified => "Verified",
};
write!(f, "{s}")
}
}
#[derive(Debug)]
pub struct CreateIssue {
pub title: String,
pub description: String,
pub status: Status,
pub component: ComponentId,
pub blocking_issues: Vec<IssueId>,
}
impl CreateIssue {
pub fn to_bugspec(&self) -> String {
use core::fmt::Write;
let mut result = String::new();
writeln!(&mut result, "{}\n", self.title).unwrap();
writeln!(&mut result, "{}\n", self.description).unwrap();
writeln!(&mut result, "STATUS={}", self.status).unwrap();
writeln!(&mut result, "COMPONENT={}", self.component).unwrap();
if !self.blocking_issues.is_empty() {
write!(&mut result, "BLOCKED_BY+={}", self.blocking_issues.iter().next().unwrap())
.unwrap();
for issue in self.blocking_issues.iter().skip(1) {
write!(&mut result, ",{}", issue).unwrap();
}
writeln!(&mut result).unwrap();
}
result
}
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct ComponentId(usize);
impl ComponentId {
pub fn new(id: usize) -> Self {
Self(id)
}
}
impl fmt::Display for ComponentId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug)]
pub struct Component {
pub id: ComponentId,
pub path: Vec<String>,
}
#[derive(Debug)]
pub struct UpdateIssue {
pub id: IssueId,
pub status: Option<Status>,
pub owner: Option<String>,
pub cc_users: Option<Vec<String>>,
pub component: Option<ComponentId>,
}
impl UpdateIssue {
pub fn to_bugspec(&self) -> String {
use core::fmt::Write;
let mut result = String::new();
if let Some(status) = &self.status {
writeln!(&mut result, "STATUS={}", status).unwrap();
}
if let Some(owner) = &self.owner {
writeln!(&mut result, "ASSIGNEE={}", owner).unwrap();
}
if let Some(cc_users) = &self.cc_users {
if !cc_users.is_empty() {
write!(&mut result, "CC+={}", cc_users.iter().next().unwrap()).unwrap();
for cc_user in cc_users.iter().skip(1) {
write!(&mut result, ",{}", cc_user).unwrap();
}
writeln!(&mut result).unwrap();
}
}
if let Some(component) = &self.component {
writeln!(&mut result, "COMPONENT={}", component).unwrap();
}
result
}
}