use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
use super::ExternalRefType;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExternalRef {
pub id: i64,
pub task_id: i64,
pub ref_type: ExternalRefType,
pub reference: String,
pub created_at: DateTime<Local>,
}
impl ExternalRef {
pub fn new(
id: i64,
task_id: i64,
ref_type: ExternalRefType,
reference: impl Into<String>,
) -> Self {
Self {
id,
task_id,
ref_type,
reference: reference.into(),
created_at: Local::now(),
}
}
pub fn github_issue(task_id: i64, owner: &str, repo: &str, number: i64) -> Self {
Self::new(
0,
task_id,
ExternalRefType::GitHubIssue,
format!("{}/{}/{}", owner, repo, number),
)
}
pub fn github_pr(task_id: i64, owner: &str, repo: &str, number: i64) -> Self {
Self::new(
0,
task_id,
ExternalRefType::GitHubPr,
format!("{}/{}/{}", owner, repo, number),
)
}
pub fn url(task_id: i64, url: impl Into<String>) -> Self {
Self::new(0, task_id, ExternalRefType::Url, url)
}
}
pub fn parse_github_ref(ref_str: &str) -> Option<(String, String, i64)> {
use regex::Regex;
let re = Regex::new(r"^([^/]+)/([^/]+)#(\d+)$").ok()?;
let caps = re.captures(ref_str)?;
let owner = caps.get(1)?.as_str().to_string();
let repo = caps.get(2)?.as_str().to_string();
let number = caps.get(3)?.as_str().parse::<i64>().ok()?;
Some((owner, repo, number))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_github_ref() {
assert_eq!(
parse_github_ref("owner/repo#123"),
Some(("owner".to_string(), "repo".to_string(), 123))
);
assert_eq!(
parse_github_ref("my-org/my-repo#42"),
Some(("my-org".to_string(), "my-repo".to_string(), 42))
);
assert_eq!(parse_github_ref("invalid"), None);
assert_eq!(parse_github_ref("owner/repo"), None);
}
}