Compare commits

...

4 commits

3 changed files with 61 additions and 15 deletions

View file

@ -82,6 +82,28 @@ Returns a list of pull request objects on success, nil on failure."
(message "Error fetching pull requests: %s" error-thrown))))) (message "Error fetching pull requests: %s" error-thrown)))))
result)) result))
(defun ghpr--get-pr (repo-name pr-number)
"Retrieve a single pull request by PR-NUMBER in REPO-NAME.
Returns a parsed PR object on success, nil on failure."
(let ((token (ghpr--get-token))
(url (format "https://api.github.com/repos/%s/pulls/%s" repo-name pr-number))
(result nil))
(when token
(request url
:type "GET"
:headers `(("Accept" . "application/vnd.github+json")
("Authorization" . ,(format "Bearer %s" token))
("X-GitHub-Api-Version" . "2022-11-28"))
:parser 'json-read
:sync t
:success (cl-function
(lambda (&key data &allow-other-keys)
(setq result (ghpr--parse-api-pr data))))
:error (cl-function
(lambda (&key error-thrown &allow-other-keys)
(message "Error fetching PR: %s" error-thrown)))))
result))
(defun ghpr--get-diff-content (repo-name pr-number) (defun ghpr--get-diff-content (repo-name pr-number)
"Retrieve the diff contents for PR-NUMBER in REPO-NAME." "Retrieve the diff contents for PR-NUMBER in REPO-NAME."
(let ((token (ghpr--get-token)) (let ((token (ghpr--get-token))

View file

@ -68,14 +68,14 @@
("^\\(> \\)$" (0 'ghpr-review-misc-line t))) ("^\\(> \\)$" (0 'ghpr-review-misc-line t)))
"Font lock keywords for ghpr-review-mode.") "Font lock keywords for ghpr-review-mode.")
(defvar-local ghpr--review-diff-content nil (defvar-local ghpr--review-base-content nil
"Buffer-local variable storing the diff content for the current PR.") "Stores the base starting content, including diff, for the current PR.")
(defvar-local ghpr--review-pr-metadata nil (defvar-local ghpr--review-pr-metadata nil
"Buffer-local variable storing the PR metadata for the current PR.") "Stores the PR metadata for the current PR.")
(defvar-local ghpr--review-repo-name nil (defvar-local ghpr--review-repo-name nil
"Buffer-local variable storing the repository name for the current PR.") "Stores the repository name for the current PR.")
(defvar ghpr-review-mode-map (defvar ghpr-review-mode-map
(let ((map (make-sparse-keymap)) (let ((map (make-sparse-keymap))
@ -111,7 +111,7 @@
"Return a string of the title, body, and patch content separated by newlines." "Return a string of the title, body, and patch content separated by newlines."
(let* ((body (or (alist-get 'body pr) "")) (let* ((body (or (alist-get 'body pr) ""))
(content-parts (list (ghpr--pr-summary pr)))) (content-parts (list (ghpr--pr-summary pr))))
(when (not (string-empty-p body)) (when (and body (not (string-empty-p body)))
(push body content-parts)) (push body content-parts))
(when diff-content (when diff-content
(push diff-content content-parts)) (push diff-content content-parts))
@ -122,11 +122,11 @@
(erase-buffer) (erase-buffer)
(let* ((number (alist-get 'number pr)) (let* ((number (alist-get 'number pr))
(diff-content (ghpr--get-diff-content repo-name number)) (diff-content (ghpr--get-diff-content repo-name number))
(contents (ghpr--open-pr/collect-contents pr diff-content))) (contents (ghpr--prefix-lines (ghpr--open-pr/collect-contents pr diff-content))))
(setq ghpr--review-diff-content diff-content) (setq ghpr--review-base-content contents)
(setq ghpr--review-pr-metadata pr) (setq ghpr--review-pr-metadata pr)
(setq ghpr--review-repo-name repo-name) (setq ghpr--review-repo-name repo-name)
(insert (ghpr--prefix-lines contents)))) (insert contents)))
(defun ghpr--open-pr (pr repo-name) (defun ghpr--open-pr (pr repo-name)
"Open a new buffer containing the body of the PR." "Open a new buffer containing the body of the PR."
@ -339,6 +339,14 @@ Returns an alist with comment, file-path, commit-sha, and diff-position, or nil
(commit-sha . ,(alist-get 'commit-sha context)) (commit-sha . ,(alist-get 'commit-sha context))
(diff-position . ,(alist-get 'diff-position context))))))) (diff-position . ,(alist-get 'diff-position context)))))))
(defun ghpr--validate-base-content-unchanged ()
"Validate that all base content (lines with > or < prefixes) remains unchanged.
Returns t if validation passes, nil otherwise."
(let* ((current-lines (split-string (buffer-string) "\n"))
(base-lines (split-string ghpr--review-base-content "\n"))
(current-base-lines (seq-filter #'ghpr--special-line-p current-lines)))
(equal current-base-lines base-lines)))
(defun ghpr--collect-review-comments () (defun ghpr--collect-review-comments ()
"Collect all inline review comments from the current buffer. "Collect all inline review comments from the current buffer.
Returns an alist of comments with their associated diff lines and GitHub API context. Returns an alist of comments with their associated diff lines and GitHub API context.
@ -367,6 +375,9 @@ Collects review body and inline comments from current buffer."
(error "No PR metadata found in buffer")) (error "No PR metadata found in buffer"))
(unless ghpr--review-repo-name (unless ghpr--review-repo-name
(error "No repository name found in buffer")) (error "No repository name found in buffer"))
;; TODO: needs better usability. maybe highlight which lines were broken/missing and restore.
(unless (ghpr--validate-base-content-unchanged)
(error "Base content has been modified. Please restore the original diff content before submitting"))
(let* ((body (ghpr--collect-review-body)) (let* ((body (ghpr--collect-review-body))
(inline-comments (ghpr--collect-review-comments)) (inline-comments (ghpr--collect-review-comments))
@ -382,13 +393,17 @@ Collects review body and inline comments from current buffer."
(or (not body) (string-empty-p (string-trim body)))) (or (not body) (string-empty-p (string-trim body))))
(error "Review body is required for %s events" event)) (error "Review body is required for %s events" event))
(unless (ghpr--create-review ghpr--review-repo-name (when (yes-or-no-p (format "Submit review (%s)? " event))
(if (ghpr--create-review ghpr--review-repo-name
pr-number pr-number
commit-sha commit-sha
(or body "") (or body "")
event event
api-comments) api-comments)
(message "Failed to submit review")))) (progn
(message "Review submitted successfully")
(kill-buffer (current-buffer)))
(message "Failed to submit review")))))
(defun ghpr-review-comment () (defun ghpr-review-comment ()
"Submit review comments with COMMENT event." "Submit review comments with COMMENT event."

View file

@ -54,6 +54,15 @@
(let ((pr (cdr (assoc selected-item pr-items)))) (let ((pr (cdr (assoc selected-item pr-items))))
(ghpr--open-pr pr repo-name)))))))) (ghpr--open-pr pr repo-name))))))))
(defun ghpr-open-pr (pr-number)
"Open a specific pull request by PR-NUMBER."
(interactive "nPR number: ")
(let* ((repo-name (ghpr--get-repo-name))
(pr (when repo-name (ghpr--get-pr repo-name pr-number))))
(if pr
(ghpr--open-pr pr repo-name)
(message "Could not open PR #%d" pr-number))))
(provide 'ghpr) (provide 'ghpr)
;;; ghpr.el ends here ;;; ghpr.el ends here