Klimi's new dotfiles with stow.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

158 rader
6.2 KiB

4 år sedan
  1. ;;; magit-worktree.el --- worktree support -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2010-2019 The Magit Project Contributors
  3. ;;
  4. ;; You should have received a copy of the AUTHORS.md file which
  5. ;; lists all contributors. If not, see http://magit.vc/authors.
  6. ;; Author: Jonas Bernoulli <jonas@bernoul.li>
  7. ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
  8. ;; Magit is free software; you can redistribute it and/or modify it
  9. ;; under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 3, or (at your option)
  11. ;; any later version.
  12. ;;
  13. ;; Magit is distributed in the hope that it will be useful, but WITHOUT
  14. ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  15. ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  16. ;; License for more details.
  17. ;;
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with Magit. If not, see http://www.gnu.org/licenses.
  20. ;;; Commentary:
  21. ;; This library implements support for `git-worktree'.
  22. ;;; Code:
  23. (require 'magit)
  24. ;;; Options
  25. (defcustom magit-worktree-read-directory-name-function 'read-directory-name
  26. "Function used to read a directory for worktree commands.
  27. This is called with one argument, the prompt, and can be used
  28. to e.g. use a base directory other than `default-directory'.
  29. Used by `magit-worktree-checkout' and `magit-worktree-branch'."
  30. :package-version '(magit . "2.91.0")
  31. :group 'magit-commands
  32. :type 'function)
  33. ;;; Commands
  34. ;;;###autoload (autoload 'magit-worktree "magit-worktree" nil t)
  35. (define-transient-command magit-worktree ()
  36. "Act on a worktree."
  37. :man-page "git-worktree"
  38. [["Create new"
  39. ("b" "worktree" magit-worktree-checkout)
  40. ("c" "branch and worktree" magit-worktree-branch)]
  41. ["Commands"
  42. ("k" "Delete worktree" magit-worktree-delete)
  43. ("g" "Visit worktree" magit-worktree-status)]])
  44. ;;;###autoload
  45. (defun magit-worktree-checkout (path branch)
  46. "Checkout BRANCH in a new worktree at PATH."
  47. (interactive
  48. (let ((branch (magit-read-branch-or-commit "Checkout")))
  49. (list (funcall magit-worktree-read-directory-name-function
  50. (format "Checkout %s in new worktree: " branch))
  51. branch)))
  52. (magit-run-git "worktree" "add" (expand-file-name path) branch)
  53. (magit-diff-visit-directory path))
  54. ;;;###autoload
  55. (defun magit-worktree-branch (path branch start-point &optional force)
  56. "Create a new BRANCH and check it out in a new worktree at PATH."
  57. (interactive
  58. `(,(funcall magit-worktree-read-directory-name-function
  59. "Create worktree: ")
  60. ,@(magit-branch-read-args "Create and checkout branch")
  61. ,current-prefix-arg))
  62. (magit-run-git "worktree" "add" (if force "-B" "-b")
  63. branch (expand-file-name path) start-point)
  64. (magit-diff-visit-directory path))
  65. (defun magit-worktree-delete (worktree)
  66. "Delete a worktree, defaulting to the worktree at point.
  67. The primary worktree cannot be deleted."
  68. (interactive
  69. (list (magit-completing-read "Delete worktree"
  70. (cdr (magit-list-worktrees))
  71. nil t nil nil
  72. (magit-section-value-if 'worktree))))
  73. (if (file-directory-p (expand-file-name ".git" worktree))
  74. (user-error "Deleting %s would delete the shared .git directory" worktree)
  75. (let ((primary (file-name-as-directory (caar (magit-list-worktrees)))))
  76. (magit-confirm-files (if magit-delete-by-moving-to-trash 'trash 'delete)
  77. (list "worktree"))
  78. (when (file-exists-p worktree)
  79. (let ((delete-by-moving-to-trash magit-delete-by-moving-to-trash))
  80. (delete-directory worktree t magit-delete-by-moving-to-trash)))
  81. (if (file-exists-p default-directory)
  82. (magit-run-git "worktree" "prune")
  83. (let ((default-directory primary))
  84. (magit-run-git "worktree" "prune"))
  85. (when (derived-mode-p 'magit-status-mode)
  86. (kill-buffer)
  87. (magit-status-setup-buffer primary))))))
  88. (defun magit-worktree-status (worktree)
  89. "Show the status for the worktree at point.
  90. If there is no worktree at point, then read one in the
  91. minibuffer. If the worktree at point is the one whose
  92. status is already being displayed in the current buffer,
  93. then show it in Dired instead."
  94. (interactive
  95. (list (or (magit-section-value-if 'worktree)
  96. (magit-completing-read
  97. "Show status for worktree"
  98. (cl-delete (directory-file-name (magit-toplevel))
  99. (magit-list-worktrees)
  100. :test #'equal :key #'car)))))
  101. (magit-diff-visit-directory worktree))
  102. ;;; Sections
  103. (defvar magit-worktree-section-map
  104. (let ((map (make-sparse-keymap)))
  105. (define-key map [remap magit-visit-thing] 'magit-worktree-status)
  106. (define-key map [remap magit-delete-thing] 'magit-worktree-delete)
  107. map)
  108. "Keymap for `worktree' sections.")
  109. (defun magit-insert-worktrees ()
  110. "Insert sections for all worktrees.
  111. If there is only one worktree, then insert nothing."
  112. (let ((worktrees (magit-list-worktrees)))
  113. (when (> (length worktrees) 1)
  114. (magit-insert-section (worktrees)
  115. (magit-insert-heading "Worktrees:")
  116. (let* ((cols
  117. (mapcar
  118. (pcase-lambda (`(,path ,barep ,commit ,branch))
  119. (cons (cond
  120. (branch (propertize
  121. branch 'font-lock-face 'magit-branch-local))
  122. (commit (propertize (magit-rev-abbrev commit)
  123. 'font-lock-face 'magit-hash))
  124. (barep "(bare)"))
  125. path))
  126. worktrees))
  127. (align (1+ (-max (--map (string-width (car it)) cols)))))
  128. (pcase-dolist (`(,head . ,path) cols)
  129. (magit-insert-section (worktree path)
  130. (insert head)
  131. (indent-to align)
  132. (insert (let ((r (file-relative-name path))
  133. (a (abbreviate-file-name path)))
  134. (if (< (string-width r) (string-width a)) r a)))
  135. (insert ?\n))))
  136. (insert ?\n)))))
  137. ;;; _
  138. (provide 'magit-worktree)
  139. ;;; magit-worktree.el ends here