Function: git-reference
git-reference is a byte-compiled function defined in hib-social.el.
Signature
(git-reference REFERENCE &optional PROJECT)
Documentation
Display the git entity associated with REFERENCE and optional PROJECT.
REFERENCE is a string of one of the following forms:
<ref-item>
/?<project>/<ref-item>
or /<project>.
<ref-item> is one of these:
one of the words: branches, commits, or tags; the associated
items are listed;
one of the words: branch, commit, or tag followed by a '/' and
item id; the item is shown;
a commit reference given by a hex number, 55a1f0; the commit
diff is displayed;
a branch or tag reference given by an alphanumeric name,
e.g. hyper20; the files in the branch are listed.
If given, PROJECT overrides any project value in REFERENCE. If
no PROJECT value is provided, it defaults to the value of
hibtypes-git-default-project.
Source Code
;; Defined in ~/.emacs.d/elpa/hyperbole-20260414.325/hib-social.el
;; Pseudo-code for next action definition:
;; 1. If within a git repo directory, use that repo unless specified in path
;; 2. If project name is given or is default, see if assocated repo dir is in cache and use it.
;; 3. Prompt to rebuild locate db and then goto 2 if yes else quit
;; 4. Run: (cd <dir-found> && git <cmd> <item>)
;; 5. Otherwise, do nothing.
;;
;; Don't make this a defact or its arguments may be improperly expanded as pathnames.
(defun git-reference (reference &optional project)
"Display the git entity associated with REFERENCE and optional PROJECT.
REFERENCE is a string of one of the following forms:
<ref-item>
/?<project>/<ref-item>
or /<project>.
<ref-item> is one of these:
one of the words: branches, commits, or tags; the associated
items are listed;
one of the words: branch, commit, or tag followed by a '/' and
item id; the item is shown;
a commit reference given by a hex number, 55a1f0; the commit
diff is displayed;
a branch or tag reference given by an alphanumeric name,
e.g. hyper20; the files in the branch are listed.
If given, PROJECT overrides any project value in REFERENCE. If
no PROJECT value is provided, it defaults to the value of
`hibtypes-git-default-project'."
(cond ((or (null reference) (equal reference ""))
(error "(git-reference): Git commit hashtag must not be empty"))
((string-match "\\`=\\([^:#@]+\\)\\'" reference)
;; =file
(git-find-file (match-string-no-properties 1 reference)))
(t (let ((case-fold-search t)
(shell-cmd-to-format (assoc-default "git" hibtypes-social-hashtag-alist #'string-match)))
(when shell-cmd-to-format
(cond ((string-match "\\`\\(=\\)\\|\\(branch\\|commit\\|tag\\)/" reference)
;; [branch | commit | tag]/ref-item
nil)
((string-match "\\`/?\\([^/#@]+\\)/\\([0-9a-f]+\\)\\'" reference)
;; /?project/hashtag
(setq project (or project (match-string-no-properties 1 reference))
reference (match-string-no-properties 2 reference)))
((string-match "\\`/\\([^/#@]+\\)\\'" reference)
;; /project
(setq project (or project (match-string-no-properties 1 reference))
reference nil))
((string-match "/.*/" reference)
;; Invalid user/project/hashtag
(error "(git-reference): Username or path not allowed, only <project>/<commit hashtag>")))
(let ((cmd)
(ref-type)
;; `project' now may be a project directory or a project name.
;; If a project name:
;; If reference is within a git project, use its project directory.
;; Otherwise, look up the project in Hyperbole's local git repo directory cache;
;; the user is prompted to have it built when necessary.
(project-dir (or (and project (file-readable-p project) (file-directory-p project) project)
(locate-dominating-file default-directory ".git"))))
(unless (or (stringp project) (= (aref reference 0) ?=))
(unless (setq project (cond (project-dir (file-name-nondirectory (directory-file-name project-dir)))
((stringp hibtypes-git-default-project)
hibtypes-git-default-project)))
(error "(git-reference): Set `hibtypes-git-default-project' to a default project name")))
(unless project-dir
(setq project-dir (and project (hibtypes-git-project-directory project))))
(when reference
(cond ((member reference '("branches" "commits" "tags"))
;; All branches, commits or commit tags reference
(setq ref-type reference
reference ""))
((string-match "\\`=?\\(commit\\)/" reference)
;; Specific reference preceded by keyword commit.
(setq ref-type "commit"
reference (substring reference (match-end 0))))
((string-match "\\`=?[0-9a-f]+\\'" reference)
;; Commit reference
(setq ref-type "commit"))
((string-match "\\`\\(=?\\(branch\\|tag\\)/\\)\\|=" reference)
;; Specific branch or commit tag reference
(setq ref-type "tree"
reference (substring reference (match-end 0)))
;; reference now might be branch-name:subpath or just branch-name.
;; (subpath by itself was handled by git-find-file up above).
;; If reference contains subpath, expand it with hibtypes-git-find.
(let (branch-name
file
path)
(if (string-match ":" reference)
(setq branch-name (substring reference 0 (match-beginning 0))
file (substring reference (match-end 0))
path (hibtypes-git-find file)
reference (concat branch-name ":" file))
(setq path default-directory))
(setq project-dir (or project-dir (and path (locate-dominating-file path ".git")))
project (or project (and project-dir (file-name-nondirectory project-dir))
hibtypes-git-default-project))))
(t
(setq ref-type "tree"))))
(when (or (null project-dir) (equal project-dir ""))
(if (and project
;; Maybe the Hyperbole git project cache is
;; out-of-date and needs to be rebuilt or added
;; to. Prompt user and if rebuilt or added to,
;; continue.
(hibtypes-git-build-or-add-to-repos-cache project))
(setq project-dir (and project (hibtypes-git-project-directory project)))
(error "(git-reference): No git directory found for project `%s'" project)))
(when (equal project-dir "") (setq project-dir nil))
;; Eliminate ~ that Windows shell can't handle in shell paths
(when project-dir (setq project-dir (expand-file-name project-dir)))
(cond ((and project-dir (file-readable-p project-dir) (file-directory-p project-dir))
(if reference
(if (equal ref-type "commits")
(let ((default-directory project-dir))
(vc-print-root-log))
;; Display commit diffs in a help buffer
;; Ensure these do not invoke with-output-to-temp-buffer a second time.
(let ((temp-buffer-show-hook)
(temp-buffer-show-function))
(setq cmd
(pcase ref-type
("branches" (format shell-cmd-to-format project-dir "branch -la" ""))
("commits" (format shell-cmd-to-format project-dir "log --abbrev-commit --pretty=oneline" ""))
("tags" (format shell-cmd-to-format project-dir "tag -l" ""))
(_ (format shell-cmd-to-format project-dir "show" reference))))
(with-help-window (format "*git%s%s %s%s%s*"
(if (equal project "") "" " ")
project ref-type
(if (equal reference "") "" " ")
(substring reference nil (min 9 (length reference))))
(princ (format "Command: %s\n\n" cmd))
(princ (shell-command-to-string cmd)))))
;; Project-only reference, run dired on the project home directory
(if (and hibtypes-git-use-magit-flag (fboundp #'magit-status-setup-buffer))
(hpath:display-buffer (save-window-excursion
(magit-status-setup-buffer
(file-name-as-directory project-dir))))
(hpath:display-buffer (dired-noselect
(file-name-as-directory project-dir))))))
(t (if project-dir
(error "(git-reference): git project `%s' directory is unreadable or invalid: \"%s\""
project project-dir)
(error "(git-reference): No git project found for `%s'" project))))))))))