Repository: sloria/sphinx-issues

Issue:
Support linking to commits
Example:

```rst
:commit:`123abc456def`
```

Comments:

Patch:
diff --git a/README.rst b/README.rst
index 020b6bb..4e36f8b 100644
--- a/README.rst
+++ b/README.rst
@@ -38,6 +38,7 @@ Add ``sphinx_issues`` to ``extensions`` in your ``conf.py``. If your project is
     # equivalent to
     issues_uri = "https://github.com/sloria/marshmallow/issues/{issue}"
     issues_pr_uri = "https://github.com/sloria/marshmallow/pull/{pr}"
+    issues_commit_uri = "https://github.com/sloria/marshmallow/commit/{commit}"
 
 Usage
 *****
@@ -65,6 +66,13 @@ You can also use explicit names if you want to use a different name than the git
 
     This change is due to :user:`Andreas Mueller <amueller>`.
 
+
+Use the ``:commit:`` role to link to commits.
+
+.. code-block:: rst
+
+    Fixed in :commit:`6bb9124d5e9dbb2f7b52864c3d8af7feb1b69403`.
+
 Use the ``:cve:`` role to link to CVEs on https://cve.mitre.org.
 
 .. code-block:: rst
@@ -88,6 +96,7 @@ Changelog
 1.2.0 (unreleased)
 ------------------
 
+- Add ``:commit:`` role for linking to commits.
 - Test against Python 3.7.
 
 1.1.0 (2018-09-18)
diff --git a/sphinx_issues.py b/sphinx_issues.py
index 6fe22c8..a665425 100644
--- a/sphinx_issues.py
+++ b/sphinx_issues.py
@@ -62,10 +62,17 @@ def cve_role(name, rawtext, text, lineno, inliner, options=None, content=None):
 
 
 class IssueRole(object):
-    def __init__(self, uri_config_option, format_kwarg, github_uri_template):
+    def __init__(
+        self, uri_config_option, format_kwarg, github_uri_template, format_text=None
+    ):
         self.uri_config_option = uri_config_option
         self.format_kwarg = format_kwarg
         self.github_uri_template = github_uri_template
+        self.format_text = format_text or self.default_format_text
+
+    @staticmethod
+    def default_format_text(issue_no):
+        return "#{0}".format(issue_no)
 
     def make_node(self, issue_no, config, options=None):
         options = options or {}
@@ -82,7 +89,7 @@ class IssueRole(object):
                     "Neither {} nor issues_github_path "
                     "is set".format(self.uri_config_option)
                 )
-            issue_text = "#{0}".format(issue_no)
+            issue_text = self.format_text(issue_no)
             link = nodes.reference(text=issue_text, refuri=ref, **options)
         else:
             link = None
@@ -130,6 +137,23 @@ pr_role = IssueRole(
 )
 
 
+def format_commit_text(sha):
+    return sha[:7]
+
+
+"""Sphinx role for linking to a commit. Must have
+`issues_pr_uri` or `issues_github_path` configured in ``conf.py``.
+Examples: ::
+    :commit:`123abc456def`
+"""
+commit_role = IssueRole(
+    uri_config_option="issues_commit_uri",
+    format_kwarg="commit",
+    github_uri_template="https://github.com/{issues_github_path}/commit/{n}",
+    format_text=format_commit_text,
+)
+
+
 def setup(app):
     # Format template for issues URI
     # e.g. 'https://github.com/sloria/marshmallow/issues/{issue}
@@ -137,6 +161,9 @@ def setup(app):
     # Format template for PR URI
     # e.g. 'https://github.com/sloria/marshmallow/pull/{issue}
     app.add_config_value("issues_pr_uri", default=None, rebuild="html")
+    # Format template for commit URI
+    # e.g. 'https://github.com/sloria/marshmallow/commits/{commit}
+    app.add_config_value("issues_commit_uri", default=None, rebuild="html")
     # Shortcut for Github, e.g. 'sloria/marshmallow'
     app.add_config_value("issues_github_path", default=None, rebuild="html")
     # Format template for user profile URI
@@ -145,6 +172,7 @@ def setup(app):
     app.add_role("issue", issue_role)
     app.add_role("pr", pr_role)
     app.add_role("user", user_role)
+    app.add_role("commit", commit_role)
     app.add_role("cve", cve_role)
     return {
         "version": __version__,


Test patch:
diff --git a/test_sphinx_issues.py b/test_sphinx_issues.py
index 3947870..46e4519 100644
--- a/test_sphinx_issues.py
+++ b/test_sphinx_issues.py
@@ -13,6 +13,7 @@ from sphinx_issues import (
     user_role,
     pr_role,
     cve_role,
+    commit_role,
     setup as issues_setup,
 )
 
@@ -26,6 +27,7 @@ import pytest
         {
             "issues_uri": "https://github.com/marshmallow-code/marshmallow/issues/{issue}",
             "issues_pr_uri": "https://github.com/marshmallow-code/marshmallow/pull/{pr}",
+            "issues_commit_uri": "https://github.com/marshmallow-code/marshmallow/commit/{commit}",
         },
     ]
 )
@@ -108,3 +110,12 @@ def test_cve_role(inliner):
     assert link.astext() == "CVE-2018-17175"
     issue_url = "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-17175"
     assert link.attributes["refuri"] == issue_url
+
+
+def test_commit_role(inliner):
+    sha = "123abc456def"
+    result = commit_role(name=None, rawtext="", text=sha, lineno=None, inliner=inliner)
+    link = result[0][0]
+    assert link.astext() == sha[:7]
+    url = "https://github.com/marshmallow-code/marshmallow/commit/{}".format(sha)
+    assert link.attributes["refuri"] == url