Browse Source

Allow to unassign myself from issues

Santiago Pastorino 5 years ago
parent
commit
fcfc436ee8
2 changed files with 48 additions and 19 deletions
  1. 26 8
      src/github.rs
  2. 22 11
      src/handlers/assign.rs

+ 26 - 8
src/github.rs

@@ -4,7 +4,7 @@ use reqwest::{Client, Error as HttpError, RequestBuilder, Response, StatusCode};
 use std::fmt;
 use std::io::Read;
 
-#[derive(Debug, serde::Deserialize)]
+#[derive(Debug, PartialEq, Eq, serde::Deserialize)]
 pub struct User {
     pub login: String,
 }
@@ -76,6 +76,11 @@ pub enum AssignmentError {
     Http(HttpError),
 }
 
+pub enum Selection<'a, T> {
+    All,
+    One(&'a T),
+}
+
 impl fmt::Display for AssignmentError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
@@ -180,13 +185,30 @@ impl Issue {
         &self.labels
     }
 
-    pub fn remove_assignees(&self, client: &GithubClient) -> Result<(), AssignmentError> {
+    pub fn contain_assignee(&self, user: &User) -> bool {
+        self.assignees.contains(user)
+    }
+
+    pub fn remove_assignees(
+        &self,
+        client: &GithubClient,
+        selection: Selection<User>,
+    ) -> Result<(), AssignmentError> {
         let url = format!(
             "{repo_url}/issues/{number}/assignees",
             repo_url = self.repository_url,
             number = self.number
         );
 
+        let assignees = match selection {
+            Selection::All => self
+                .assignees
+                .iter()
+                .map(|u| u.login.as_str())
+                .collect::<Vec<_>>(),
+            Selection::One(user) => vec![user.login.as_str()],
+        };
+
         #[derive(serde::Serialize)]
         struct AssigneeReq<'a> {
             assignees: &'a [&'a str],
@@ -194,11 +216,7 @@ impl Issue {
         client
             .delete(&url)
             .json(&AssigneeReq {
-                assignees: &self
-                    .assignees
-                    .iter()
-                    .map(|u| u.login.as_str())
-                    .collect::<Vec<_>>()[..],
+                assignees: &assignees[..],
             })
             .send_req()
             .map_err(AssignmentError::Http)?;
@@ -229,7 +247,7 @@ impl Issue {
             Err(e) => return Err(AssignmentError::Http(e)),
         }
 
-        self.remove_assignees(client)?;
+        self.remove_assignees(client, Selection::All)?;
 
         #[derive(serde::Serialize)]
         struct AssigneeReq<'a> {

+ 22 - 11
src/handlers/assign.rs

@@ -13,7 +13,7 @@
 
 use crate::{
     config::AssignConfig,
-    github::{self, Event},
+    github::{self, Event, Selection},
     handlers::{Context, Handler},
     interactions::EditIssueBody,
 };
@@ -88,18 +88,29 @@ impl Handler for AssignmentHandler {
                 username.clone()
             }
             AssignCommand::Release => {
-                let current = if let Some(AssignData { user: Some(user) }) = e.current_data() {
-                    user
+                if let Some(AssignData {
+                    user: Some(current),
+                }) = e.current_data()
+                {
+                    if current == event.comment.user.login || is_team_member {
+                        event.issue.remove_assignees(&ctx.github, Selection::All)?;
+                        e.apply(&ctx.github, String::new(), AssignData { user: None })?;
+                        return Ok(());
+                    } else {
+                        failure::bail!("Cannot release another user's assignment");
+                    }
                 } else {
-                    failure::bail!("Cannot release unassigned issue");
+                    let current = &event.comment.user;
+                    if event.issue.contain_assignee(current) {
+                        event
+                            .issue
+                            .remove_assignees(&ctx.github, Selection::One(&current))?;
+                        e.apply(&ctx.github, String::new(), AssignData { user: None })?;
+                        return Ok(());
+                    } else {
+                        failure::bail!("Cannot release unassigned issue");
+                    }
                 };
-                if current == event.comment.user.login || is_team_member {
-                    event.issue.remove_assignees(&ctx.github)?;
-                    e.apply(&ctx.github, String::new(), AssignData { user: None })?;
-                    return Ok(());
-                } else {
-                    failure::bail!("Cannot release another user's assignment");
-                }
             }
         };
         let data = AssignData {