Commits

Hugh Giddens committed 5bfaeed

No longer need to specify instance twice for every network request.

Comments (0)

Files changed (1)

 (define-key jira-rest-issue-mode-map "u" 'jira-rest-update-issue-summary)
 (define-key jira-rest-issue-mode-map "t" 'jira-rest-update-issue-status)
 
-(defun jira-rest-instance-name ()
-  (first jira-rest-instance))
+(defun jira-rest-instance-name (instance)
+  (first instance))
 
-(defun jira-rest-instance-url (&optional instance)
-  (second jira-rest-instance))
+(defun jira-rest-instance-url (instance)
+  (second instance))
 
-(defun jira-rest-instance-username (&optional instance)
-  (third jira-rest-instance))
+(defun jira-rest-instance-username (instance)
+  (third instance))
 
-(defun jira-rest-instance-password (&optional instance)
-  (fourth jira-rest-instance))
+(defun jira-rest-instance-password (instance)
+  (fourth instance))
 
-(defun jira-rest-project-endpoint ()
-  (concat (jira-rest-instance-url) "/rest/api/latest/project"))
+(defun jira-rest-endpoint-for-instance (instance endpoint)
+  (concat (jira-rest-instance-url instance)
+          (if (eql (elt instance (1- (length instance))) ?/)
+                       (substring endpoint 1)
+                     endpoint)))
 
-(defun jira-rest-project-information-endpoint (key)
-  (concat (jira-rest-instance-url) "/rest/api/latest/project/" key))
+(defun jira-rest-project-endpoint ()
+  "/rest/api/latest/project")
 
 (defun jira-rest-filter-endpoint (filter-id)
-  (format "%s/rest/api/latest/filter/%s" (jira-rest-instance-url) filter-id))
-
-(defun jira-rest-favourite-filter-endpoint ()
-  (concat (jira-rest-instance-url) "/rest/api/latest/filter/favourite"))
+  (format "/rest/api/latest/filter/%s" filter-id))
 
 (defun jira-rest-search-endpoint ()
-  (concat (jira-rest-instance-url) "/rest/api/latest/search"))
+  "/rest/api/latest/search")
 
 (defun jira-rest-issue-endpoint (id-or-key)
-  (format "%s/rest/api/latest/issue/%s" (jira-rest-instance-url) id-or-key))
+  (format "/rest/api/latest/issue/%s" id-or-key))
 
