Skip to content

Commit

Permalink
improve operations on comments, including through Gitlab connector
Browse files Browse the repository at this point in the history
  • Loading branch information
jhspetersson committed Sep 30, 2024
1 parent f693313 commit 6727a44
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/connectors/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl RemoteConnector for GithubRemoteConnector {
}
}

fn update_remote_comment(&self, user: &String, repo: &String, comment_id: &String, text: &String) -> Result<(), String> {
fn update_remote_comment(&self, user: &String, repo: &String, _task_id: &String, comment_id: &String, text: &String) -> Result<(), String> {
match get_token_from_env() {
Some(_) => RUNTIME.block_on(update_comment(user, repo, comment_id.parse().unwrap(), text)),
None => Err("Could not find GITHUB_TOKEN environment variable.".to_string())
Expand Down
82 changes: 67 additions & 15 deletions src/connectors/gitlab.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::cmp::PartialEq;
use std::collections::HashMap;

use gitlab::api::issues::{IssueScope, IssueState};
use gitlab::api::projects::issues::IssueStateEvent;
use gitlab::api::{ApiError, Query};
use gitlab::api::Query;
use gitlab::Gitlab;
use regex::Regex;
use serde::{Deserialize, Serialize};
Expand All @@ -29,6 +28,14 @@ struct Issue {
state: String,
}

#[derive(Serialize, Deserialize)]
struct GitlabComment {
id: u64,
body: String,
author: Author,
created_at: String,
}

impl RemoteConnector for GitlabRemoteConnector {
fn supports_remote(&self, url: &str) -> Option<(String, String)> {
match Regex::new("https://gitlab.com/([a-z0-9-]+)/([a-z0-9-]+)\\.?").unwrap().captures(url) {
Expand Down Expand Up @@ -65,10 +72,11 @@ impl RemoteConnector for GitlabRemoteConnector {
props.insert(String::from("created"), parse_datetime_to_seconds(issue.created_at));
props.insert(String::from("author"), issue.author.username);

let task = Task::from_properties(issue.iid.to_string(), props).unwrap();
let mut task = Task::from_properties(issue.iid.to_string(), props).unwrap();

if with_comments {
eprintln!("Comments are not supported for Gitlab");
let comments = list_issue_comments(&client, &user, &repo, &issue.iid.to_string());
task.set_comments(comments);
}

result.push(task);
Expand Down Expand Up @@ -97,10 +105,11 @@ impl RemoteConnector for GitlabRemoteConnector {
props.insert(String::from("created"), parse_datetime_to_seconds(issue.created_at));
props.insert(String::from("author"), issue.author.username);

let task = Task::from_properties(task_id.to_string(), props).unwrap();
let mut task = Task::from_properties(task_id.to_string(), props).unwrap();

if with_comments {
eprintln!("Comments are not supported for Gitlab");
let comments = list_issue_comments(&client, &user, &repo, task_id);
task.set_comments(comments);
}

Some(task)
Expand All @@ -114,7 +123,7 @@ impl RemoteConnector for GitlabRemoteConnector {
fn create_remote_task(&self, user: &String, repo: &String, task: &Task) -> Result<String, String> {
let client = get_client(get_token_from_env().unwrap().as_str());
let mut endpoint = gitlab::api::projects::issues::CreateIssue::builder();
let mut endpoint = endpoint.project(user.to_string() + "/" + repo);
let endpoint = endpoint.project(user.to_string() + "/" + repo);
endpoint.title(task.get_property("name").unwrap());
endpoint.description(task.get_property("description").unwrap());
let endpoint = endpoint.build().unwrap();
Expand All @@ -130,13 +139,20 @@ impl RemoteConnector for GitlabRemoteConnector {
}

fn create_remote_comment(&self, user: &String, repo: &String, task_id: &String, comment: &Comment) -> Result<String, String> {
todo!()
let client = get_client(get_token_from_env().unwrap().as_str());
let mut endpoint = gitlab::api::projects::issues::notes::CreateIssueNote::builder();
let endpoint = endpoint.project(user.to_string() + "/" + repo).issue(task_id.parse().unwrap());
endpoint.body(comment.get_text().clone());
let endpoint = endpoint.build().unwrap();
let comment: GitlabComment = endpoint.query(&client).unwrap();

Ok(comment.id.to_string())
}

fn update_remote_task(&self, user: &String, repo: &String, task_id: &String, name: &String, text: &String, state: RemoteTaskState) -> Result<(), String> {
let client = get_client(get_token_from_env().unwrap().as_str());
let mut endpoint = gitlab::api::projects::issues::EditIssue::builder();
let mut endpoint = endpoint.project(user.to_string() + "/" + repo).issue(task_id.parse().unwrap());
let endpoint = endpoint.project(user.to_string() + "/" + repo).issue(task_id.parse().unwrap());
endpoint.title(name);
endpoint.description(text);
endpoint.state_event(if state == RemoteTaskState::Open { IssueStateEvent::Reopen } else { IssueStateEvent::Close });
Expand All @@ -150,16 +166,52 @@ impl RemoteConnector for GitlabRemoteConnector {
}
}

fn update_remote_comment(&self, user: &String, repo: &String, comment_id: &String, text: &String) -> Result<(), String> {
todo!()
fn update_remote_comment(&self, user: &String, repo: &String, task_id: &String, comment_id: &String, text: &String) -> Result<(), String> {
let client = get_client(get_token_from_env().unwrap().as_str());
let mut endpoint = gitlab::api::projects::issues::notes::EditIssueNote::builder();
let endpoint = endpoint.project(user.to_string() + "/" + repo).issue(task_id.parse().unwrap());
endpoint.note(comment_id.parse().unwrap());
endpoint.body(text.as_str());
let endpoint = endpoint.build().unwrap();
match endpoint.query(&client) {
Ok(comment) => {
let _: GitlabComment = comment;
Ok(())
},
Err(e) => Err(e.to_string())
}
}

fn delete_remote_task(&self, _user: &String, _repo: &String, _task_id: &String) -> Result<(), String> {
Err("Deleting remote tasks is not implemented for Gitlab".to_string())
}

fn delete_remote_task(&self, user: &String, repo: &String, task_id: &String) -> Result<(), String> {
todo!()
fn delete_remote_comment(&self, _user: &String, _repo: &String, _comment_id: &String) -> Result<(), String> {
Err("Deleting remote comments is not implemented for Gitlab".to_string())
}
}

fn delete_remote_comment(&self, user: &String, repo: &String, comment_id: &String) -> Result<(), String> {
todo!()
fn list_issue_comments(client: &Gitlab, user: &String, repo: &String, task_id: &String) -> Vec<Comment> {
let mut endpoint = gitlab::api::projects::issues::notes::IssueNotes::builder();
let endpoint = endpoint.project(user.to_string() + "/" + repo).issue(task_id.parse().unwrap());
let endpoint = endpoint.build().unwrap();
match gitlab::api::paged(endpoint, gitlab::api::Pagination::Limit(100)).query(client) {
Ok(comments) => {
let comments: Vec<GitlabComment> = comments;
let mut result: Vec<Comment> = vec![];
for comment in comments {
let comment = Comment::new(comment.id.to_string(), HashMap::from([
("author".to_string(), comment.author.username),
("created".to_string(), parse_datetime_to_seconds(comment.created_at)),
]), comment.body);
result.push(comment);
}
result
},
Err(e) => {
eprintln!("{}", e);
vec![]
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/connectors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub trait RemoteConnector {
fn create_remote_task(&self, user: &String, repo: &String, task: &Task) -> Result<String, String>;
fn create_remote_comment(&self, user: &String, repo: &String, task_id: &String, comment: &Comment) -> Result<String, String>;
fn update_remote_task(&self, user: &String, repo: &String, task_id: &String, name: &String, text: &String, state: RemoteTaskState) -> Result<(), String>;
fn update_remote_comment(&self, user: &String, repo: &String, comment_id: &String, text: &String) -> Result<(), String>;
fn update_remote_comment(&self, user: &String, repo: &String, task_id: &String, comment_id: &String, text: &String) -> Result<(), String>;
fn delete_remote_task(&self, user: &String, repo: &String, task_id: &String) -> Result<(), String>;
fn delete_remote_comment(&self, user: &String, repo: &String, comment_id: &String) -> Result<(), String>;
}
Expand Down
29 changes: 17 additions & 12 deletions src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ pub(crate) fn task_comment_edit(task_id: String, comment_id: String, push: bool,
if push {
match get_user_repo(remote) {
Ok((connector, user, repo)) => {
match connector.update_remote_comment(&user, &repo, &comment_id, &text) {
match connector.update_remote_comment(&user, &repo, &task_id, &comment_id, &text) {
Ok(_) => {
println!("Sync: REMOTE comment ID {comment_id} has been updated");
success = true;
Expand Down Expand Up @@ -592,21 +592,26 @@ pub(crate) fn task_push(ids: Vec<String>, remote: &Option<String>, no_comments:
match connector.update_remote_task(&user, &repo, &id, local_name, local_text, state) {
Ok(_) => {
println!("Sync: REMOTE task ID {id} has been updated");

if !no_comments {
let remote_comment_ids: Vec<String> = remote_task.get_comments().as_ref().unwrap_or(&vec![]).iter().map(|comment| comment.get_id().unwrap()).collect();
for comment in local_task.get_comments().as_ref().unwrap_or(&vec![]) {
let local_comment_id = comment.get_id().unwrap();
if !remote_comment_ids.contains(&local_comment_id) {
create_remote_comment(&connector, &user, &repo, &id, &comment);
}
}
}
},
Err(e) => eprintln!("ERROR: {e}")
}
} else {
println!("Nothing to sync");
if !no_comments {
let mut comments_updated = false;
let remote_comment_ids: Vec<String> = remote_task.get_comments().as_ref().unwrap_or(&vec![]).iter().map(|comment| comment.get_id().unwrap()).collect();
for comment in local_task.get_comments().as_ref().unwrap_or(&vec![]) {
let local_comment_id = comment.get_id().unwrap();
if !remote_comment_ids.contains(&local_comment_id) {
create_remote_comment(&connector, &user, &repo, &id, &comment);
comments_updated = true;
}
}
if !comments_updated {
println!("Nothing to sync");
}
} else {
println!("Nothing to sync");
}
}
} else {
eprintln!("Sync: REMOTE task ID {id} NOT found");
Expand Down

0 comments on commit 6727a44

Please sign in to comment.