Egerrit is a package which makes it possible to work with Gerrit Code Review from within the comfort of Emacs. The package gets started when the user requests the
The packaged is designed around the idea that the user of the package have different roles. For changes committed by other, the user takes upon the role of
reviewer. While for patches created by the user he/she takes the role of an
As an author of a change it should be easy to get and act on external feedback. The feedback can be provided either by peers, or by a CI machinery.
For a given change its easy to jump to the output of a CI job. The output will be opened in the context of project the change belongs to. Making it easy to navigate to the source code where errors have occurred.
The author can also open a buffer with conversations on the given change. There are keybindings to navigate between conversations, and the author can also engage in the conversation. When navigating between conversations the location in the source code are directly shown as well.
In the role of a reviewer, the user might be less interested in finding issues in CI jobs and instead more focused on the content of the change. Its easy to start a review on a change. When doing so one window with the patch diff is shown together with a window of conversations. The reviewer can highlight parts of the patch diff and start a conversation. Or engage in an existing conversation.
When navigating between conversations as a reviewer the patch diff buffer is automatically updated to show what the conversation is about. Conversations can be started around a location not accessible in the patch diff, or when showing conversations started on earlier patch sets. To mitigate that issue the context is always shown in relation to the conversation.
The package has only one external dependency, which is to the transient package. It supports Emacs version 27 and newer.
Egerrit requires the user to have the the following external tools installed:
For the time being users of the package needs to install it manually from source.
Here is a minimal use-package configuration to get started with
(use-package egerrit :commands egerrit-dashboard :custom ((egerrit-request-url "gerrit.something.com")))
The package provides the following modes:
In the dashboard the package relies on
transient to provide a more user-friendly interface. The different transient commands can be viewed by pressing
egerrit-diff-mode is used when the review view is opened for a change.
|egerrit-create-comment||C-c '||Create a comment at point|
|egerrit-open-conversations-buffer||C-c C-c||Open conversations buffer|
|egerrit-quit-review-or-feedback||C-c C-q||Quit review|
|egerrit-open-info||C-c C-i||Open a status buffer for change at point|
|egerrit-publish-review-label||C-c C-r||Set and publish a review label|
egerrit-job-mode is used when viewing a CI job output.
|egerrit-switch-to-other-job||C-c C-j||Switch to another job|
|egerrit-quit-job||C-c C-q||Quit job|
egerrit-comment-mode is used when composing a comment.
|egerrit-complete-comment||C-c C-c||Complete the comment|
|delete-window||C-c C-k||Quit and discard comment|
egerrit-conversation-mode is activated in the
|egerrit-visit-conversation||Visit conversation location|
|egerrit-visit-conversation-source-code||S-||Visit the source code which the conversation relates to|
|egerrit-create-comment||C-c '||Join a conversation by creating a comment|
|egerrit-kill-comment||C-c C-k||Kill a comment in a conversation|
|egerrit-open-info||C-c C-i||Open a status buffer for change at point|
|egerrit-quit-review-or-feedback||C-c C-q||Quit the conversations buffer|
|egerrit-toggle-conversation-status||C-c C-t||Toggle the status of the conversation|
|egerrit-review-change||C-c C-r||Set review label on change|
|egerrit-next-conversation||M-n||Navigate to next conversation|
|egerrit-previous-conversation||M-p||Navigate to previous conversation|
|egerrit-publish-comments||C-c C-s||Publish your comments to Gerrit|
|egerrit-dashboard-config||Which columns to display and how to obtain its values|
|egerrit-revision-config||Which information to display when listing revisions|
|egerrit-job-config||Which information to display when listing CI jobs|
|egerrit-request-url||The url to the Gerrit server|
|egerrit-max-changes||Maximum number of changes to retrieve|
|egerrit-job-regexp||Regular expression to capture CI job information|
|egerrit-project-configs||A list of project configurations|
|egerrit-comment-block-list||A list of regular expressions for comments that should be blocked|
|egerrit-commit-message-source-code-function||A function that can locate the source of a commit message|
|egerrit-job-function||A function which adds CI jobs to a Gerrit change|
|egerrit-comment-formatter||A function which can format a comment|
|egerrit-status-formatter||A function which can format the status of a conversation|
|egerrit-git-diff-context||A variable determining number of context lines in git diff|
|egerrit-gerrit-conversation-context||A variable determining number of context lines in conversations|
The package is designed to support multiple projects. The variable
egerrit-project-configs contain a mapping between the name of the project, which should be the name that will show up in Gerrit, and a config.
(setq egerrit-project-roots '((:name "foo" :code-repo "~/git/foo" :review-repo "~/git/foo-review/") (:name "bar" :code-repo "~/git/bar")))
The package has a concept it call views. This makes it possible to have different queries definied in your package configuration which you can quickly switch between. A query can be composed of multiple queries. The default views are:
`(("Gerrit Dashboard" . (("Has draft comments" . ("has:draft")) ("Your turn" . ("attention:self")) ("Work in progress" . ("is:open owner:self is:wip")) ("Outgoing reviews" . ("is:open owner:self -is:wip -is:ignored")) ("Incoming reviews" . ("is:open -owner:self -is:wip -is:ignored (reviewer:self OR assignee:self)")) ("CCed on" . ("is:open -is:ignored cc:self")) ("Recently closed" . ("is:closed -is:ignored (-is:wip OR owner:self) (owner:self OR reviewer:self OR assignee:self OR cc:self)" 20)))) ("Custom" . egerrit-custom-query))
As can be seen there are two different views
Gerrit Dashboard and
Custom. The former mimics the default view of Gerrit. Each of the entries in its alist will turn into headings in the dashboard view.
egerrit relies on the Emacs auth-source library. This library supports gpg encryption and integrates with the pass unix password manager. It is recommended to use the HTTP password for authentication. This password can be generated in Gerrit's web interface.
If you are not a user of
pass, consult the variable
auth-sources for files which can store the authentication information. The default values should be:
("~/.authinfo" "~/.authinfo.gpg" "~/.netrc")
Add the following entry to any of the possible files.
machine gerrit.something.net login USERNAME password PASSWORD
PASSWORD with your own values.
The excellent magit package can be utilized in
egerrit. We can make
magit-commit-ammend be called automatically when we press the return key on a conversation that revolves around the commit message.
(setq egerrit-commit-message-source-code-function #'magit-commit-amend)
egerrit dashboard open in a dedicated tab using tab-bar.
(defun my/egerrit-dashboard-tab () "Open the `egerrit' dashboard for current buffer in a tab." (interactive) (let ((tabname "Gerrit") (tabs (mapcar (lambda (tab) (alist-get 'name tab)) (tab-bar-tabs))) (buffer (current-buffer))) ;; Create or switch to Egerrit tab (if (member tabname tabs) (tab-bar-switch-to-tab tabname) (tab-bar-new-tab) (tab-bar-rename-tab tabname)) (with-current-buffer buffer (egerrit-dashboard))))
Its possible to use markdown-mode package to enhance the fontification of comments in the conversation buffer.
(defun my/egerrit-comment-formatter () "Use `gfm' as formatter. " (gfm-mode) (font-lock-ensure)) (setq egerrit-comment-formatter my/egerrit-comment-formatter)
It can also be integrated with the
egerrit-comment-mode to allow for a better experience when creating comments.
(add-hook 'egerrit-comment-hooks #'gfm-mode)
egerrit package uses line breaks
^L to separate conversations. For a prettier solution use the page-break-lines package.
(add-hook 'egerrit-conversation-mode-hook #'page-break-lines-mode)