Commits

Hugh Giddens committed b239b75

Refactor everything about endpoints enormously.

I can no longer recall why I did this.

  • Participants
  • Parent commits 49e62af
  • Branches refactor-endpoints

Comments (0)

Files changed (1)

File jira-rest.el

                        (substring endpoint 1)
                      endpoint)))
 
-(defun jira-rest-project-endpoint ()
-  "/rest/api/latest/project")
-
-(defun jira-rest-filter-endpoint (filter-id)
-  (format "/rest/api/latest/filter/%s" filter-id))
-
-(defun jira-rest-search-endpoint ()
-  "/rest/api/latest/search")
-
-(defun jira-rest-issue-endpoint (id-or-key)
-  (format "/rest/api/latest/issue/%s" id-or-key))
-
-(defun jira-rest-create-issue-metadata-endpoint ()
-  "/rest/api/latest/issue/createmeta")
-
-(defun jira-rest-create-issue-endpoint ()
-  "/rest/api/latest/issue")
-
-(defun jira-rest-comment-endpoint (id-or-key)
-  (format "/rest/api/latest/issue/%s/comment" id-or-key))
-
-(defun jira-rest-assignable-user-endpoint (issue-key user-search)
-  (format "/rest/api/latest/user/assignable/search?issueKey=%s&username=%s" issue-key user-search))
-
-(defun jira-rest-issue-transitions-endpoint (id-or-key)
-  (format "/rest/api/latest/issue/%s/transitions" id-or-key))
-
-(defun jira-rest-server-info-endpoint ()
-  "/rest/api/latest/serverInfo")
-
-(defun jira-rest-resolutions-endpoint ()
-  "/rest/api/latest/resolution")
-
-(defun jira-rest-watchers-endpoint (id-or-key &optional user-to-delete)
-  (format "/rest/api/latest/issue/%s/watchers%s"
-          id-or-key
-          (if user-to-delete (concat "?username=" user-to-delete) "")))
+(macrolet ((endpoint (endpoint-name &rest methods-and-urls)
+             (setf methods-and-urls (mapcan (lambda (method-and-url)
+                                              (destructuring-bind (method url) method-and-url
+                                                (etypecase method
+                                                  (list (loop for m in method collect (list m url)))
+                                                  (atom (list method-and-url)))))
+                                            methods-and-urls))
+             `(prog1 nil
+                ,@(mapcar (lambda (method-and-url)
+                            (let* ((method (first method-and-url))
+                                   (url (second method-and-url))
+                                   (words (loop while (string-match ":[-[:alnum:]]+" url)
+                                                collect (prog1 (intern (substring (match-string 0 url) 1))
+                                                          (setf url (replace-match "%s" t t url))))))
+                              (setf url (concat "/rest/api/latest/" url))
+                              `(defun ,(intern (format "jira-rest-%s-%s" method endpoint-name))
+                                 (instance ,@words ,@(unless (eq method 'get) '(data)) callback &optional callback-args)
+                                 (jira-rest-request instance
+                                                    (list ,(if (null words) url `(format ,url ,@words))
+                                                          ,@(if (eq method 'get)
+                                                                (list nil nil nil)
+                                                              (list (upcase (symbol-name method))
+                                                                    '(("Content-Type" . "application/json"))
+                                                                    '(json-encode data))))
+                                                    callback
+                                                    callback-args))))
+                          methods-and-urls))))
+  (endpoint project
+    (get "project"))
+  (endpoint filter
+    (get "filter/:filter-id"))
+  (endpoint search
+    (post "search"))
+  (endpoint issue
+    ((get put) "issue/:id-or-key"))
+  (endpoint create-issue-metadata
+    (get "issue/createmeta"))
+  (endpoint create-issue
+    (post "issue"))
+  (endpoint comment
+    (post "issue/:id-or-key/comment"))
+  (endpoint assignable-user
+    (get "user/assignable/search?issueKey=:issue-key&username=:user-search"))
+  (endpoint issue-transition
+    ((get post) "issue/:id-or-key/transitions"))
+  (endpoint server-info
+    (get "serverInfo"))
+  (endpoint resolution
+    (get "resolution"))
+  (endpoint watcher
+    (post "issue/:id-or-key/watchers")
+    (delete "issue/:id-or-key/watchers?username=:user-to-delete")))
 
 (defun jira-rest-auth-token (instance)
   (concat "Basic "
         jira-rest-instance instance)
   (labels ((got-server-info (info target-buffer)
              (with-current-buffer target-buffer
-               (jira-rest-get jira-rest-instance
-                              (jira-rest-project-endpoint)
-                              'got-projects
-                              (list info target-buffer))))
+               (jira-rest-get-project instance 'got-projects (list info target-buffer))))
            (got-projects (projects info target-buffer)
              (with-current-buffer target-buffer
-               (jira-rest-get jira-rest-instance
-                              (jira-rest-filter-endpoint "favourite")
-                              'got-filters
-                              (list projects info target-buffer))))
+               (jira-rest-get-filter instance "favourite" 'got-filters (list projects info target-buffer))))
            (got-filters (filters projects info target-buffer)
              (let ((row-count 0)
                    avatar-requests)
                       (overlay-put (make-overlay row-start (point)) 'face 'jira-rest-zebra-stripe-face)))
                   (incf row-count))
                 (jira-rest-load-images-async (nreverse avatar-requests))))))
-    (jira-rest-get instance
-                   (jira-rest-server-info-endpoint)
-                   'got-server-info
-                   (list (current-buffer)))))
+    (jira-rest-get-server-info instance 'got-server-info (list (current-buffer)))))
 
 (defun jira-rest-load-images-async (requests)
   (labels ((after-timeout (target-buffer requests request-level)
   (incf jira-rest-request-level)
   (setf jira-rest-instance instance
         jira-rest-revert-buffer
-        (list 'jira-rest-post
+        (list 'jira-rest-post-search
               instance
-              (jira-rest-search-endpoint)
               `((jql . ,(or (jira-rest-jql-text-search text) ""))
                 (maxResults . 20))
               (lambda (search-results text max-results target-buffer)
   (incf jira-rest-request-level)
   (setf jira-rest-instance instance
         jira-rest-revert-buffer
-        (list 'jira-rest-post
+        (list 'jira-rest-post-search
               instance
-              (jira-rest-search-endpoint)
               `((jql . ,(let ((text-query (jira-rest-jql-text-search text)))
                           (if (null text-query)
                               (format "project = \"%s\"" project)
   (incf jira-rest-request-level)
   (labels ((got-filter (filter filter-id target-buffer)
              (with-current-buffer target-buffer
-               (jira-rest-post jira-rest-instance
-                               (jira-rest-search-endpoint)
-                               `((jql . ,(format "filter = %s" filter-id)))
-                               'got-search-results
-                               (list filter filter-id target-buffer))))
+               (jira-rest-post-search jira-rest-instance
+                                      `((jql . ,(format "filter = %s" filter-id)))
+                                      'got-search-results
+                                      (list filter filter-id target-buffer))))
            (got-search-results (search-results filter filter-id target-buffer)
              (let ((issues (cdr (assoc 'issues search-results))))
                (with-jira-rest-buffer target-buffer
                 (jira-rest-display-issues issues)))))
     (setf jira-rest-instance instance
           jira-rest-revert-buffer
-          (list 'jira-rest-get
-                instance
-                (jira-rest-filter-endpoint filter-id)
-                'got-filter
-                (list filter-id (current-buffer))))
+          (list 'jira-rest-get-filter instance filter-id 'got-filter (list filter-id (current-buffer))))
     (jira-rest-revert-buffer)))
 
 (defun jira-rest-format-date (date)
   (incf jira-rest-request-level)
   (setf jira-rest-instance instance
         jira-rest-revert-buffer
-        (list 'jira-rest-get
+        (list 'jira-rest-get-issue
               instance
-              (jira-rest-issue-endpoint issue-key)
+              issue-key
               (lambda (issue issue-key target-buffer)
                 (let* ((fields (cdr (assoc 'fields issue)))
                        (project (cdr (assoc 'project fields)))
                     (summary (jira-rest-required-read "Summary"))
                     (description (read-string "Description: ")))
                ;; TODO: we should have a much more magit commit message style thing here
-               (jira-rest-post instance
-                               (jira-rest-create-issue-endpoint)
-                               `((fields . ((project . ((id . ,project-id)))
-                                            (issuetype . ((id . ,issue-type-id)))
-                                            (summary . ,summary)
-                                            ,@(unless (equal description "")
-                                                `((description . ,description))))))
-                               'got-new-issue-key
-                               (list instance))))
+               (jira-rest-post-create-issue instance
+                                            `((fields . ((project . ((id . ,project-id)))
+                                                         (issuetype . ((id . ,issue-type-id)))
+                                                         (summary . ,summary)
+                                                         ,@(unless (equal description "")
+                                                             `((description . ,description))))))
+                                            'got-new-issue-key
+                                            (list instance))))
            (got-new-issue-key (result instance)
              (let ((key (cdr (assoc 'key result))))
                (jira-rest-show-issue instance key)
                (message "Created issue %s" key))))
-    (jira-rest-get instance
-                   (jira-rest-create-issue-metadata-endpoint)
-                   'got-projects-and-issues
-                   (list instance))))
+    (jira-rest-get-create-issue-metadata instance 'got-projects-and-issues (list instance))))
 
 (defun jira-rest-revert-buffer (&optional ignore-auto noconfirm)
   "Reverts a jira-rest buffer.
   (interactive (list (jira-rest-infer-instance)
                      (jira-rest-infer-issue)
                      (jira-rest-required-read "Comment")))
-  (jira-rest-post instance
-                  (jira-rest-comment-endpoint key)
-                  `((body . ,comment))
-                  (lambda (_ instance key)
-                    (jira-rest-show-issue instance key))
-                  (list instance key)))
+  (jira-rest-post-comment instance
+                          key
+                          `((body . ,comment))
+                          (lambda (_ instance key)
+                            (jira-rest-show-issue instance key))
+                          (list instance key)))
 
 (defun jira-rest-assign-issue (instance key assignee)
   "Assigns the issue with specified KEY to ASSIGNEE."
                                     (with-current-buffer
                                         (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token instance)))))
                                           (url-retrieve-synchronously
+                                           ;; XXXXXXX
                                            (jira-rest-endpoint-for-instance instance (jira-rest-assignable-user-endpoint key prefix))))
                                       (with-jira-rest-response
                                        (jira-rest-skip-header)
                                                  (string= prefix (subseq name 0 (length prefix)))))
                                           names))))))))
                  (list instance key (completing-read "Assignee: " completer nil 'confirm))))
-  (jira-rest-put instance
-                 (jira-rest-issue-endpoint key)
-                 `((update . ((assignee . [((set . ((name . ,assignee))))]))))
-                 (lambda (_ instance key)
-                   (jira-rest-show-issue instance key))
-                 (list instance key)))
+  (jira-rest-put-issue instance
+                       key
+                       `((update . ((assignee . [((set . ((name . ,assignee))))]))))
+                       (lambda (_ instance key)
+                         (jira-rest-show-issue instance key))
+                       (list instance key)))
 
 (defun jira-rest-update-issue-summary (instance key summary)
   "Changes the summary of the issue with KEY to SUMMARY."
   (interactive (list (jira-rest-infer-instance)
                      (jira-rest-infer-issue)
                      (jira-rest-required-read "Summary")))
-  (jira-rest-put instance
-                 (jira-rest-issue-endpoint key)
-                 `((update . ((summary . [((set . ,summary))]))))
-                 (lambda (_ instance key)
-                   (jira-rest-show-issue instance key))
-                 (list instance key)))
+  (jira-rest-put-issue instance
+                       key
+                       `((update . ((summary . [((set . ,summary))]))))
+                       (lambda (_ instance key)
+                         (jira-rest-show-issue instance key))
+                       (list instance key)))
 
 ;; TODO this and functions like this should accept transition names and transition ids
 (defun jira-rest-update-issue-status (instance key transition-name &optional resolution-name)
                           (with-current-buffer
                               (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token instance)))))
                                 (url-retrieve-synchronously
+                                 ;; XXXXXXXX
                                  (jira-rest-endpoint-for-instance instance (jira-rest-issue-transitions-endpoint key))))
                             (with-jira-rest-response
                              (jira-rest-skip-header)
                        (with-current-buffer
                            (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token instance)))))
                              (url-retrieve-synchronously
+                              ;; XXXXXXXXX
                               (jira-rest-endpoint-for-instance instance (jira-rest-issue-endpoint key))))
                          (with-jira-rest-response
                           (jira-rest-skip-header)
                           (with-current-buffer
                               (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token instance)))))
                                 (url-retrieve-synchronously
+                                 ;; XXXXXXXXX
                                  (jira-rest-endpoint-for-instance instance (jira-rest-resolutions-endpoint))))
                             (with-jira-rest-response
                              (jira-rest-skip-header)
                                       :key (lambda (transition) (cdr (assoc 'name transition)))))
                     (transition-id (cdr (assoc 'id transition))))
                (if resolution-name
-                   (jira-rest-get instance
-                                  (jira-rest-resolutions-endpoint)
-                                  'got-resolutions
-                                  (list instance key transition-id resolution-name))
+                   (jira-rest-get-resolution instance 'got-resolutions (list instance key transition-id resolution-name))
                  (send-post instance key `((transition . ((id . ,transition-id))))))))
            (got-resolutions (resolutions instance key transition-id resolution-name)
              (let* ((resolution (find resolution-name resolutions
                (send-post instance key `((transition . ((id . ,transition-id)))
                                          (fields . ((resolution . ((id . ,resolution-id)))))))))
            (send-post (instance key data)
-             (jira-rest-post instance
-                             (jira-rest-issue-transitions-endpoint key)
-                             data
-                             'got-post-response
-                             (list instance key)))
+             (jira-rest-post-issue-transition instance key data 'got-post-response (list instance key)))
            (got-post-response (_ instance key)
              (jira-rest-show-issue instance key)))
-    (jira-rest-get instance
-                   (jira-rest-issue-transitions-endpoint key)
-                   'got-issue-transitions
-                   (list instance key transition-name resolution-name))))
+    (jira-rest-get-issue-transition instance key 'got-issue-transitions (list instance key transition-name resolution-name))))
 
 (defun jira-rest-watch-issue (instance key &optional stop-watching)
   "Starts watching the issue specified by KEY.
   (interactive (list (jira-rest-infer-instance)
                      (jira-rest-infer-issue)
                      current-prefix-arg))
-  (let ((username (jira-rest-instance-username instance)))
-    (funcall (if stop-watching 'jira-rest-delete 'jira-rest-post)
-             instance
-             (if stop-watching
-                 (jira-rest-watchers-endpoint key username)
-               (jira-rest-watchers-endpoint key))
-             username
-             (lambda (_ instance key)
-               (jira-rest-show-issue instance key))
-             (list instance key))))
+  (let ((username (jira-rest-instance-username instance))
+        (callback (lambda (_ instance key) (jira-rest-show-issue instance key)))
+        (args (list instance key)))
+    (if stop-watching
+        (jira-rest-delete-watcher instance key username nil callback args)
+      (jira-rest-post-watcher instance key username callback args))))
 
 (defun jira-rest-send-region-as-comment (start end instance issue-key)
   "Adds the contents of the buffer between START and END as a comment on ISSUE-KEY.