-(defun jira-rest-create-issue-metadata-endpoint (&optional project-id issue-type-id)
-  (let ((prefix (concat (jira-rest-instance-url) "/rest/api/latest/issue/createmeta")))
-    (if (and project-id issue-type-id)
-        (format "%s?projectIds=%s&issuetypeIds=%s&expand=projects.issuetypes.fields"
-                prefix project-id issue-type-id)
-      prefix)))
+(defun jira-rest-create-issue-metadata-endpoint ()
+  "/rest/api/latest/issue/createmeta")
 
 (defun jira-rest-create-issue-endpoint ()
-  (concat (jira-rest-instance-url) "/rest/api/latest/issue"))
+  "/rest/api/latest/issue")
 
 (defun jira-rest-comment-endpoint (id-or-key)
-  (format "%s/rest/api/latest/issue/%s/comment" (jira-rest-instance-url) id-or-key))
+  (format "/rest/api/latest/issue/%s/comment" id-or-key))
 
 (defun jira-rest-assignable-user-endpoint (issue-key user-search)
-  (format "%s/rest/api/latest/user/assignable/search?issueKey=%s&username=%s"
-          (jira-rest-instance-url) 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 "%s/rest/api/latest/issue/%s/transitions" (jira-rest-instance-url) id-or-key))
+  (format "/rest/api/latest/issue/%s/transitions" id-or-key))
 
 (defun jira-rest-server-info-endpoint ()
-  (concat (jira-rest-instance-url) "/rest/api/latest/serverInfo"))
+  "/rest/api/latest/serverInfo")
 
 (defun jira-rest-resolutions-endpoint ()
-  (concat (jira-rest-instance-url) "/rest/api/latest/resolution"))
+  "/rest/api/latest/resolution")
 
 (defun jira-rest-watchers-endpoint (id-or-key &optional user-to-delete)
-  (format "%s/rest/api/latest/issue/%s/watchers%s"
-          (jira-rest-instance-url)
+  (format "/rest/api/latest/issue/%s/watchers%s"
           id-or-key
           (if user-to-delete (concat "?username=" user-to-delete) "")))
 
-(defun jira-rest-auth-token ()
+(defun jira-rest-auth-token (instance)
   (concat "Basic "
-          (base64-encode-string (concat (jira-rest-instance-username)
+          (base64-encode-string (concat (jira-rest-instance-username instance)
                                         ":"
-                                        (jira-rest-instance-password)))))
+                                        (jira-rest-instance-password instance)))))
 
 (defmacro with-jira-rest-response (&rest body)
   (let ((buffer (gensym)))
 (defmacro jira-rest-retrieve (url callback args)
   `(url-retrieve ,url ,callback ,args ,@(if (eql emacs-major-version 23) nil (list t))))
 
-(defun jira-rest-request (url-parameters callback args)
+(defun jira-rest-request (instance url-parameters callback args)
   "Submits a request to JIRA.
 
 URL-PARAMETERS should be a list of four elements, containing as
 Wraps `url-retrieve', which should be seen for more details."
   (destructuring-bind (url url-request-method url-request-extra-headers url-request-data)
       url-parameters
-    (push (cons "Authorization" (jira-rest-auth-token)) url-request-extra-headers)
-    (jira-rest-retrieve url
+    (push (cons "Authorization" (jira-rest-auth-token instance)) url-request-extra-headers)
+    (jira-rest-retrieve (jira-rest-endpoint-for-instance instance url)
                         (lambda (status callback args)
                           (with-jira-rest-response
                            (destructuring-bind (&optional error-symbol . data) (plist-get status :error)
                            (apply callback (jira-rest-parse-response status) args)))
                         (list callback args))))
 
-(defun jira-rest-get (url callback &optional args)
-  (jira-rest-request (list url nil nil nil) callback args))
+(defun jira-rest-get (instance url callback &optional args)
+  (jira-rest-request instance (list url nil nil nil) callback args))
 
-(defun jira-rest-post (url data callback &optional args)
-  (jira-rest-request (list url "POST" '(("Content-Type" . "application/json")) (json-encode data))
+(defun jira-rest-post (instance url data callback &optional args)
+  (jira-rest-request instance (list url "POST" '(("Content-Type" . "application/json")) (json-encode data))
                      callback args))
 
-(defun jira-rest-put (url data callback &optional args)
-  (jira-rest-request (list url "PUT" '(("Content-Type" . "application/json")) (json-encode data))
+(defun jira-rest-put (instance url data callback &optional args)
+  (jira-rest-request instance (list url "PUT" '(("Content-Type" . "application/json")) (json-encode data))
                      callback args))
 
-(defun jira-rest-delete (url data callback &optional args)
-  (jira-rest-request (list url "DELETE" '(("Content-Type" . "application/json")) (json-encode data))
+(defun jira-rest-delete (instance url data callback &optional args)
+  (jira-rest-request instance (list url "DELETE" '(("Content-Type" . "application/json")) (json-encode data))
                      callback args))
 
 (defun jira-rest-required-read (prompt &optional completions)
 (defun jira-rest-list-projects-and-filters (instance)
   "Lists the projects and favourited filters of INSTANCE."
   (interactive (list (jira-rest-infer-instance)))
-  (switch-to-buffer (let ((jira-rest-instance instance))
-                      (format "*%s*" (jira-rest-instance-name))))
+  (switch-to-buffer (format "*%s*" (jira-rest-instance-name instance)))
   (unless (eq major-mode 'jira-rest-mode)
     (jira-rest-mode))
   (incf jira-rest-request-level)
         jira-rest-instance instance)
   (labels ((got-server-info (info target-buffer)
              (with-current-buffer target-buffer
-               (jira-rest-get (jira-rest-project-endpoint)
+               (jira-rest-get jira-rest-instance
+                              (jira-rest-project-endpoint)
                               'got-projects
                               (list info target-buffer))))
            (got-projects (projects info target-buffer)
              (with-current-buffer target-buffer
-               (jira-rest-get (jira-rest-favourite-filter-endpoint)
+               (jira-rest-get jira-rest-instance
+                              (jira-rest-filter-endpoint "favourite")
                               'got-filters
                               (list projects info target-buffer))))
            (got-filters (filters projects info target-buffer)
                       (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 (jira-rest-server-info-endpoint) 'got-server-info (list (current-buffer)))))
+    (jira-rest-get instance
+                   (jira-rest-server-info-endpoint)
+                   'got-server-info
+                   (list (current-buffer)))))
 
 (defun jira-rest-load-images-async (requests)
   (labels ((after-timeout (target-buffer requests request-level)
              (with-current-buffer target-buffer
                (dolist (request requests)
                  (destructuring-bind (url . insertion-points) request
-                   (jira-rest-retrieve url 'got-avatar (list target-buffer insertion-points request-level))))))
+                   (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token jira-rest-instance)))))
+                     (jira-rest-retrieve url 'got-avatar (list target-buffer insertion-points request-level)))))))
            (got-avatar (status target-buffer insertion-points request-level)
              (let ((buffer (current-buffer)))
                (unwind-protect
 Summary, description, and comment fields are searched."
   (interactive (list (jira-rest-infer-instance)
                      (read-string "Search: ")))
-  (switch-to-buffer (let ((jira-rest-instance instance))
-                      (format "*%s Search*" (jira-rest-instance-name))))
+  (switch-to-buffer (format "*%s Search*" (jira-rest-instance-name instance)))
   (unless (eq major-mode 'jira-rest-mode)
     (jira-rest-mode))
   (incf jira-rest-request-level)
   (setf jira-rest-instance instance
         jira-rest-revert-buffer
         (list 'jira-rest-post
+              instance
               (jira-rest-search-endpoint)
               `((jql . ,(or (jira-rest-jql-text-search text) ""))
                 (maxResults . 20))
                      (read-string "Query: ")))
   ;; TODO should only request the fields needed?
   ;; TODO should do a completing-read for projects.
-  (switch-to-buffer (let ((jira-rest-instance instance))
-                      (format "*%s Search*" (jira-rest-instance-name))))
+  (switch-to-buffer (format "*%s Search*" (jira-rest-instance-name instance)))
   (unless (eq major-mode 'jira-rest-mode)
     (jira-rest-mode))
   (incf jira-rest-request-level)
   (setf jira-rest-instance instance
         jira-rest-revert-buffer
         (list 'jira-rest-post
+              instance
               (jira-rest-search-endpoint)
               `((jql . ,(let ((text-query (jira-rest-jql-text-search text)))
                           (if (null text-query)
   (interactive (list (jira-rest-infer-instance)
                      (read-number "Filter ID: ")))
   ;; TODO should do a completing read for the filter id
-  (switch-to-buffer (let ((jira-rest-instance instance))
-                      (format "*%s Search*" (jira-rest-instance-name))))
+  (switch-to-buffer (format "*%s Search*" (jira-rest-instance-name instance)))
   (unless (eq major-mode 'jira-rest-mode)
     (jira-rest-mode))
   (incf jira-rest-request-level)
   (labels ((got-filter (filter filter-id target-buffer)
              (with-current-buffer target-buffer
-               (jira-rest-post (jira-rest-search-endpoint)
+               (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))))
     (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))))
   (interactive (list (jira-rest-infer-instance)
                      (jira-rest-required-read "Issue Key")))
   (setf issue-key (upcase issue-key))
-  (switch-to-buffer (let ((jira-rest-instance instance))
-                      (format "*%s %s*" (jira-rest-instance-name) issue-key)))
+  (switch-to-buffer (format "*%s %s*" (jira-rest-instance-name instance) issue-key))
   (unless (eq major-mode 'jira-rest-issue-mode)
     (jira-rest-issue-mode))
   (setf jira-rest-default-issue issue-key)
   (setf jira-rest-instance instance
         jira-rest-revert-buffer
         (list 'jira-rest-get
+              instance
               (jira-rest-issue-endpoint issue-key)
               (lambda (issue issue-key target-buffer)
                 (let* ((fields (cdr (assoc 'fields issue)))
   (labels ((project-key (project) (cdr (assoc 'key project)))
            (issue-type-name (issue-type) (cdr (assoc 'name issue-type)))
            (got-projects-and-issues (issue-creation-metadata instance)
-             (let* ((jira-rest-instance instance)
-                    (projects (cdr (assoc 'projects issue-creation-metadata)))
+             (let* ((projects (cdr (assoc 'projects issue-creation-metadata)))
                     (project-key-list (mapcar 'project-key projects))
                     (key (jira-rest-required-read "Project key" project-key-list))
                     (project (find key projects :test 'equal :key 'project-key))
                     (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 (jira-rest-create-issue-endpoint)
+               (jira-rest-post instance
+                               (jira-rest-create-issue-endpoint)
                                `((fields . ((project . ((id . ,project-id)))
                                             (issuetype . ((id . ,issue-type-id)))
                                             (summary . ,summary)
              (let ((key (cdr (assoc 'key result))))
                (jira-rest-show-issue instance key)
                (message "Created issue %s" key))))
-    (let ((jira-rest-instance instance))
-      (jira-rest-get (jira-rest-create-issue-metadata-endpoint)
-                     'got-projects-and-issues
-                     (list instance)))))
+    (jira-rest-get instance
+                   (jira-rest-create-issue-metadata-endpoint)
+                   '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")))
-  (let ((jira-rest-instance instance))
-    (jira-rest-post (jira-rest-comment-endpoint key)
-                    `((body . ,comment))
-                    (lambda (_ instance key)
-                      (jira-rest-show-issue instance key))
-                    (list instance key))))
+  (jira-rest-post instance
+                  (jira-rest-comment-endpoint 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."
                       (key (jira-rest-infer-issue))
                       (completer (completion-table-dynamic
                                   (lambda (prefix)
-                                    (with-current-buffer (url-retrieve-synchronously
-                                                          (let ((jira-rest-instance instance))
-                                                            (jira-rest-assignable-user-endpoint key prefix)))
+                                    (with-current-buffer
+                                        (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token instance)))))
+                                          (url-retrieve-synchronously
+                                           (jira-rest-endpoint-for-instance instance (jira-rest-assignable-user-endpoint key prefix))))
                                       (with-jira-rest-response
                                        (jira-rest-skip-header)
                                        (let* ((names (mapcar (lambda (user) (cdr (assoc 'name user)))
                                                  (string= prefix (subseq name 0 (length prefix)))))
                                           names))))))))
                  (list instance key (completing-read "Assignee: " completer nil 'confirm))))
-  (let ((jira-rest-instance instance))
-    (jira-rest-put (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 instance
+                 (jira-rest-issue-endpoint 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")))
-  (let ((jira-rest-instance instance))
-    (jira-rest-put (jira-rest-issue-endpoint key)
-                   `((update . ((summary . [((set . ,summary))]))))
-                   (lambda (_ instance key)
-                     (jira-rest-show-issue instance key))
-                   (list instance key))))
+  (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)))
 
 ;; 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)
                       (transition-completer
                        (completion-table-dynamic
                         (lambda (prefix)
-                          (with-current-buffer (url-retrieve-synchronously
-                                                (let ((jira-rest-instance instance))
-                                                  (jira-rest-issue-transitions-endpoint key)))
+                          (with-current-buffer
+                              (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token instance)))))
+                                (url-retrieve-synchronously
+                                 (jira-rest-endpoint-for-instance instance (jira-rest-issue-transitions-endpoint key))))
                             (with-jira-rest-response
                              (jira-rest-skip-header)
                              (loop for transition in (cdr (assoc 'transitions
                                    collect name))))))
                       (transition-name (jira-rest-required-read "Transition" transition-completer))
                       (resolution
-                       (with-current-buffer (url-retrieve-synchronously
-                                             (let ((jira-rest-instance instance))
-                                               (jira-rest-issue-endpoint key)))
+                       (with-current-buffer
+                           (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token instance)))))
+                             (url-retrieve-synchronously
+                              (jira-rest-endpoint-for-instance instance (jira-rest-issue-endpoint key))))
                          (with-jira-rest-response
                           (jira-rest-skip-header)
                           (cdr (assoc 'resolution (cdr (assoc 'fields (jira-rest-parse-document))))))))
                       (resolution-completer
                        (completion-table-dynamic
                         (lambda (prefix)
-                          (with-current-buffer (url-retrieve-synchronously
-                                                (let ((jira-rest-instance instance))
-                                                  (jira-rest-resolutions-endpoint)))
+                          (with-current-buffer
+                              (let ((url-request-extra-headers `(("Authorization" . ,(jira-rest-auth-token instance)))))
+                                (url-retrieve-synchronously
+                                 (jira-rest-endpoint-for-instance instance (jira-rest-resolutions-endpoint))))
                             (with-jira-rest-response
                              (jira-rest-skip-header)
                              (loop for resolution in (jira-rest-parse-document)
              (let* ((transition (find transition-name (cdr (assoc 'transitions transitions))
                                       :test 'string=
                                       :key (lambda (transition) (cdr (assoc 'name transition)))))
-                    (transition-id (cdr (assoc 'id transition)))
-                    (jira-rest-instance instance))
+                    (transition-id (cdr (assoc 'id transition))))
                (if resolution-name
-                   (jira-rest-get (jira-rest-resolutions-endpoint)
+                   (jira-rest-get instance
+                                  (jira-rest-resolutions-endpoint)
                                   'got-resolutions
                                   (list instance key transition-id resolution-name))
                  (send-post instance key `((transition . ((id . ,transition-id))))))))
              (let* ((resolution (find resolution-name resolutions
                                       :test 'string=
                                       :key (lambda (transition) (cdr (assoc 'name transition)))))
-                    (resolution-id (cdr (assoc 'id resolution)))
-                    (jira-rest-instance instance))
+                    (resolution-id (cdr (assoc 'id resolution))))
                (send-post instance key `((transition . ((id . ,transition-id)))
                                          (fields . ((resolution . ((id . ,resolution-id)))))))))
            (send-post (instance key data)
-             (let ((jira-rest-instance instance))
-               (jira-rest-post (jira-rest-issue-transitions-endpoint key)
-                               data
-                               'got-post-response
-                               (list instance key))))
+             (jira-rest-post instance
+                             (jira-rest-issue-transitions-endpoint key)
+                             data
+                             'got-post-response
+                             (list instance key)))
            (got-post-response (_ instance key)
              (jira-rest-show-issue instance key)))
-    (let ((jira-rest-instance instance))
-      (jira-rest-get (jira-rest-issue-transitions-endpoint key)
-                     'got-issue-transitions
-                     (list instance key transition-name resolution-name)))))
+    (jira-rest-get instance
+                   (jira-rest-issue-transitions-endpoint 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 ((jira-rest-instance instance))
+  (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 (jira-rest-instance-username))
+                 (jira-rest-watchers-endpoint key username)
                (jira-rest-watchers-endpoint key))
-             (jira-rest-instance-username)
+             username
              (lambda (_ instance key)
                (jira-rest-show-issue instance key))
              (list instance key))))