- (cond ((file-directory-p (expand-file-name ".git" dir))
- (message "Waiting for git...")
- (with-temp-buffer
- (let ((default-directory (file-name-as-directory dir)))
- (and (eq 0
- (condition-case nil
- (call-process "git" nil '(t nil) nil "rev-parse"
- "HEAD")
- (error nil)))
- (not (zerop (buffer-size)))
- (replace-regexp-in-string "\n" "" (buffer-string))))))))
+ (let* ((base-dir (expand-file-name ".git" dir))
+ (in-main-worktree (file-directory-p base-dir))
+ (in-linked-worktree nil)
+ sub-dir)
+ ;; If the sources are in a linked worktree, .git is a file that points to
+ ;; the location of the main worktree and the repo's administrative files.
+ (when (and (not in-main-worktree)
+ (file-regular-p base-dir)
+ (file-readable-p base-dir))
+ (with-temp-buffer
+ (insert-file-contents base-dir)
+ (when (looking-at "gitdir: \\(.*\.git\\)\\(.*\\)$")
+ (setq base-dir (match-string 1)
+ sub-dir (concat base-dir (match-string 2))
+ in-linked-worktree t))))
+ ;; We've found a worktree, either main or linked.
+ (when (or in-main-worktree in-linked-worktree)
+ (if external
+ (emacs-repository-version-git dir)
+ (or (if in-linked-worktree
+ (emacs-repository--version-git-1
+ (expand-file-name "HEAD" sub-dir) base-dir)
+ (let ((files '("HEAD" "refs/heads/master"))
+ file rev)
+ (while (and (not rev)
+ (setq file (car files)))
+ (setq file (expand-file-name file base-dir)
+ files (cdr files)
+ rev (emacs-repository--version-git-1 file base-dir)))
+ rev))
+ ;; AFAICS this doesn't work during dumping (bug#20799).
+ (emacs-repository-version-git dir))))))