diff options
| author | Jonas Bernoulli <jonas@bernoul.li> | 2026-03-30 22:31:57 +0200 |
|---|---|---|
| committer | Jonas Bernoulli <jonas@bernoul.li> | 2026-03-30 22:31:57 +0200 |
| commit | bef6bdc62fc0ffba77dd6a91baaf53bffcbcd5ad (patch) | |
| tree | 81da8cf675323746362a8a720e9d8651221635b4 | |
| parent | 315d85c765afbce10b08c5c9164da64bc789197a (diff) | |
Support visiting anonymous blobs
I.e., support visiting a blob via its blob oid without
knowing a commit and tree path in which it can be found.
| -rw-r--r-- | lisp/magit-files.el | 45 | ||||
| -rw-r--r-- | lisp/magit-git.el | 12 | ||||
| -rw-r--r-- | lisp/magit-mode.el | 1 |
3 files changed, 37 insertions, 21 deletions
diff --git a/lisp/magit-files.el b/lisp/magit-files.el index 1a2ee60..f98edee 100644 --- a/lisp/magit-files.el +++ b/lisp/magit-files.el @@ -43,6 +43,7 @@ (defvar magit-find-blob-hook (list #'magit-blob-mode)) +(defvar-local magit-buffer-blob-oid--init nil) (defvar-local magit-buffer--volatile nil) (put 'magit-buffer--volatile 'permanent-local t) @@ -90,7 +91,8 @@ the line and column corresponding to that location." (defun magit-find-file-noselect (rev file &optional no-restore-position volatile) "Read FILE from REV into a buffer and return the buffer. -REV is a revision or one of \"{worktree}\" or \"{index}\"." +REV is a revision or one of \"{worktree}\" or \"{index}\". +Non-interactively REV can also be a blob object." (let* ((rev (pcase rev ('nil "{worktree}") ((and "{index}" @@ -117,7 +119,9 @@ REV is a revision or one of \"{worktree}\" or \"{index}\"." (error "%s is not inside Git repository %s" file topdir)) (with-current-buffer (magit--get-blob-buffer rev file-relative volatile) - (setq magit-buffer-revision rev) + (if (magit-blob-p rev) + (setq magit-buffer-blob-oid--init (magit-rev-parse rev)) + (setq magit-buffer-revision rev)) (setq magit-buffer-file-name file) (setq default-directory (if (file-exists-p defdir) defdir topdir)) @@ -132,29 +136,33 @@ REV is a revision or one of \"{worktree}\" or \"{index}\"." (apply #'magit-find-file--restore-position pos)))) buffer)) -(defun magit--get-blob-buffer (rev file &optional volatile) - ;; REV is assumed to be abbreviated and FILE to be relative. +(defun magit--get-blob-buffer (obj file &optional volatile) + ;; If OBJ is a commit, is assummed to be abbreviated. + ;; FILE is assumed to be relative to the top-level. (cond-let - ([buf (magit--find-buffer 'magit-buffer-revision rev - 'magit-buffer-file-name file)] + ([buf (if (magit-blob-p obj) + (magit--find-buffer 'magit-buffer-blob-oid (magit-rev-parse obj) + 'magit-buffer-file-name file) + (magit--find-buffer 'magit-buffer-revision obj + 'magit-buffer-file-name file))] (with-current-buffer buf (when (and (not volatile) magit-buffer--volatile) (setq magit-buffer--volatile nil) - (rename-buffer (magit--blob-buffer-name rev file)) + (rename-buffer (magit--blob-buffer-name obj file)) (magit--blob-cache-remove buf))) buf) - ([buf (get-buffer-create (magit--blob-buffer-name rev file volatile))] + ([buf (get-buffer-create (magit--blob-buffer-name obj file volatile))] (with-current-buffer buf (setq magit-buffer--volatile volatile) (magit--blob-cache-put buf)) (buffer-enable-undo buf) buf))) -(defun magit--blob-buffer-name (rev file &optional volatile) +(defun magit--blob-buffer-name (obj file &optional volatile) (format "%s%s.~%s~" (if volatile " " "") - file - (subst-char-in-string ?/ ?_ rev))) + (or file (and (magit-blob-p obj) "{blob}")) + (subst-char-in-string ?/ ?_ obj))) (defun magit--revert-blob-buffer (_ignore-auto _noconfirm) (let ((pos (magit-find-file--position))) @@ -163,10 +171,15 @@ REV is a revision or one of \"{worktree}\" or \"{index}\"." (defun magit--refresh-blob-buffer (&optional force) (let ((old-blob-oid magit-buffer-blob-oid)) - (setq magit-buffer-revision-oid - (magit-commit-oid magit-buffer-revision t)) - (setq magit-buffer-blob-oid - (magit-blob-oid magit-buffer-revision magit-buffer-file-name)) + (cond + (magit-buffer-revision + (setq magit-buffer-revision-oid + (magit-commit-oid magit-buffer-revision t)) + (setq magit-buffer-blob-oid + (magit-blob-oid magit-buffer-revision magit-buffer-file-name))) + (magit-buffer-blob-oid--init + (setq magit-buffer-blob-oid magit-buffer-blob-oid--init) + (setq magit-buffer-blob-oid--init nil))) (when (or force (not (equal old-blob-oid magit-buffer-blob-oid))) (let ((inhibit-read-only t)) (erase-buffer) @@ -308,7 +321,7 @@ Age is tracked in seconds. If nil, only use `magit--blob-cache-limit'.") (define-advice lsp (:around (fn &rest args) magit-find-file) "Do nothing when visiting blob using `magit-find-file' and similar. See also https://github.com/doomemacs/doomemacs/pull/6309." - (unless magit-buffer-revision + (unless magit-buffer-blob-oid (apply fn args))) ;;; Update Index diff --git a/lisp/magit-git.el b/lisp/magit-git.el index 7a52a52..d8d9d83 100644 --- a/lisp/magit-git.el +++ b/lisp/magit-git.el @@ -1349,12 +1349,14 @@ Sorted from longest to shortest CYGWIN name." (magit-git-lines "ls-files" "--stage" "--" (magit-convert-filename-for-git file)))) -(defun magit--insert-blob-contents (rev file) +(defun magit--insert-blob-contents (obj file) (let ((coding-system-for-read (or coding-system-for-read 'undecided))) - (magit-git-insert "cat-file" "-p" - (if (equal rev "{index}") - (concat ":" file) - (concat rev ":" file))) + (if (magit-blob-p obj) + (magit-git-insert "cat-file" "blob" obj) + (magit-git-insert "cat-file" "-p" + (if (equal obj "{index}") + (concat ":" file) + (concat obj ":" file)))) (setq buffer-file-coding-system last-coding-system-used) nil)) diff --git a/lisp/magit-mode.el b/lisp/magit-mode.el index fa82632..00ee776 100644 --- a/lisp/magit-mode.el +++ b/lisp/magit-mode.el @@ -625,6 +625,7 @@ In an indirect buffer get the value for its base buffer." (defun magit-buffer-revision () "Return `magit-buffer-revision' or if that is nil \"{worktree}\". If not visiting a blob or file, or the file isn't being tracked, +return nil. If visiting a blob but `magit-buffer-revision' is nil, return nil." (or magit-buffer-revision (and buffer-file-name |
