소스 검색

New way of performing set_assignee

Try to assign regardless if the user is in the repo assignee list, and
check whether it is successful. If so, remove all other assignees.

This would allow "outside contributers" to be assigned if they have
commented the issue.
Gary Guo 4 년 전
부모
커밋
d412eaf08b
1개의 변경된 파일33개의 추가작업 그리고 39개의 파일을 삭제
  1. 33 39
      src/github.rs

+ 33 - 39
src/github.rs

@@ -284,9 +284,10 @@ pub enum AssignmentError {
 }
 
 #[derive(Debug)]
-pub enum Selection<'a, T> {
+pub enum Selection<'a, T: ?Sized> {
     All,
     One(&'a T),
+    Except(&'a T),
 }
 
 impl fmt::Display for AssignmentError {
@@ -462,7 +463,7 @@ impl Issue {
     pub async fn remove_assignees(
         &self,
         client: &GithubClient,
-        selection: Selection<'_, String>,
+        selection: Selection<'_, str>,
     ) -> Result<(), AssignmentError> {
         log::info!("remove {:?} assignees for {}", selection, self.global_id());
         let url = format!(
@@ -477,7 +478,13 @@ impl Issue {
                 .iter()
                 .map(|u| u.login.as_str())
                 .collect::<Vec<_>>(),
-            Selection::One(user) => vec![user.as_str()],
+            Selection::One(user) => vec![user],
+            Selection::Except(user) => self
+                .assignees
+                .iter()
+                .map(|u| u.login.as_str())
+                .filter(|&u| u != user)
+                .collect::<Vec<_>>(),
         };
 
         #[derive(serde::Serialize)]
@@ -493,60 +500,47 @@ impl Issue {
         Ok(())
     }
 
-    pub async fn set_assignee(
+    pub async fn add_assignee(
         &self,
         client: &GithubClient,
         user: &str,
     ) -> Result<(), AssignmentError> {
-        log::info!("set_assignee for {} to {}", self.global_id(), user);
+        log::info!("add_assignee {} for {}", user, self.global_id());
         let url = format!(
             "{repo_url}/issues/{number}/assignees",
             repo_url = self.repository().url(),
             number = self.number
         );
 
-        let check_url = format!(
-            "{repo_url}/assignees/{name}",
-            repo_url = self.repository().url(),
-            name = user,
-        );
-
-        match client._send_req(client.get(&check_url)).await {
-            Ok((resp, _)) => {
-                if resp.status() == reqwest::StatusCode::NO_CONTENT {
-                    // all okay
-                    log::debug!("set_assignee: assignee is valid");
-                } else {
-                    log::error!(
-                        "unknown status for assignee check, assuming all okay: {:?}",
-                        resp
-                    );
-                }
-            }
-            Err(e) => {
-                if let Some(e) = e.downcast_ref::<reqwest::Error>() {
-                    if e.status() == Some(reqwest::StatusCode::NOT_FOUND) {
-                        log::debug!("set_assignee: assignee is invalid, returning");
-                        return Err(AssignmentError::InvalidAssignee);
-                    }
-                }
-                log::debug!("set_assignee: get {} failed, {:?}", check_url, e);
-                return Err(AssignmentError::Http(e));
-            }
-        }
-
-        self.remove_assignees(client, Selection::All).await?;
-
         #[derive(serde::Serialize)]
         struct AssigneeReq<'a> {
             assignees: &'a [&'a str],
         }
 
-        client
-            ._send_req(client.post(&url).json(&AssigneeReq { assignees: &[user] }))
+        let result: Issue = client
+            .json(client.post(&url).json(&AssigneeReq { assignees: &[user] }))
             .await
             .map_err(AssignmentError::Http)?;
+        // Invalid assignees are silently ignored. We can just check if the user is now
+        // contained in the assignees list.
+        let success = result.assignees.iter().any(|u| u.login.as_str() == user);
+
+        if success {
+            Ok(())
+        } else {
+            Err(AssignmentError::InvalidAssignee)
+        }
+    }
 
+    pub async fn set_assignee(
+        &self,
+        client: &GithubClient,
+        user: &str,
+    ) -> Result<(), AssignmentError> {
+        log::info!("set_assignee for {} to {}", self.global_id(), user);
+        self.add_assignee(client, user).await?;
+        self.remove_assignees(client, Selection::Except(user))
+            .await?;
         Ok(())
     }
 }