Skip to content

nvimtor/git-commit-jira.el

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 

Repository files navigation

git-commit-jira.el

Description

An Emacs package to automatically add JIRA tickets in git-commit buffers.

Code

Some licensing bullshit:

;;; git-commit-jira.el --- Automatically insert JIRA tickets in git commits -*- lexical-binding: t -*-

;; Copyright (C) 2023  Vitor Leal

;; Author: Vitor Leal <[email protected]>
;; URL: https://github.com/nvimtor/git-commit-jira.el
;; Version: 0.1.0
;; Package-Requires: ((emacs "25.1"))

;; This file is not part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:
;;
;; The git-commit-jira package automatically inserts JIRA ticket identifiers
;; into git commit messages based on the current branch name.
;;

;;; Code:

Require dependencies. eval-when-compile is used to load a library only during the compilation of this code, rather than at runtime.

(eval-when-compile
  (require 'vc-git))

Originally, this was done using the s library’s s-split-words, but as it is a simple function, we will just define our own:

(defun git-commit-jira-split-words (string)
    "Split STRING into a list of words, using non-word characters as delimiters."
    (split-string string "[^[:word:]]+"))

Let’s start by creating a customization group.

(defgroup git-commit-jira nil
  "Customization group for the git-commit-jira package."
  :group 'tools
  :prefix "git-commit-jira-")

Define a Regular expression that matches JIRA tickets. We need one to match it in brackets (for commit messages), and one without (for branch names).

(defcustom git-commit-jira-ticket-regex-brackets "\\[[A-Za-z]+-[0-9]+\\]"
  "Regex pattern used to match JIRA ticket identifiers that are wrapped in brackets, e.g., [ABC-123]."
  :type 'regexp
  :group 'git-commit-jira)

(defcustom git-commit-jira-ticket-regex-nobrackets "\\([A-Za-z]+-[0-9]+\\)"
  "Regex pattern used to match JIRA ticket identifiers that are not wrapped in brackets, e.g., ABC-123."
  :type 'regexp
  :group 'git-commit-jira)

This block defines a function to retrieve the current branch name, using vc.

(defun git-commit-jira-vc-current-branch ()
  "Get the current git branch using VC."
  (car (vc-git-branches)))

And this going to be the default function.

(defcustom git-commit-jira-get-current-branch-function #'git-commit-jira-vc-current-branch
  "Function to retrieve the current branch name."
  :type 'function
  :group 'git-commit-jira)

This is the main function. It inserts the JIRA ticket identifier. It is pretty much the same as the one from gopar’s video, but it checks if the current commit message already contains a JIRA ticket. This is especially useful for commit amends.

  (defun git-commit-jira-insert-ticket ()
"Insert a JIRA ticket identifier from the branch name into the commit message if not already present."
    (let ((branch-name (funcall git-commit-jira-get-current-branch-function))
          (commit-message (buffer-string)))
      (unless (string-match git-commit-jira-ticket-regex-brackets commit-message)
        (when (string-match git-commit-jira-ticket-regex-nobrackets branch-name)
          (let ((words (git-commit-jira-split-words branch-name)))
            (insert (format "[%s-%s] " (car words) (car (cdr words)))))))))

The minor mode.

(define-minor-mode git-commit-jira-mode
  "Minor mode to automatically insert JIRA ticket in git commit messages."
  :global t
  :group 'git-commit-jira
  (if git-commit-jira-mode
      (add-hook 'git-commit-setup-hook #'git-commit-jira-insert-ticket)
    (remove-hook 'git-commit-setup-hook #'git-commit-jira-insert-ticket)))

Let’s extend what we currently have by allowing users to optionally control the case of the ticket.

  (defcustom git-commit-jira-uppercase-ticket t
    "If non-nil, the JIRA ticket identifier will be converted to uppercase."
    :type 'boolean
    :group 'git-commit-jira)

(defun git-commit-jira-uppercase-advice (func &rest args)
  "Advice to conditionally uppercase the inserted JIRA ticket."
  (let ((start (point)))
    (apply func args)
    (when git-commit-jira-uppercase-ticket
      (save-excursion
        (goto-char start)
        (while (re-search-forward git-commit-jira-ticket-regex-brackets nil t)
          (replace-match (upcase (match-string 0)) t))))))

  (advice-add 'git-commit-jira-insert-ticket :around #'git-commit-jira-uppercase-advice)

Provide the package.

(provide 'git-commit-jira)

;;; git-commit-jira.el ends here

Todos

Write tests

Figure out if there is a built-in way to get the current branch with vc

Maybe this can remove dependency from =magit=, although =git-commit= has been fused into =magit= anyway.
(car (vc-git-branches))

According to this StackOverflow post, vc-git-branches will always return the current branch as the first element.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published