mirror of https://github.com/Chizi123/.emacs.d.git

Chizi123
2018-11-18 8f6f2705a38e2515b6c57fda12c5be29fb9a798f
commit | author | age
5cb5f7 1 ;;; magit-patch.el --- creating and applying patches  -*- lexical-binding: t -*-
C 2
3 ;; Copyright (C) 2008-2018  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 ;; Magit is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; any later version.
15 ;;
16 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
17 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19 ;; License for more details.
20 ;;
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with Magit.  If not, see http://www.gnu.org/licenses.
23
24 ;;; Commentary:
25
26 ;; This library implements patch commands.
27
28 ;;; Code:
29
30 (eval-when-compile
31   (require 'subr-x))
32
33 (require 'magit)
34
35 ;;; Options
36
37 (defcustom magit-patch-save-arguments '(exclude "--stat")
38   "Arguments used by `magit-patch-save-arguments' (which see)"
39   :package-version '(magit . "2.12.0")
40   :group 'magit-diff
41   :type '(choice (const :tag "use buffer arguments" buffer)
42                  (cons :tag "use buffer arguments except"
43                        (const :format "" exclude)
44                        (repeat :format "%v%i\n"
45                                (string :tag "Argument")))
46                  (repeat :tag "use constant arguments"
47                          (string :tag "Argument"))))
48
49 ;;; Commands
50
51 ;;;###autoload (autoload 'magit-patch-popup "magit-patch" nil t)
52 (magit-define-popup magit-patch-popup
53   "Popup console for patch commands."
54   :man-page "git-format-patch"
55   :switches '("Switches for formatting patches"
56               (?l "Add cover letter" "--cover-letter"))
57   :options  '("Options for formatting patches"
58               (?f "From"             "--from=")
59               (?t "To"               "--to=")
60               (?c "CC"               "--cc=")
61               (?r "In reply to"      "--in-reply-to=")
62               (?P "Subject Prefix"   "--subject-prefix=")
63               (?v "Reroll count"     "--reroll-count=")
64               (?s "Thread style"     "--thread=")
65               (?U "Context lines"    "-U")
66               (?M "Detect renames"   "-M")
67               (?C "Detect copies"    "-C")
68               (?A "Diff algorithm"   "--diff-algorithm="
69                   magit-diff-select-algorithm)
70               (?o "Output directory" "--output-directory=")
71               (?F "Limit to files"   "-- " magit-read-files))
72   :actions  '((?p "Format patches"   magit-format-patch)
73               (?r "Request pull"     magit-request-pull))
74   :default-action 'magit-format-patch)
75
76 ;;;###autoload
77 (defun magit-format-patch (range args files)
78   "Create patches for the commits in RANGE.
79 When a single commit is given for RANGE, create a patch for the
80 changes introduced by that commit (unlike 'git format-patch'
81 which creates patches for all commits that are reachable from
82 `HEAD' but not from the specified commit)."
83   (interactive
84    (cons (if-let ((revs (magit-region-values 'commit t)))
85              (concat (car (last revs)) "^.." (car revs))
86            (let ((range (magit-read-range-or-commit
87                          "Format range or commit")))
88              (if (string-match-p "\\.\\." range)
89                  range
90                (format "%s~..%s" range range))))
91          (magit-popup-export-file-args (magit-patch-arguments))))
92   (magit-run-git "format-patch" range args "--" files)
93   (when (member "--cover-letter" args)
94     (find-file
95      (expand-file-name
96       "0000-cover-letter.patch"
97       (let ((topdir (magit-toplevel)))
98         (or (--some (and (string-match "--output-directory=\\(.+\\)" it)
99                          (expand-file-name (match-string 1 it) topdir))
100                     args)
101             topdir))))))
102
103 ;;;###autoload
104 (defun magit-request-pull (url start end)
105   "Request upstream to pull from you public repository.
106
107 URL is the url of your publically accessible repository.
108 START is a commit that already is in the upstream repository.
109 END is the last commit, usually a branch name, which upstream
110 is asked to pull.  START has to be reachable from that commit."
111   (interactive
112    (list (magit-get "remote" (magit-read-remote "Remote") "url")
113          (magit-read-branch-or-commit "Start" (magit-get-upstream-branch))
114          (magit-read-branch-or-commit "End")))
115   (let ((dir default-directory))
116     ;; mu4e changes default-directory
117     (compose-mail)
118     (setq default-directory dir))
119   (message-goto-body)
120   (magit-git-insert "request-pull" start url end)
121   (set-buffer-modified-p nil))
122
123 ;;;###autoload (autoload 'magit-patch-apply-popup "magit-patch" nil t)
124 (magit-define-popup magit-patch-apply-popup
125   "Popup console for applying a patch file."
126   :man-page "git-apply"
127   :switches '((?i "Also apply to index"     "--index")
128               (?c "Only apply to index"     "--cached")
129               (?3 "Fall back on 3way merge" "--3way"))
130   :actions  '((?a "Apply patch" magit-patch-apply))
131   :default-action 'magit-patch-apply)
132
133 ;;;###autoload
134 (defun magit-patch-apply (file &rest args)
135   "Apply the patch file FILE."
136   (interactive (list (expand-file-name
137                       (read-file-name "Apply patch: "
138                                       default-directory nil nil
139                                       (--when-let (magit-file-at-point)
140                                         (file-relative-name it))))
141                      (magit-patch-apply-arguments)))
142   (magit-run-git "apply" args "--" (magit-convert-filename-for-git file)))
143
144 ;;;###autoload
145 (defun magit-patch-save (file &optional arg)
146   "Write current diff into patch FILE.
147
148 What arguments are used to create the patch depends on the value
149 of `magit-patch-save-arguments' and whether a prefix argument is
150 used.
151
152 If the value is the symbol `buffer', then use the same arguments
153 as the buffer.  With a prefix argument use no arguments.
154
155 If the value is a list beginning with the symbol `exclude', then
156 use the same arguments as the buffer except for those matched by
157 entries in the cdr of the list.  The comparison is done using
158 `string-prefix-p'.  With a prefix argument use the same arguments
159 as the buffer.
160
161 If the value is a list of strings (including the empty list),
162 then use those arguments.  With a prefix argument use the same
163 arguments as the buffer.
164
165 Of course the arguments that are required to actually show the
166 same differences as those shown in the buffer are always used."
167   (interactive (list (read-file-name "Write patch file: " default-directory)
168                      current-prefix-arg))
169   (unless (derived-mode-p 'magit-diff-mode)
170     (user-error "Only diff buffers can be saved as patches"))
171   (pcase-let ((`(,rev ,const ,args ,files) magit-refresh-args))
172     (when (derived-mode-p 'magit-revision-mode)
173       (setq rev (format "%s~..%s" rev rev)))
174     (cond ((eq magit-patch-save-arguments 'buffer)
175            (when arg
176              (setq args nil)))
177           ((eq (car-safe magit-patch-save-arguments) 'exclude)
178            (unless arg
179              (setq args (-difference args (cdr magit-patch-save-arguments)))))
180           ((not arg)
181            (setq args magit-patch-save-arguments)))
182     (with-temp-file file
183       (magit-git-insert "diff" rev "-p" const args "--" files)))
184   (magit-refresh))
185
186 ;;; _
187 (provide 'magit-patch)
188 ;;; magit-patch.el ends here