~niklaseklund/egerrit

An Emacs interface to Gerrit
Move egerrit-dashboard command to egerrit
Update egerrit-dashboard
Check for local files before querying in autogen

clone

read-only
https://git.sr.ht/~niklaseklund/egerrit
read/write
git@git.sr.ht:~niklaseklund/egerrit

You can also use your local clone with git send-email.

#Emacs 💕 Gerrit

Build

#Introduction

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 egerrit-dashboard.

#Design

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 author.

#Author

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.

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.

#Reviewer

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.

#Dependencies

The package has only one external dependency, which is to the transient package. It supports Emacs version 27 and newer.

#External tools

Egerrit requires the user to have the the following external tools installed:

#Installation

For the time being users of the package needs to install it manually from source.

#Use-package example

Here is a minimal use-package configuration to get started with egerrit.

(use-package egerrit
  :commands egerrit-dashboard
  :custom ((egerrit-request-url "gerrit.something.com")))

#Modes

The package provides the following modes:

  • egerrit-dashboard-mode (major)
  • egerrit-diff-mode (major)
  • egerrit-job-mode (major)
  • egerrit-conversation-mode (major)
  • egerrit-comment-mode (minor)

#Egerrit-Dashboard-Mode

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

The egerrit-diff-mode is used when the review view is opened for a change.

Command Binding Description
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

The egerrit-job-mode is used when viewing a CI job output.

| Command | Binding | Description | |--------------------------------+---------+-------------------------------| | 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

The egerrit-comment-mode is used when composing a comment.

| Command | Binding | Description | |--------------------------+---------+--------------------------| | egerrit-complete-comment | C-c C-c | Complete the comment | | delete-window | C-c C-k | Quit and discard comment |

#Egerrit-Conversation-Mode

The egerrit-conversation-mode is activated in the conversations buffer.

| Command | Binding | Description | |----------------------------------------+------------+---------------------------------------------------------| | 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 |

#Customization

#Variables

Name Description
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

#Multi-project support

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")))

#Views

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.

#Authentication

For authentication 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

Replace gerrit.something.net, USERNAME and PASSWORD with your own values.

#Integrate 3rd party packages

#Magit

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)

#Tab-bar

Have the 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))))

#Markdown

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)

#Page breaks

The 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)

#Road map and feature ideas

Ideas for improvements/new features of the package as well as a road map are described in the file notes.org.

#Similar packages

#Contributions

The author might try to include the package into ELPA in the future, which means that if you want to contribute you must have a copyright assignment.