dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

magit-gitignore.el (7561B)


      1 ;;; magit-gitignore.el --- intentionally untracked files  -*- lexical-binding: t -*-
      2 
      3 ;; Copyright (C) 2008-2021  The Magit Project Contributors
      4 ;;
      5 ;; You should have received a copy of the AUTHORS.md file which
      6 ;; lists all contributors.  If not, see http://magit.vc/authors.
      7 
      8 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
      9 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
     10 
     11 ;; SPDX-License-Identifier: GPL-3.0-or-later
     12 
     13 ;; Magit is free software; you can redistribute it and/or modify it
     14 ;; under the terms of the GNU General Public License as published by
     15 ;; the Free Software Foundation; either version 3, or (at your option)
     16 ;; any later version.
     17 ;;
     18 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
     19 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     20 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     21 ;; License for more details.
     22 ;;
     23 ;; You should have received a copy of the GNU General Public License
     24 ;; along with Magit.  If not, see http://www.gnu.org/licenses.
     25 
     26 ;;; Commentary:
     27 
     28 ;; This library implements gitignore commands.
     29 
     30 ;;; Code:
     31 
     32 (require 'magit)
     33 
     34 ;;; Transient
     35 
     36 ;;;###autoload (autoload 'magit-gitignore "magit-gitignore" nil t)
     37 (transient-define-prefix magit-gitignore ()
     38   "Instruct Git to ignore a file or pattern."
     39   :man-page "gitignore"
     40   ["Gitignore"
     41    ("t" "shared at toplevel (.gitignore)"
     42     magit-gitignore-in-topdir)
     43    ("s" "shared in subdirectory (path/to/.gitignore)"
     44     magit-gitignore-in-subdir)
     45    ("p" "privately (.git/info/exclude)"
     46     magit-gitignore-in-gitdir)
     47    ("g" magit-gitignore-on-system
     48     :if (lambda () (magit-get "core.excludesfile"))
     49     :description (lambda ()
     50                    (format "privately for all repositories (%s)"
     51                            (magit-get "core.excludesfile"))))]
     52   ["Skip worktree"
     53    (7 "w" "do skip worktree"     magit-skip-worktree)
     54    (7 "W" "do not skip worktree" magit-no-skip-worktree)]
     55   ["Assume unchanged"
     56    (7 "u" "do assume unchanged"     magit-assume-unchanged)
     57    (7 "U" "do not assume unchanged" magit-no-assume-unchanged)])
     58 
     59 ;;; Gitignore Commands
     60 
     61 ;;;###autoload
     62 (defun magit-gitignore-in-topdir (rule)
     63   "Add the Git ignore RULE to the top-level \".gitignore\" file.
     64 Since this file is tracked, it is shared with other clones of the
     65 repository.  Also stage the file."
     66   (interactive (list (magit-gitignore-read-pattern)))
     67   (magit-with-toplevel
     68     (magit--gitignore rule ".gitignore")
     69     (magit-run-git "add" ".gitignore")))
     70 
     71 ;;;###autoload
     72 (defun magit-gitignore-in-subdir (rule directory)
     73   "Add the Git ignore RULE to a \".gitignore\" file in DIRECTORY.
     74 Prompt the user for a directory and add the rule to the
     75 \".gitignore\" file in that directory.  Since such files are
     76 tracked, they are shared with other clones of the repository.
     77 Also stage the file."
     78   (interactive (list (magit-gitignore-read-pattern)
     79                      (read-directory-name "Limit rule to files in: ")))
     80   (magit-with-toplevel
     81     (let ((file (expand-file-name ".gitignore" directory)))
     82       (magit--gitignore rule file)
     83       (magit-run-git "add" (magit-convert-filename-for-git file)))))
     84 
     85 ;;;###autoload
     86 (defun magit-gitignore-in-gitdir (rule)
     87   "Add the Git ignore RULE to \"$GIT_DIR/info/exclude\".
     88 Rules in that file only affects this clone of the repository."
     89   (interactive (list (magit-gitignore-read-pattern)))
     90   (magit--gitignore rule (magit-git-dir "info/exclude"))
     91   (magit-refresh))
     92 
     93 ;;;###autoload
     94 (defun magit-gitignore-on-system (rule)
     95   "Add the Git ignore RULE to the file specified by `core.excludesFile'.
     96 Rules that are defined in that file affect all local repositories."
     97   (interactive (list (magit-gitignore-read-pattern)))
     98   (magit--gitignore rule
     99                     (or (magit-get "core.excludesFile")
    100                         (error "Variable `core.excludesFile' isn't set")))
    101   (magit-refresh))
    102 
    103 (defun magit--gitignore (rule file)
    104   (when-let ((directory (file-name-directory file)))
    105     (make-directory directory t))
    106   (with-temp-buffer
    107     (when (file-exists-p file)
    108       (insert-file-contents file))
    109     (goto-char (point-max))
    110     (unless (bolp)
    111       (insert "\n"))
    112     (insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" rule))
    113     (insert "\n")
    114     (write-region nil nil file)))
    115 
    116 (defun magit-gitignore-read-pattern ()
    117   (let* ((default (magit-current-file))
    118          (base (car magit-buffer-diff-files))
    119          (base (and base (file-directory-p base) base))
    120          (choices
    121           (delete-dups
    122            (--mapcat
    123             (cons (concat "/" it)
    124                   (when-let ((ext (file-name-extension it)))
    125                     (list (concat "/" (file-name-directory it) "*." ext)
    126                           (concat "*." ext))))
    127             (sort (nconc
    128                    (magit-untracked-files nil base)
    129                    ;; The untracked section of the status buffer lists
    130                    ;; directories containing only untracked files.
    131                    ;; Add those as candidates.
    132                    (-filter #'directory-name-p
    133                             (magit-list-files
    134                              "--other" "--exclude-standard" "--directory"
    135                              "--no-empty-directory" "--" base)))
    136                   #'string-lessp)))))
    137     (when default
    138       (setq default (concat "/" default))
    139       (unless (member default choices)
    140         (setq default (concat "*." (file-name-extension default)))
    141         (unless (member default choices)
    142           (setq default nil))))
    143     (magit-completing-read "File or pattern to ignore"
    144                            choices nil nil nil nil default)))
    145 
    146 ;;; Skip Worktree Commands
    147 
    148 ;;;###autoload
    149 (defun magit-skip-worktree (file)
    150   "Call \"git update-index --skip-worktree -- FILE\"."
    151   (interactive
    152    (list (magit-read-file-choice "Skip worktree for"
    153                                  (magit-with-toplevel
    154                                    (cl-set-difference
    155                                     (magit-list-files)
    156                                     (magit-skip-worktree-files))))))
    157   (magit-with-toplevel
    158     (magit-run-git "update-index" "--skip-worktree" "--" file)))
    159 
    160 ;;;###autoload
    161 (defun magit-no-skip-worktree (file)
    162   "Call \"git update-index --no-skip-worktree -- FILE\"."
    163   (interactive
    164    (list (magit-read-file-choice "Do not skip worktree for"
    165                                  (magit-with-toplevel
    166                                    (magit-skip-worktree-files)))))
    167   (magit-with-toplevel
    168     (magit-run-git "update-index" "--no-skip-worktree" "--" file)))
    169 
    170 ;;; Assume Unchanged Commands
    171 
    172 ;;;###autoload
    173 (defun magit-assume-unchanged (file)
    174   "Call \"git update-index --assume-unchanged -- FILE\"."
    175   (interactive
    176    (list (magit-read-file-choice "Assume file to be unchanged"
    177                                  (magit-with-toplevel
    178                                    (cl-set-difference
    179                                     (magit-list-files)
    180                                     (magit-assume-unchanged-files))))))
    181   (magit-with-toplevel
    182     (magit-run-git "update-index" "--assume-unchanged" "--" file)))
    183 
    184 ;;;###autoload
    185 (defun magit-no-assume-unchanged (file)
    186   "Call \"git update-index --no-assume-unchanged -- FILE\"."
    187   (interactive
    188    (list (magit-read-file-choice "Do not assume file to be unchanged"
    189                                  (magit-with-toplevel
    190                                    (magit-assume-unchanged-files)))))
    191   (magit-with-toplevel
    192     (magit-run-git "update-index" "--no-assume-unchanged" "--" file)))
    193 
    194 ;;; _
    195 (provide 'magit-gitignore)
    196 ;;; magit-gitignore.el ends here