blob: 98857db69d3b483f8dd79ea8833579438421e087 [file] [log] [blame]
;; -*- lexical-binding: t -*-
;; Copyright 2020 The Chromium OS Authors. All rights reserved.
;; Use of this source code is governed by a BSD-style license that can be
;; found in the LICENSE file.
(require 'request)
;; TODO this is test code to be removed in future CL.
(setq test-user "jrosenth")
(setq test-host "chromium-review.googlesource.com")
(setq test-repo-root (file-name-as-directory "~/chromiumos"))
(setq test-repo-manifest-path (expand-file-name ".repo/manifests/default.xml" test-repo-root))
(cl-defun gerrit--fetch-recent-changeid-project-pairs (host user &optional (count 3))
"Fetches recent changes as changeid project dotted pairs.
host - Gerrit server address
user - the user who owns the recent changes
count (optional) - the number of recent changes, default is 3
Fetch recent changes that are not abandoned/merged, and
thus are actionable, returns a list of dotted pairs
of the form (change-id . project)."
(let ((response
(request
(format "https://%s/changes/" host)
;; We don't use "status:reviewed" because that only counts reviews after latest patch,
;; but we may want reviews before the latest patch too.
:params `(("q" . ,(format "owner:%s status:open" user))
("n" . ,(format "%d" count)))
:sync t
:parser 'gerrit--request-response-json-parser
:success (lambda (&key data error-thrown &allow-other-keys)
(when error-thrown
(message "%s" error-thrown))))))
(loop for change across (request-response-data response)
collect `(,(gethash "change_id" change) . ,(gethash "project" change)))))
(defun gerrit--request-response-json-parser ()
"Response parsing callback for use with request.el
parses Gerrit response json payload by removing the
embedded XSS protection string before using a real json parser."
(json-parse-string (replace-regexp-in-string "^[[:space:]]*)]}'" "" (buffer-string))))
(defun gerrit--get-unresolved-comments (host project change-id)
"Gets recent unresolved comments for open Gerrit CLs.
Returns a map of the form path => sequence of comments,
where path is the filepath from the gerrit project root
and each comment represents a CommentInfo entity from Gerrit"
(let* ((response
(request
(format "https://%s/changes/%s~master~%s/comments"
host
(url-hexify-string project)
change-id)
:sync t
:parser 'gerrit--request-response-json-parser
:success (lambda (&key data error-thrown &allow-other-keys)
(when error-thrown
(message "%s" error-thrown)))))
(out-map (request-response-data response)))
;; We only want the user to see unresolved comments.
(loop for key in (hash-table-keys out-map) do
;; We explicitly check if not true because the value may be ':false'
;; which is technically evals to true as it is not nil.
(delete-if (lambda (comment) (not (eql t (gethash "unresolved" comment))))
(gethash key out-map)))
out-map))
(defun gerrit--fetch-map-changeid-project-pair-to-unresolved-comments (host user)
"Returns a map of maps of the form:
(change-id . project) => filepath => Sequence(CommentInfo Map),
where filepath is from the nearest git root for a file."
;; The return value is intended as a local cache of comments for user's recent changes.
(let ((out-map (make-hash-table :test 'equal)))
(loop for pair in (gerrit--fetch-recent-changeid-project-pairs host user) do
(setf (gethash pair out-map)
(gerrit--get-unresolved-comments host (cdr pair) (car pair))))
out-map))