applied whitespace-cleanup
close issue 304
Yann Hodique
12 years ago
136 | 136 | :type '(choice (const :tag "Never" nil) |
137 | 137 | (const :tag "Ask" t) |
138 | 138 | (const :tag "Refuse" refuse) |
139 | (const :tag "Always" dontask))) | |
139 | (const :tag "Always" dontask))) | |
140 | 140 | |
141 | 141 | (defcustom magit-save-some-buffers t |
142 | 142 | "Non-nil means that \\[magit-status] will save modified buffers before running. |
144 | 144 | save all modified buffers without asking." |
145 | 145 | :group 'magit |
146 | 146 | :type '(choice (const :tag "Never" nil) |
147 | (const :tag "Ask" t) | |
148 | (const :tag "Save without asking" dontask))) | |
147 | (const :tag "Ask" t) | |
148 | (const :tag "Save without asking" dontask))) | |
149 | 149 | |
150 | 150 | (defcustom magit-save-some-buffers-predicate |
151 | 151 | 'magit-save-buffers-predicate-tree-only |
178 | 178 | after a confirmation." |
179 | 179 | :group 'magit |
180 | 180 | :type '(choice (const :tag "No" nil) |
181 | (const :tag "Always" t) | |
182 | (const :tag "Ask" ask) | |
183 | (const :tag "Ask to stage everything" ask-stage))) | |
181 | (const :tag "Always" t) | |
182 | (const :tag "Ask" ask) | |
183 | (const :tag "Ask to stage everything" ask-stage))) | |
184 | 184 | |
185 | 185 | (defcustom magit-commit-signoff nil |
186 | 186 | "Add the \"Signed-off-by:\" line when committing." |
209 | 209 | "Popup the process buffer if a command takes longer than this many seconds." |
210 | 210 | :group 'magit |
211 | 211 | :type '(choice (const :tag "Never" -1) |
212 | (const :tag "Immediately" 0) | |
213 | (integer :tag "After this many seconds"))) | |
212 | (const :tag "Immediately" 0) | |
213 | (integer :tag "After this many seconds"))) | |
214 | 214 | |
215 | 215 | (defcustom magit-revert-item-confirm t |
216 | 216 | "Require acknowledgment before reverting an item." |
251 | 251 | :group 'magit |
252 | 252 | :type '(radio (function-item magit-iswitchb-completing-read) |
253 | 253 | (function-item magit-ido-completing-read) |
254 | (function-item magit-builtin-completing-read) | |
255 | (function :tag "Other"))) | |
254 | (function-item magit-builtin-completing-read) | |
255 | (function :tag "Other"))) | |
256 | 256 | |
257 | 257 | (defcustom magit-create-branch-behaviour 'at-head |
258 | 258 | "Where magit will create a new branch if not supplied a branchname or ref. |
270 | 270 | The function is given one argument, the status buffer." |
271 | 271 | :group 'magit |
272 | 272 | :type '(radio (function-item switch-to-buffer) |
273 | (function-item pop-to-buffer) | |
274 | (function :tag "Other"))) | |
273 | (function-item pop-to-buffer) | |
274 | (function :tag "Other"))) | |
275 | 275 | |
276 | 276 | (defcustom magit-rewrite-inclusive t |
277 | 277 | "Whether magit includes the selected base commit in a rewrite operation. |
645 | 645 | (defun magit-buffer-switch (buf) |
646 | 646 | (if (string-match "magit" (buffer-name)) |
647 | 647 | (switch-to-buffer buf) |
648 | (pop-to-buffer buf))) | |
648 | (pop-to-buffer buf))) | |
649 | 649 | |
650 | 650 | ;;; Macros |
651 | 651 | |
710 | 710 | "Same as `string-match' except this function does not |
711 | 711 | change the match data." |
712 | 712 | (let ((inhibit-changing-match-data t)) |
713 | (string-match regexp string start)))) | |
713 | (string-match regexp string start)))) | |
714 | 714 | |
715 | 715 | (if (fboundp 'with-silent-modifications) |
716 | 716 | (defalias 'magit-with-silent-modifications 'with-silent-modifications) |
748 | 748 | (magit-refresh-all)) |
749 | 749 | |
750 | 750 | (defun magit-iswitchb-completing-read (prompt choices &optional predicate require-match |
751 | initial-input hist def) | |
751 | initial-input hist def) | |
752 | 752 | "iswitchb-based completing-read almost-replacement." |
753 | 753 | (require 'iswitchb) |
754 | 754 | (let ((iswitchb-make-buflist-hook |
771 | 771 | selected))) |
772 | 772 | |
773 | 773 | (defun magit-builtin-completing-read (prompt choices &optional predicate require-match |
774 | initial-input hist def) | |
774 | initial-input hist def) | |
775 | 775 | "Magit wrapper for standard `completing-read' function." |
776 | 776 | (completing-read (if (and def (> (length prompt) 2) |
777 | 777 | (string-equal ": " (substring prompt -2))) |
780 | 780 | choices predicate require-match initial-input hist def)) |
781 | 781 | |
782 | 782 | (defun magit-completing-read (prompt choices &optional predicate require-match |
783 | initial-input hist def) | |
783 | initial-input hist def) | |
784 | 784 | (funcall magit-completing-read-function prompt choices predicate require-match |
785 | 785 | initial-input hist def)) |
786 | 786 | |
800 | 800 | (if (string= str "") |
801 | 801 | nil |
802 | 802 | (if (equal (elt str (- (length str) 1)) ?\n) |
803 | (substring str 0 (- (length str) 1)) | |
803 | (substring str 0 (- (length str) 1)) | |
804 | 804 | str))) |
805 | 805 | |
806 | 806 | (defun magit-split-lines (str) |
808 | 808 | nil |
809 | 809 | (let ((lines (nreverse (split-string str "\n")))) |
810 | 810 | (if (string= (car lines) "") |
811 | (setq lines (cdr lines))) | |
811 | (setq lines (cdr lines))) | |
812 | 812 | (nreverse lines)))) |
813 | 813 | |
814 | 814 | (defun magit-git-insert (args) |
837 | 837 | |
838 | 838 | (defun magit-git-exit-code (&rest args) |
839 | 839 | (apply #'process-file magit-git-executable nil nil nil |
840 | (append magit-git-standard-options args))) | |
840 | (append magit-git-standard-options args))) | |
841 | 841 | |
842 | 842 | (defun magit-file-lines (file) |
843 | 843 | (when (file-exists-p file) |
844 | 844 | (with-temp-buffer |
845 | 845 | (insert-file-contents file) |
846 | 846 | (let ((rev (nreverse (split-string (buffer-string) "\n")))) |
847 | (nreverse (if (equal (car rev) "") | |
848 | (cdr rev) | |
849 | rev)))))) | |
847 | (nreverse (if (equal (car rev) "") | |
848 | (cdr rev) | |
849 | rev)))))) | |
850 | 850 | |
851 | 851 | (defun magit-write-file-lines (file lines) |
852 | 852 | (with-temp-buffer |
870 | 870 | |
871 | 871 | (defun magit-remove-conflicts (alist) |
872 | 872 | (let ((dict (make-hash-table :test 'equal)) |
873 | (result nil)) | |
873 | (result nil)) | |
874 | 874 | (dolist (a alist) |
875 | 875 | (puthash (car a) (cons (cdr a) (gethash (car a) dict)) |
876 | dict)) | |
876 | dict)) | |
877 | 877 | (maphash (lambda (key value) |
878 | (if (= (length value) 1) | |
879 | (push (cons key (car value)) result) | |
880 | (let ((sub (magit-remove-conflicts | |
881 | (mapcar (lambda (entry) | |
882 | (let ((dir (directory-file-name | |
883 | (substring entry 0 (- (length key)))))) | |
884 | (cons (concat (file-name-nondirectory dir) "/" key) | |
885 | entry))) | |
886 | value)))) | |
887 | (setq result (append result sub))))) | |
888 | dict) | |
878 | (if (= (length value) 1) | |
879 | (push (cons key (car value)) result) | |
880 | (let ((sub (magit-remove-conflicts | |
881 | (mapcar (lambda (entry) | |
882 | (let ((dir (directory-file-name | |
883 | (substring entry 0 (- (length key)))))) | |
884 | (cons (concat (file-name-nondirectory dir) "/" key) | |
885 | entry))) | |
886 | value)))) | |
887 | (setq result (append result sub))))) | |
888 | dict) | |
889 | 889 | result)) |
890 | 890 | |
891 | 891 | (defun magit-git-repo-p (dir) |
900 | 900 | (if (magit-git-repo-p dir) |
901 | 901 | (list dir) |
902 | 902 | (apply #'append |
903 | (mapcar (lambda (entry) | |
904 | (unless (or (string= (substring entry -3) "/..") | |
905 | (string= (substring entry -2) "/.")) | |
906 | (magit-list-repos* entry (+ level 1)))) | |
907 | (and (file-directory-p dir) | |
908 | (< level magit-repo-dirs-depth) | |
909 | (directory-files dir t nil t)))))) | |
903 | (mapcar (lambda (entry) | |
904 | (unless (or (string= (substring entry -3) "/..") | |
905 | (string= (substring entry -2) "/.")) | |
906 | (magit-list-repos* entry (+ level 1)))) | |
907 | (and (file-directory-p dir) | |
908 | (< level magit-repo-dirs-depth) | |
909 | (directory-files dir t nil t)))))) | |
910 | 910 | |
911 | 911 | (defun magit-list-repos (dirs) |
912 | 912 | (magit-remove-conflicts |
913 | 913 | (apply #'append |
914 | (mapcar (lambda (dir) | |
915 | (mapcar #'(lambda (repo) | |
916 | (cons (file-name-nondirectory repo) | |
917 | repo)) | |
918 | (magit-list-repos* dir 0))) | |
919 | dirs)))) | |
914 | (mapcar (lambda (dir) | |
915 | (mapcar #'(lambda (repo) | |
916 | (cons (file-name-nondirectory repo) | |
917 | repo)) | |
918 | (magit-list-repos* dir 0))) | |
919 | dirs)))) | |
920 | 920 | |
921 | 921 | (defun magit-get-top-dir (cwd) |
922 | 922 | (let ((cwd (expand-file-name (file-truename cwd)))) |
931 | 931 | |
932 | 932 | (defun magit-get-current-branch () |
933 | 933 | (let* ((head (magit-get-ref "HEAD")) |
934 | (pos (and head (string-match "^refs/heads/" head)))) | |
934 | (pos (and head (string-match "^refs/heads/" head)))) | |
935 | 935 | (if pos |
936 | (substring head 11) | |
936 | (substring head 11) | |
937 | 937 | nil))) |
938 | 938 | |
939 | 939 | (defun magit-get-remote (branch) |
969 | 969 | (error "Not a repository or a directory: %s" reply))))) |
970 | 970 | (file-name-as-directory |
971 | 971 | (read-directory-name "Git repository: " |
972 | (or (magit-get-top-dir default-directory) | |
973 | default-directory))))) | |
972 | (or (magit-get-top-dir default-directory) | |
973 | default-directory))))) | |
974 | 974 | |
975 | 975 | (defun magit-rev-parse (ref) |
976 | 976 | "Return the SHA hash for REF." |
1028 | 1028 | |
1029 | 1029 | (defun magit-put-line-property (prop val) |
1030 | 1030 | (put-text-property (line-beginning-position) (line-beginning-position 2) |
1031 | prop val)) | |
1031 | prop val)) | |
1032 | 1032 | |
1033 | 1033 | (defun magit-format-commit (commit format) |
1034 | 1034 | (magit-git-string "log" "--max-count=1" |
1035 | (concat "--pretty=format:" format) | |
1036 | commit)) | |
1035 | (concat "--pretty=format:" format) | |
1036 | commit)) | |
1037 | 1037 | |
1038 | 1038 | (defun magit-current-line () |
1039 | 1039 | (buffer-substring-no-properties (line-beginning-position) |
1040 | (line-end-position))) | |
1040 | (line-end-position))) | |
1041 | 1041 | |
1042 | 1042 | (defun magit-insert-region (beg end buf) |
1043 | 1043 | (let ((text (buffer-substring-no-properties beg end))) |
1046 | 1046 | |
1047 | 1047 | (defun magit-insert-current-line (buf) |
1048 | 1048 | (let ((text (buffer-substring-no-properties |
1049 | (line-beginning-position) (line-beginning-position 2)))) | |
1049 | (line-beginning-position) (line-beginning-position 2)))) | |
1050 | 1050 | (with-current-buffer buf |
1051 | 1051 | (insert text)))) |
1052 | 1052 | |
1068 | 1068 | (defun magit-choose-parent-id (commit op) |
1069 | 1069 | (let* ((parents (magit-commit-parents commit))) |
1070 | 1070 | (if (> (length parents) 1) |
1071 | (error "Can't %s merge commits" op) | |
1071 | (error "Can't %s merge commits" op) | |
1072 | 1072 | nil))) |
1073 | 1073 | |
1074 | 1074 | ;;; Revisions and ranges |
1150 | 1150 | (defun magit-read-rev (prompt &optional def uninteresting) |
1151 | 1151 | (let* ((interesting-refs (magit-list-interesting-refs |
1152 | 1152 | (or uninteresting magit-uninteresting-refs))) |
1153 | (reply (magit-completing-read (concat prompt ": ") interesting-refs | |
1153 | (reply (magit-completing-read (concat prompt ": ") interesting-refs | |
1154 | 1154 | nil nil nil 'magit-read-rev-history def)) |
1155 | (rev (or (cdr (assoc reply interesting-refs)) reply))) | |
1155 | (rev (or (cdr (assoc reply interesting-refs)) reply))) | |
1156 | 1156 | (if (string= rev "") |
1157 | nil | |
1157 | nil | |
1158 | 1158 | rev))) |
1159 | 1159 | |
1160 | 1160 | (defun magit-read-rev-range (op &optional def-beg def-end) |
1161 | 1161 | (let ((beg (magit-read-rev (format "%s start" op) |
1162 | def-beg))) | |
1162 | def-beg))) | |
1163 | 1163 | (if (not beg) |
1164 | nil | |
1164 | nil | |
1165 | 1165 | (save-match-data |
1166 | (if (string-match "^\\(.+\\)\\.\\.\\(.+\\)$" beg) | |
1167 | (cons (match-string 1 beg) (match-string 2 beg)) | |
1168 | (let ((end (magit-read-rev (format "%s end" op) def-end))) | |
1169 | (cons beg end))))))) | |
1166 | (if (string-match "^\\(.+\\)\\.\\.\\(.+\\)$" beg) | |
1167 | (cons (match-string 1 beg) (match-string 2 beg)) | |
1168 | (let ((end (magit-read-rev (format "%s end" op) def-end))) | |
1169 | (cons beg end))))))) | |
1170 | 1170 | |
1171 | 1171 | (defun magit-rev-to-git (rev) |
1172 | 1172 | (or rev |
1181 | 1181 | (if (stringp range) |
1182 | 1182 | range |
1183 | 1183 | (if (cdr range) |
1184 | (format "%s..%s" | |
1185 | (magit-rev-to-git (car range)) | |
1186 | (magit-rev-to-git (cdr range))) | |
1184 | (format "%s..%s" | |
1185 | (magit-rev-to-git (car range)) | |
1186 | (magit-rev-to-git (cdr range))) | |
1187 | 1187 | (format "%s" (magit-rev-to-git (car range)))))) |
1188 | 1188 | |
1189 | 1189 | (defun magit-rev-describe (rev) |
1199 | 1199 | (if (stringp range) |
1200 | 1200 | (format "%s in %s" things range) |
1201 | 1201 | (if (cdr range) |
1202 | (format "%s from %s to %s" things | |
1203 | (magit-rev-describe (car range)) | |
1204 | (magit-rev-describe (cdr range))) | |
1202 | (format "%s from %s to %s" things | |
1203 | (magit-rev-describe (car range)) | |
1204 | (magit-rev-describe (cdr range))) | |
1205 | 1205 | (format "%s at %s" things (magit-rev-describe (car range)))))) |
1206 | 1206 | |
1207 | 1207 | (defun magit-default-rev () |
1208 | 1208 | (or (magit-name-rev (magit-commit-at-point t)) |
1209 | 1209 | (let ((branch (magit-guess-branch))) |
1210 | (if branch | |
1211 | (if (string-match "^refs/\\(.*\\)" branch) | |
1212 | (match-string 1 branch) | |
1213 | branch))))) | |
1210 | (if branch | |
1211 | (if (string-match "^refs/\\(.*\\)" branch) | |
1212 | (match-string 1 branch) | |
1213 | branch))))) | |
1214 | 1214 | |
1215 | 1215 | (defun magit-read-remote (&optional prompt def) |
1216 | 1216 | "Read the name of a remote. |
1218 | 1218 | DEF is the default value, and defaults to the value of `magit-get-current-branch'." |
1219 | 1219 | (let* ((prompt (or prompt "Remote: ")) |
1220 | 1220 | (def (or def (magit-get-current-remote))) |
1221 | (remotes (magit-git-lines "remote")) | |
1222 | (reply (magit-completing-read prompt remotes | |
1221 | (remotes (magit-git-lines "remote")) | |
1222 | (reply (magit-completing-read prompt remotes | |
1223 | 1223 | nil nil nil nil def))) |
1224 | 1224 | (if (string= reply "") nil reply))) |
1225 | 1225 | |
1255 | 1255 | |
1256 | 1256 | If TYPE is nil, the section won't be highlighted." |
1257 | 1257 | (let* ((s (make-magit-section :parent magit-top-section |
1258 | :title title | |
1259 | :type type | |
1260 | :hidden magit-section-hidden-default)) | |
1261 | (old (and magit-old-top-section | |
1262 | (magit-find-section (magit-section-path s) | |
1263 | magit-old-top-section)))) | |
1258 | :title title | |
1259 | :type type | |
1260 | :hidden magit-section-hidden-default)) | |
1261 | (old (and magit-old-top-section | |
1262 | (magit-find-section (magit-section-path s) | |
1263 | magit-old-top-section)))) | |
1264 | 1264 | (if magit-top-section |
1265 | (push s (magit-section-children magit-top-section)) | |
1266 | (setq magit-top-section s)) | |
1265 | (push s (magit-section-children magit-top-section)) | |
1266 | (setq magit-top-section s)) | |
1267 | 1267 | (if old |
1268 | (setf (magit-section-hidden s) (magit-section-hidden old))) | |
1268 | (setf (magit-section-hidden s) (magit-section-hidden old))) | |
1269 | 1269 | s)) |
1270 | 1270 | |
1271 | 1271 | (defun magit-cancel-section (section) |
1272 | 1272 | "Delete the section SECTION." |
1273 | 1273 | (delete-region (magit-section-beginning section) |
1274 | (magit-section-end section)) | |
1274 | (magit-section-end section)) | |
1275 | 1275 | (let ((parent (magit-section-parent section))) |
1276 | 1276 | (if parent |
1277 | (setf (magit-section-children parent) | |
1278 | (delq section (magit-section-children parent))) | |
1279 | (setq magit-top-section nil)))) | |
1277 | (setf (magit-section-children parent) | |
1278 | (delq section (magit-section-children parent))) | |
1279 | (setq magit-top-section nil)))) | |
1280 | 1280 | |
1281 | 1281 | (defmacro magit-with-section (title type &rest body) |
1282 | 1282 | "Create a new section of title TITLE and type TYPE and evaluate BODY there. |
1288 | 1288 | (declare (indent 2)) |
1289 | 1289 | (let ((s (make-symbol "*section*"))) |
1290 | 1290 | `(let* ((,s (magit-new-section ,title ,type)) |
1291 | (magit-top-section ,s)) | |
1291 | (magit-top-section ,s)) | |
1292 | 1292 | (setf (magit-section-beginning ,s) (point)) |
1293 | 1293 | ,@body |
1294 | 1294 | (setf (magit-section-end ,s) (point)) |
1295 | 1295 | (setf (magit-section-children ,s) |
1296 | (nreverse (magit-section-children ,s))) | |
1296 | (nreverse (magit-section-children ,s))) | |
1297 | 1297 | ,s))) |
1298 | 1298 | |
1299 | 1299 | (defun magit-set-section (title type start end) |
1309 | 1309 | |
1310 | 1310 | (defun magit-set-section-needs-refresh-on-show (flag &optional section) |
1311 | 1311 | (setf (magit-section-needs-refresh-on-show |
1312 | (or section magit-top-section)) | |
1313 | flag)) | |
1312 | (or section magit-top-section)) | |
1313 | flag)) | |
1314 | 1314 | |
1315 | 1315 | (defmacro magit-create-buffer-sections (&rest body) |
1316 | 1316 | "Empty current buffer of text and Magit's sections, and then evaluate BODY." |
1321 | 1321 | (setq magit-top-section nil) |
1322 | 1322 | ,@body |
1323 | 1323 | (when (null magit-top-section) |
1324 | (magit-with-section 'top nil | |
1325 | (insert "(empty)\n"))) | |
1324 | (magit-with-section 'top nil | |
1325 | (insert "(empty)\n"))) | |
1326 | 1326 | (magit-propertize-section magit-top-section) |
1327 | 1327 | (magit-section-set-hidden magit-top-section |
1328 | (magit-section-hidden magit-top-section))))) | |
1328 | (magit-section-hidden magit-top-section))))) | |
1329 | 1329 | |
1330 | 1330 | (defun magit-propertize-section (section) |
1331 | 1331 | "Add text-property needed for SECTION." |
1332 | 1332 | (put-text-property (magit-section-beginning section) |
1333 | (magit-section-end section) | |
1334 | 'magit-section section) | |
1333 | (magit-section-end section) | |
1334 | 'magit-section section) | |
1335 | 1335 | (dolist (s (magit-section-children section)) |
1336 | 1336 | (magit-propertize-section s))) |
1337 | 1337 | |
1341 | 1341 | top |
1342 | 1342 | (let ((secs (magit-section-children top))) |
1343 | 1343 | (while (and secs (not (equal (car path) |
1344 | (magit-section-title (car secs))))) | |
1345 | (setq secs (cdr secs))) | |
1344 | (magit-section-title (car secs))))) | |
1345 | (setq secs (cdr secs))) | |
1346 | 1346 | (and (car secs) |
1347 | (magit-find-section (cdr path) (car secs)))))) | |
1347 | (magit-find-section (cdr path) (car secs)))))) | |
1348 | 1348 | |
1349 | 1349 | (defun magit-section-path (section) |
1350 | 1350 | "Return the path of SECTION." |
1351 | 1351 | (if (not (magit-section-parent section)) |
1352 | 1352 | '() |
1353 | 1353 | (append (magit-section-path (magit-section-parent section)) |
1354 | (list (magit-section-title section))))) | |
1354 | (list (magit-section-title section))))) | |
1355 | 1355 | |
1356 | 1356 | (defun magit-find-section-after (pos) |
1357 | 1357 | "Find the first section that begins after POS." |
1399 | 1399 | magit-top-section)) |
1400 | 1400 | |
1401 | 1401 | (defun magit-insert-section (section-title-and-type |
1402 | buffer-title washer cmd &rest args) | |
1402 | buffer-title washer cmd &rest args) | |
1403 | 1403 | "Run CMD and put its result in a new section. |
1404 | 1404 | |
1405 | 1405 | SECTION-TITLE-AND-TYPE is either a string that is the title of the section |
1415 | 1415 | |
1416 | 1416 | CMD is an external command that will be run with ARGS as arguments." |
1417 | 1417 | (let* ((body-beg nil) |
1418 | (section-title (if (consp section-title-and-type) | |
1419 | (car section-title-and-type) | |
1420 | section-title-and-type)) | |
1421 | (section-type (if (consp section-title-and-type) | |
1422 | (cdr section-title-and-type) | |
1423 | nil)) | |
1424 | (section | |
1425 | (magit-with-section section-title section-type | |
1426 | (if buffer-title | |
1427 | (insert (propertize buffer-title 'face 'magit-section-title) | |
1428 | "\n")) | |
1429 | (setq body-beg (point)) | |
1418 | (section-title (if (consp section-title-and-type) | |
1419 | (car section-title-and-type) | |
1420 | section-title-and-type)) | |
1421 | (section-type (if (consp section-title-and-type) | |
1422 | (cdr section-title-and-type) | |
1423 | nil)) | |
1424 | (section | |
1425 | (magit-with-section section-title section-type | |
1426 | (if buffer-title | |
1427 | (insert (propertize buffer-title 'face 'magit-section-title) | |
1428 | "\n")) | |
1429 | (setq body-beg (point)) | |
1430 | 1430 | (magit-cmd-insert cmd args) |
1431 | (if (not (eq (char-before) ?\n)) | |
1432 | (insert "\n")) | |
1433 | (if washer | |
1434 | (save-restriction | |
1435 | (narrow-to-region body-beg (point)) | |
1436 | (goto-char (point-min)) | |
1437 | (funcall washer) | |
1438 | (goto-char (point-max))))))) | |
1431 | (if (not (eq (char-before) ?\n)) | |
1432 | (insert "\n")) | |
1433 | (if washer | |
1434 | (save-restriction | |
1435 | (narrow-to-region body-beg (point)) | |
1436 | (goto-char (point-min)) | |
1437 | (funcall washer) | |
1438 | (goto-char (point-max))))))) | |
1439 | 1439 | (if (= body-beg (point)) |
1440 | (magit-cancel-section section) | |
1440 | (magit-cancel-section section) | |
1441 | 1441 | (insert "\n")) |
1442 | 1442 | section)) |
1443 | 1443 | |
1444 | 1444 | (defun magit-git-section (section-title-and-type |
1445 | buffer-title washer &rest args) | |
1445 | buffer-title washer &rest args) | |
1446 | 1446 | "Run git and put its result in a new section. |
1447 | 1447 | |
1448 | 1448 | see `magit-insert-section' for meaning of the arguments" |
1449 | 1449 | (apply #'magit-insert-section |
1450 | section-title-and-type | |
1451 | buffer-title | |
1452 | washer | |
1453 | magit-git-executable | |
1454 | (append magit-git-standard-options args))) | |
1450 | section-title-and-type | |
1451 | buffer-title | |
1452 | washer | |
1453 | magit-git-executable | |
1454 | (append magit-git-standard-options args))) | |
1455 | 1455 | |
1456 | 1456 | (defun magit-goto-next-section () |
1457 | 1457 | "Go to the next Magit section." |
1491 | 1491 | "Go to the section described by PATH." |
1492 | 1492 | (let ((sec (magit-find-section path magit-top-section))) |
1493 | 1493 | (if sec |
1494 | (goto-char (magit-section-beginning sec)) | |
1494 | (goto-char (magit-section-beginning sec)) | |
1495 | 1495 | (message "No such section")))) |
1496 | 1496 | |
1497 | 1497 | (defun magit-for-all-sections (func &optional top) |
1502 | 1502 | (when section |
1503 | 1503 | (funcall func section) |
1504 | 1504 | (dolist (c (magit-section-children section)) |
1505 | (magit-for-all-sections func c))))) | |
1505 | (magit-for-all-sections func c))))) | |
1506 | 1506 | |
1507 | 1507 | (defun magit-section-set-hidden (section hidden) |
1508 | 1508 | "Hide SECTION if HIDDEN is not nil, show it otherwise." |
1509 | 1509 | (setf (magit-section-hidden section) hidden) |
1510 | 1510 | (if (and (not hidden) |
1511 | (magit-section-needs-refresh-on-show section)) | |
1511 | (magit-section-needs-refresh-on-show section)) | |
1512 | 1512 | (magit-refresh) |
1513 | 1513 | (let ((inhibit-read-only t) |
1514 | (beg (save-excursion | |
1515 | (goto-char (magit-section-beginning section)) | |
1516 | (forward-line) | |
1517 | (point))) | |
1518 | (end (magit-section-end section))) | |
1514 | (beg (save-excursion | |
1515 | (goto-char (magit-section-beginning section)) | |
1516 | (forward-line) | |
1517 | (point))) | |
1518 | (end (magit-section-end section))) | |
1519 | 1519 | (if (< beg end) |
1520 | 1520 | (put-text-property beg end 'invisible hidden))) |
1521 | 1521 | (if (not hidden) |
1522 | (dolist (c (magit-section-children section)) | |
1523 | (magit-section-set-hidden c (magit-section-hidden c)))))) | |
1522 | (dolist (c (magit-section-children section)) | |
1523 | (magit-section-set-hidden c (magit-section-hidden c)))))) | |
1524 | 1524 | |
1525 | 1525 | (defun magit-section-any-hidden (section) |
1526 | 1526 | "Return true if SECTION or any of its children is hidden." |
1527 | 1527 | (or (magit-section-hidden section) |
1528 | 1528 | (let ((kids (magit-section-children section))) |
1529 | (while (and kids (not (magit-section-any-hidden (car kids)))) | |
1530 | (setq kids (cdr kids))) | |
1531 | kids))) | |
1529 | (while (and kids (not (magit-section-any-hidden (car kids)))) | |
1530 | (setq kids (cdr kids))) | |
1531 | kids))) | |
1532 | 1532 | |
1533 | 1533 | (defun magit-section-collapse (section) |
1534 | 1534 | "Show SECTION and hide all its children." |
1562 | 1562 | (when (magit-section-parent section) |
1563 | 1563 | (goto-char (magit-section-beginning section)) |
1564 | 1564 | (if (functionp flag-or-func) |
1565 | (funcall flag-or-func section) | |
1566 | (magit-section-set-hidden section flag-or-func))))) | |
1565 | (funcall flag-or-func section) | |
1566 | (magit-section-set-hidden section flag-or-func))))) | |
1567 | 1567 | |
1568 | 1568 | (defun magit-show-section () |
1569 | 1569 | "Show current section." |
1605 | 1605 | (magit-section-hideshow |
1606 | 1606 | (lambda (s) |
1607 | 1607 | (cond ((magit-section-any-hidden s) |
1608 | (magit-section-expand-all s)) | |
1609 | (t | |
1610 | (magit-section-collapse s)))))) | |
1608 | (magit-section-expand-all s)) | |
1609 | (t | |
1610 | (magit-section-collapse s)))))) | |
1611 | 1611 | |
1612 | 1612 | (defun magit-cycle-section () |
1613 | 1613 | "Cycle between expanded, hidden and collapsed state for current section. |
1619 | 1619 | (magit-section-hideshow |
1620 | 1620 | (lambda (s) |
1621 | 1621 | (cond ((magit-section-hidden s) |
1622 | (magit-section-collapse s)) | |
1623 | ((notany #'magit-section-hidden (magit-section-children s)) | |
1624 | (magit-section-set-hidden s t)) | |
1625 | (t | |
1626 | (magit-section-expand s)))))) | |
1622 | (magit-section-collapse s)) | |
1623 | ((notany #'magit-section-hidden (magit-section-children s)) | |
1624 | (magit-section-set-hidden s t)) | |
1625 | (t | |
1626 | (magit-section-expand s)))))) | |
1627 | 1627 | |
1628 | 1628 | (defun magit-section-lineage (s) |
1629 | 1629 | "Return list of parent, grand-parents... for section S." |
1634 | 1634 | (magit-section-set-hidden section (>= level threshold)) |
1635 | 1635 | (when (and (< level threshold) |
1636 | 1636 | (not (magit-no-commit-p))) |
1637 | (if path | |
1638 | (magit-section-show-level (car path) (1+ level) threshold (cdr path)) | |
1639 | (dolist (c (magit-section-children section)) | |
1640 | (magit-section-show-level c (1+ level) threshold nil))))) | |
1637 | (if path | |
1638 | (magit-section-show-level (car path) (1+ level) threshold (cdr path)) | |
1639 | (dolist (c (magit-section-children section)) | |
1640 | (magit-section-show-level c (1+ level) threshold nil))))) | |
1641 | 1641 | |
1642 | 1642 | (defun magit-show-level (level all) |
1643 | 1643 | "Show section whose level is less than LEVEL, hide the others. |
1645 | 1645 | otherwise do it only on ancestors and descendants of current section." |
1646 | 1646 | (magit-with-refresh |
1647 | 1647 | (if all |
1648 | (magit-section-show-level magit-top-section 0 level nil) | |
1648 | (magit-section-show-level magit-top-section 0 level nil) | |
1649 | 1649 | (let ((path (reverse (magit-section-lineage (magit-current-section))))) |
1650 | (magit-section-show-level (car path) 0 level (cdr path)))))) | |
1650 | (magit-section-show-level (car path) 0 level (cdr path)))))) | |
1651 | 1651 | |
1652 | 1652 | (defun magit-show-only-files () |
1653 | 1653 | "Show section that are files, but not there subsection. |
1673 | 1673 | If ALL is non nil, this function will affect all section, |
1674 | 1674 | otherwise it will affect only ancestors and descendants of current section." |
1675 | 1675 | (let ((fun (intern (format "magit-show-level-%s%s" |
1676 | level (if all "-all" "")))) | |
1677 | (doc (format "Show sections on level %s." level))) | |
1676 | level (if all "-all" "")))) | |
1677 | (doc (format "Show sections on level %s." level))) | |
1678 | 1678 | `(defun ,fun () |
1679 | 1679 | ,doc |
1680 | 1680 | (interactive) |
1692 | 1692 | |
1693 | 1693 | TITLE is the displayed title of the section." |
1694 | 1694 | (let ((fun (intern (format "magit-jump-to-%s" sym))) |
1695 | (doc (format "Jump to section `%s'." title))) | |
1695 | (doc (format "Jump to section `%s'." title))) | |
1696 | 1696 | `(defun ,fun () |
1697 | 1697 | ,doc |
1698 | 1698 | (interactive) |
1720 | 1720 | (when (not (eq section magit-highlighted-section)) |
1721 | 1721 | (setq magit-highlighted-section section) |
1722 | 1722 | (if (not magit-highlight-overlay) |
1723 | (let ((ov (make-overlay 1 1))) | |
1724 | (overlay-put ov 'face 'magit-item-highlight) | |
1725 | (setq magit-highlight-overlay ov))) | |
1723 | (let ((ov (make-overlay 1 1))) | |
1724 | (overlay-put ov 'face 'magit-item-highlight) | |
1725 | (setq magit-highlight-overlay ov))) | |
1726 | 1726 | (if (and section (magit-section-type section)) |
1727 | (move-overlay magit-highlight-overlay | |
1728 | (magit-section-beginning section) | |
1729 | (magit-section-end section) | |
1730 | (current-buffer)) | |
1731 | (delete-overlay magit-highlight-overlay))))) | |
1727 | (move-overlay magit-highlight-overlay | |
1728 | (magit-section-beginning section) | |
1729 | (magit-section-end section) | |
1730 | (current-buffer)) | |
1731 | (delete-overlay magit-highlight-overlay))))) | |
1732 | 1732 | |
1733 | 1733 | (defun magit-section-context-type (section) |
1734 | 1734 | (if (null section) |
1735 | 1735 | '() |
1736 | 1736 | (let ((c (or (magit-section-type section) |
1737 | (if (symbolp (magit-section-title section)) | |
1738 | (magit-section-title section))))) | |
1737 | (if (symbolp (magit-section-title section)) | |
1738 | (magit-section-title section))))) | |
1739 | 1739 | (if c |
1740 | (cons c (magit-section-context-type | |
1741 | (magit-section-parent section))) | |
1742 | '())))) | |
1740 | (cons c (magit-section-context-type | |
1741 | (magit-section-parent section))) | |
1742 | '())))) | |
1743 | 1743 | |
1744 | 1744 | (defun magit-prefix-p (prefix list) |
1745 | 1745 | "Returns non-nil if PREFIX is a prefix of LIST. PREFIX and LIST should both be |
1787 | 1787 | (cond ,@(mapcar (lambda (clause) |
1788 | 1788 | (if (eq (car clause) t) |
1789 | 1789 | `(t (or (progn ,@(cdr clause)) |
1790 | t)) | |
1790 | t)) | |
1791 | 1791 | (let ((prefix (reverse (car clause))) |
1792 | 1792 | (body (cdr clause))) |
1793 | 1793 | `((magit-prefix-p ',prefix ,context) |
1794 | 1794 | (or (progn ,@body) |
1795 | t))))) | |
1795 | t))))) | |
1796 | 1796 | clauses) |
1797 | 1797 | ,@(when opname |
1798 | 1798 | `(((run-hook-with-args-until-success |
1875 | 1875 | (let ((pr (if str (concat " " str) ""))) |
1876 | 1876 | (save-excursion |
1877 | 1877 | (magit-for-all-buffers (lambda () |
1878 | (setq mode-line-process pr)))))) | |
1878 | (setq mode-line-process pr)))))) | |
1879 | 1879 | |
1880 | 1880 | (defun magit-process-indicator-from-command (comps) |
1881 | 1881 | (if (magit-prefix-p (cons magit-git-executable magit-git-standard-options) |
1882 | comps) | |
1882 | comps) | |
1883 | 1883 | (setq comps (nthcdr (+ (length magit-git-standard-options) 1) comps))) |
1884 | 1884 | (cond ((or (null (cdr comps)) |
1885 | (not (member (car comps) '("remote")))) | |
1886 | (car comps)) | |
1887 | (t | |
1888 | (concat (car comps) " " (cadr comps))))) | |
1885 | (not (member (car comps) '("remote")))) | |
1886 | (car comps)) | |
1887 | (t | |
1888 | (concat (car comps) " " (cadr comps))))) | |
1889 | 1889 | |
1890 | 1890 | (defvar magit-process nil) |
1891 | 1891 | (defvar magit-process-client-buffer nil) |
1893 | 1893 | "Buffer name for running git commands.") |
1894 | 1894 | |
1895 | 1895 | (defun magit-run* (cmd-and-args |
1896 | &optional logline noerase noerror nowait input) | |
1896 | &optional logline noerase noerror nowait input) | |
1897 | 1897 | (if (and magit-process |
1898 | (get-buffer magit-process-buffer-name)) | |
1898 | (get-buffer magit-process-buffer-name)) | |
1899 | 1899 | (error "Git is already running")) |
1900 | 1900 | (let ((cmd (car cmd-and-args)) |
1901 | (args (cdr cmd-and-args)) | |
1902 | (dir default-directory) | |
1903 | (buf (get-buffer-create magit-process-buffer-name)) | |
1904 | (successp nil)) | |
1901 | (args (cdr cmd-and-args)) | |
1902 | (dir default-directory) | |
1903 | (buf (get-buffer-create magit-process-buffer-name)) | |
1904 | (successp nil)) | |
1905 | 1905 | (magit-set-mode-line-process |
1906 | 1906 | (magit-process-indicator-from-command cmd-and-args)) |
1907 | 1907 | (setq magit-process-client-buffer (current-buffer)) |
1909 | 1909 | (view-mode 1) |
1910 | 1910 | (set (make-local-variable 'view-no-disable-on-exit) t) |
1911 | 1911 | (setq view-exit-action |
1912 | (lambda (buffer) | |
1913 | (with-current-buffer buffer | |
1914 | (bury-buffer)))) | |
1912 | (lambda (buffer) | |
1913 | (with-current-buffer buffer | |
1914 | (bury-buffer)))) | |
1915 | 1915 | (setq buffer-read-only t) |
1916 | 1916 | (let ((inhibit-read-only t)) |
1917 | (setq default-directory dir) | |
1918 | (if noerase | |
1919 | (goto-char (point-max)) | |
1920 | (erase-buffer)) | |
1921 | (insert "$ " (or logline | |
1922 | (mapconcat 'identity cmd-and-args " ")) | |
1923 | "\n") | |
1924 | (cond (nowait | |
1925 | (setq magit-process | |
1926 | (let ((process-connection-type magit-process-connection-type)) | |
1927 | (apply 'magit-start-process cmd buf cmd args))) | |
1928 | (set-process-sentinel magit-process 'magit-process-sentinel) | |
1929 | (set-process-filter magit-process 'magit-process-filter) | |
1930 | (when input | |
1931 | (with-current-buffer input | |
1932 | (process-send-region magit-process | |
1933 | (point-min) (point-max))) | |
1934 | (process-send-eof magit-process) | |
1935 | (sit-for 0.1 t)) | |
1936 | (cond ((= magit-process-popup-time 0) | |
1937 | (pop-to-buffer (process-buffer magit-process))) | |
1938 | ((> magit-process-popup-time 0) | |
1939 | (run-with-timer | |
1940 | magit-process-popup-time nil | |
1941 | (function | |
1942 | (lambda (buf) | |
1943 | (with-current-buffer buf | |
1944 | (when magit-process | |
1945 | (display-buffer (process-buffer magit-process)) | |
1946 | (goto-char (point-max)))))) | |
1947 | (current-buffer)))) | |
1948 | (setq successp t)) | |
1949 | (input | |
1950 | (with-current-buffer input | |
1951 | (setq default-directory dir) | |
1952 | (setq magit-process | |
1953 | ;; Don't use a pty, because it would set icrnl | |
1954 | ;; which would modify the input (issue #20). | |
1955 | (let ((process-connection-type nil)) | |
1956 | (apply 'magit-start-process cmd buf cmd args))) | |
1957 | (set-process-filter magit-process 'magit-process-filter) | |
1958 | (process-send-region magit-process | |
1959 | (point-min) (point-max)) | |
1960 | (process-send-eof magit-process) | |
1961 | (while (equal (process-status magit-process) 'run) | |
1962 | (sit-for 0.1 t)) | |
1963 | (setq successp | |
1964 | (equal (process-exit-status magit-process) 0)) | |
1965 | (setq magit-process nil)) | |
1966 | (magit-set-mode-line-process nil) | |
1967 | (magit-need-refresh magit-process-client-buffer)) | |
1968 | (t | |
1969 | (setq successp | |
1970 | (equal (apply 'process-file cmd nil buf nil args) 0)) | |
1971 | (magit-set-mode-line-process nil) | |
1972 | (magit-need-refresh magit-process-client-buffer)))) | |
1917 | (setq default-directory dir) | |
1918 | (if noerase | |
1919 | (goto-char (point-max)) | |
1920 | (erase-buffer)) | |
1921 | (insert "$ " (or logline | |
1922 | (mapconcat 'identity cmd-and-args " ")) | |
1923 | "\n") | |
1924 | (cond (nowait | |
1925 | (setq magit-process | |
1926 | (let ((process-connection-type magit-process-connection-type)) | |
1927 | (apply 'magit-start-process cmd buf cmd args))) | |
1928 | (set-process-sentinel magit-process 'magit-process-sentinel) | |
1929 | (set-process-filter magit-process 'magit-process-filter) | |
1930 | (when input | |
1931 | (with-current-buffer input | |
1932 | (process-send-region magit-process | |
1933 | (point-min) (point-max))) | |
1934 | (process-send-eof magit-process) | |
1935 | (sit-for 0.1 t)) | |
1936 | (cond ((= magit-process-popup-time 0) | |
1937 | (pop-to-buffer (process-buffer magit-process))) | |
1938 | ((> magit-process-popup-time 0) | |
1939 | (run-with-timer | |
1940 | magit-process-popup-time nil | |
1941 | (function | |
1942 | (lambda (buf) | |
1943 | (with-current-buffer buf | |
1944 | (when magit-process | |
1945 | (display-buffer (process-buffer magit-process)) | |
1946 | (goto-char (point-max)))))) | |
1947 | (current-buffer)))) | |
1948 | (setq successp t)) | |
1949 | (input | |
1950 | (with-current-buffer input | |
1951 | (setq default-directory dir) | |
1952 | (setq magit-process | |
1953 | ;; Don't use a pty, because it would set icrnl | |
1954 | ;; which would modify the input (issue #20). | |
1955 | (let ((process-connection-type nil)) | |
1956 | (apply 'magit-start-process cmd buf cmd args))) | |
1957 | (set-process-filter magit-process 'magit-process-filter) | |
1958 | (process-send-region magit-process | |
1959 | (point-min) (point-max)) | |
1960 | (process-send-eof magit-process) | |
1961 | (while (equal (process-status magit-process) 'run) | |
1962 | (sit-for 0.1 t)) | |
1963 | (setq successp | |
1964 | (equal (process-exit-status magit-process) 0)) | |
1965 | (setq magit-process nil)) | |
1966 | (magit-set-mode-line-process nil) | |
1967 | (magit-need-refresh magit-process-client-buffer)) | |
1968 | (t | |
1969 | (setq successp | |
1970 | (equal (apply 'process-file cmd nil buf nil args) 0)) | |
1971 | (magit-set-mode-line-process nil) | |
1972 | (magit-need-refresh magit-process-client-buffer)))) | |
1973 | 1973 | (or successp |
1974 | noerror | |
1975 | (error | |
1974 | noerror | |
1975 | (error | |
1976 | 1976 | "%s ... [Hit %s or see buffer %s for details]" |
1977 | 1977 | (or (with-current-buffer (get-buffer magit-process-buffer-name) |
1978 | 1978 | (when (re-search-backward |
1988 | 1988 | (autoload 'dired-uncache "dired") |
1989 | 1989 | (defun magit-process-sentinel (process event) |
1990 | 1990 | (let ((msg (format "%s %s." (process-name process) (substring event 0 -1))) |
1991 | (successp (string-match "^finished" event)) | |
1991 | (successp (string-match "^finished" event)) | |
1992 | 1992 | (key (with-current-buffer magit-process-client-buffer |
1993 | 1993 | (key-description (car (where-is-internal |
1994 | 1994 | 'magit-display-process)))))) |
1995 | 1995 | (with-current-buffer (process-buffer process) |
1996 | 1996 | (let ((inhibit-read-only t)) |
1997 | (goto-char (point-max)) | |
1998 | (insert msg "\n") | |
1999 | (message (if successp msg | |
1997 | (goto-char (point-max)) | |
1998 | (insert msg "\n") | |
1999 | (message (if successp msg | |
2000 | 2000 | (format "%s Hit %s or see buffer %s for details." |
2001 | 2001 | msg key (current-buffer))))) |
2002 | 2002 | (unless (memq (process-status process) '(run open)) |
2014 | 2014 | ((string-match "^[pP]assword:" string) |
2015 | 2015 | (setq ask "Password:"))) |
2016 | 2016 | (when ask |
2017 | (process-send-string proc (concat (read-passwd ask nil) "\n"))))) | |
2017 | (process-send-string proc (concat (read-passwd ask nil) "\n"))))) | |
2018 | 2018 | |
2019 | 2019 | (defun magit-process-filter (proc string) |
2020 | 2020 | (save-current-buffer |
2025 | 2025 | ;; Find last ^M in string. If one was found, ignore everything |
2026 | 2026 | ;; before it and delete the current line. |
2027 | 2027 | (let ((ret-pos (length string))) |
2028 | (while (and (>= (setq ret-pos (1- ret-pos)) 0) | |
2029 | (/= ?\r (aref string ret-pos)))) | |
2030 | (cond ((>= ret-pos 0) | |
2031 | (goto-char (line-beginning-position)) | |
2032 | (delete-region (point) (line-end-position)) | |
2033 | (insert (substring string (+ ret-pos 1)))) | |
2034 | (t | |
2035 | (insert string)))) | |
2028 | (while (and (>= (setq ret-pos (1- ret-pos)) 0) | |
2029 | (/= ?\r (aref string ret-pos)))) | |
2030 | (cond ((>= ret-pos 0) | |
2031 | (goto-char (line-beginning-position)) | |
2032 | (delete-region (point) (line-end-position)) | |
2033 | (insert (substring string (+ ret-pos 1)))) | |
2034 | (t | |
2035 | (insert string)))) | |
2036 | 2036 | (set-marker (process-mark proc) (point))))) |
2037 | 2037 | |
2038 | 2038 | (defun magit-run (cmd &rest args) |
2042 | 2042 | (defun magit-run-git (&rest args) |
2043 | 2043 | (magit-with-refresh |
2044 | 2044 | (magit-run* (append (cons magit-git-executable |
2045 | magit-git-standard-options) | |
2046 | args)))) | |
2045 | magit-git-standard-options) | |
2046 | args)))) | |
2047 | 2047 | |
2048 | 2048 | (defun magit-run-git-with-input (input &rest args) |
2049 | 2049 | (magit-with-refresh |
2050 | 2050 | (magit-run* (append (cons magit-git-executable |
2051 | magit-git-standard-options) | |
2052 | args) | |
2053 | nil nil nil nil input))) | |
2051 | magit-git-standard-options) | |
2052 | args) | |
2053 | nil nil nil nil input))) | |
2054 | 2054 | |
2055 | 2055 | (defun magit-run-git-async (&rest args) |
2056 | 2056 | (message "Running %s %s" magit-git-executable (mapconcat 'identity args " ")) |
2057 | 2057 | (magit-run* (append (cons magit-git-executable |
2058 | magit-git-standard-options) | |
2059 | args) | |
2060 | nil nil nil t)) | |
2058 | magit-git-standard-options) | |
2059 | args) | |
2060 | nil nil nil t)) | |
2061 | 2061 | |
2062 | 2062 | (defun magit-run-async-with-input (input cmd &rest args) |
2063 | 2063 | (magit-run* (cons cmd args) nil nil nil t input)) |
2185 | 2185 | before the last command." |
2186 | 2186 | (if (invisible-p (point)) |
2187 | 2187 | (let ((end (magit-invisible-region-end (point)))) |
2188 | (goto-char (if (= end last-point) | |
2189 | (magit-invisible-region-start (point)) | |
2190 | end)))) | |
2188 | (goto-char (if (= end last-point) | |
2189 | (magit-invisible-region-start (point)) | |
2190 | end)))) | |
2191 | 2191 | (setq disable-point-adjustment t)) |
2192 | 2192 | |
2193 | 2193 | (defun magit-post-command-hook () |
2204 | 2204 | (buffer-disable-undo) |
2205 | 2205 | (setq buffer-read-only t) |
2206 | 2206 | (setq major-mode 'magit-mode |
2207 | mode-name "Magit" | |
2207 | mode-name "Magit" | |
2208 | 2208 | mode-line-process "") |
2209 | 2209 | (add-hook 'pre-command-hook #'magit-remember-point nil t) |
2210 | 2210 | (add-hook 'post-command-hook #'magit-post-command-hook t t) |
2219 | 2219 | |
2220 | 2220 | (defun magit-mode-init (dir submode refresh-func &rest refresh-args) |
2221 | 2221 | (setq default-directory dir |
2222 | magit-refresh-function refresh-func | |
2223 | magit-refresh-args refresh-args) | |
2222 | magit-refresh-function refresh-func | |
2223 | magit-refresh-args refresh-args) | |
2224 | 2224 | (funcall submode) |
2225 | 2225 | (magit-refresh-buffer)) |
2226 | 2226 | |
2247 | 2247 | (dolist (buf (buffer-list)) |
2248 | 2248 | (with-current-buffer buf |
2249 | 2249 | (if (and (derived-mode-p 'magit-mode) |
2250 | (or (null dir) | |
2251 | (equal default-directory dir))) | |
2252 | (funcall func))))) | |
2250 | (or (null dir) | |
2251 | (equal default-directory dir))) | |
2252 | (funcall func))))) | |
2253 | 2253 | |
2254 | 2254 | (defun magit-refresh-buffer (&optional buffer) |
2255 | 2255 | (with-current-buffer (or buffer (current-buffer)) |
2256 | 2256 | (let* ((old-line (line-number-at-pos)) |
2257 | 2257 | (old-point (point)) |
2258 | (old-section (magit-current-section)) | |
2259 | (old-path (and old-section | |
2260 | (magit-section-path (magit-current-section))))) | |
2258 | (old-section (magit-current-section)) | |
2259 | (old-path (and old-section | |
2260 | (magit-section-path (magit-current-section))))) | |
2261 | 2261 | (beginning-of-line) |
2262 | 2262 | (let ((section-line (and old-section |
2263 | 2263 | (count-lines |
2302 | 2302 | "Update the modeline for buffers representable by magit." |
2303 | 2303 | (dolist (buffer (buffer-list)) |
2304 | 2304 | (when (and buffer |
2305 | (buffer-file-name buffer) | |
2306 | (magit-string-has-prefix-p (buffer-file-name buffer) dir)) | |
2305 | (buffer-file-name buffer) | |
2306 | (magit-string-has-prefix-p (buffer-file-name buffer) dir)) | |
2307 | 2307 | (with-current-buffer buffer |
2308 | (condition-case var | |
2309 | (vc-find-file-hook) | |
2310 | (error (let ((signal-data (cadr var))) | |
2311 | (cond (t (magit-bug-report signal-data)))))))))) | |
2308 | (condition-case var | |
2309 | (vc-find-file-hook) | |
2310 | (error (let ((signal-data (cadr var))) | |
2311 | (cond (t (magit-bug-report signal-data)))))))))) | |
2312 | 2312 | |
2313 | 2313 | (defvar magit-refresh-needing-buffers nil) |
2314 | 2314 | (defvar magit-refresh-pending nil) |
2317 | 2317 | (if magit-refresh-pending |
2318 | 2318 | (funcall func) |
2319 | 2319 | (let* ((dir default-directory) |
2320 | (status-buffer (magit-find-status-buffer dir)) | |
2321 | (magit-refresh-needing-buffers nil) | |
2322 | (magit-refresh-pending t)) | |
2320 | (status-buffer (magit-find-status-buffer dir)) | |
2321 | (magit-refresh-needing-buffers nil) | |
2322 | (magit-refresh-pending t)) | |
2323 | 2323 | (unwind-protect |
2324 | (funcall func) | |
2325 | (when magit-refresh-needing-buffers | |
2326 | (magit-revert-buffers dir) | |
2327 | (dolist (b (adjoin status-buffer | |
2328 | magit-refresh-needing-buffers)) | |
2329 | (magit-refresh-buffer b))))))) | |
2324 | (funcall func) | |
2325 | (when magit-refresh-needing-buffers | |
2326 | (magit-revert-buffers dir) | |
2327 | (dolist (b (adjoin status-buffer | |
2328 | magit-refresh-needing-buffers)) | |
2329 | (magit-refresh-buffer b))))))) | |
2330 | 2330 | |
2331 | 2331 | (defun magit-need-refresh (&optional buffer) |
2332 | 2332 | "Mark BUFFER as needing to be refreshed. If BUFFER is nil, use the |
2353 | 2353 | (defun magit-wash-untracked-file () |
2354 | 2354 | (if (looking-at "^? \\(.*\\)$") |
2355 | 2355 | (let ((file (match-string-no-properties 1))) |
2356 | (delete-region (point) (+ (line-end-position) 1)) | |
2357 | (magit-with-section file 'file | |
2358 | (magit-set-section-info file) | |
2359 | (insert "\t" file "\n")) | |
2360 | t) | |
2356 | (delete-region (point) (+ (line-end-position) 1)) | |
2357 | (magit-with-section file 'file | |
2358 | (magit-set-section-info file) | |
2359 | (insert "\t" file "\n")) | |
2360 | t) | |
2361 | 2361 | nil)) |
2362 | 2362 | |
2363 | 2363 | (defun magit-wash-untracked-files () |
2374 | 2374 | (unless (string= (magit-get "status" "showUntrackedFiles") "no") |
2375 | 2375 | (apply 'magit-git-section |
2376 | 2376 | `(untracked |
2377 | "Untracked files:" | |
2378 | magit-wash-untracked-files | |
2379 | "ls-files" "--others" "-t" "--exclude-standard" | |
2380 | ,@(when magit-omit-untracked-dir-contents | |
2381 | '("--directory")))))) | |
2377 | "Untracked files:" | |
2378 | magit-wash-untracked-files | |
2379 | "ls-files" "--others" "-t" "--exclude-standard" | |
2380 | ,@(when magit-omit-untracked-dir-contents | |
2381 | '("--directory")))))) | |
2382 | 2382 | |
2383 | 2383 | ;;; Diffs and Hunks |
2384 | 2384 | |
2407 | 2407 | |
2408 | 2408 | (defun magit-diff-line-file () |
2409 | 2409 | (cond ((looking-at "^diff --git ./\\(.*\\) ./\\(.*\\)$") |
2410 | (match-string-no-properties 2)) | |
2411 | ((looking-at "^diff --cc +\\(.*\\)$") | |
2412 | (match-string-no-properties 1)) | |
2413 | (t | |
2414 | nil))) | |
2410 | (match-string-no-properties 2)) | |
2411 | ((looking-at "^diff --cc +\\(.*\\)$") | |
2412 | (match-string-no-properties 1)) | |
2413 | (t | |
2414 | nil))) | |
2415 | 2415 | |
2416 | 2416 | (defun magit-wash-diffs () |
2417 | 2417 | (magit-wash-sequence #'magit-wash-diff-or-other-file)) |
2423 | 2423 | (defun magit-wash-other-file () |
2424 | 2424 | (if (looking-at "^? \\(.*\\)$") |
2425 | 2425 | (let ((file (match-string-no-properties 1))) |
2426 | (delete-region (point) (+ (line-end-position) 1)) | |
2427 | (magit-with-section file 'file | |
2428 | (magit-set-section-info file) | |
2429 | (insert "\tNew " file "\n")) | |
2430 | t) | |
2426 | (delete-region (point) (+ (line-end-position) 1)) | |
2427 | (magit-with-section file 'file | |
2428 | (magit-set-section-info file) | |
2429 | (insert "\tNew " file "\n")) | |
2430 | t) | |
2431 | 2431 | nil)) |
2432 | 2432 | |
2433 | 2433 | (defvar magit-hide-diffs nil) |
2436 | 2436 | |
2437 | 2437 | (defun magit-insert-diff-title (status file file2) |
2438 | 2438 | (let ((status-text (case status |
2439 | ((unmerged) | |
2440 | (format "Unmerged %s" file)) | |
2441 | ((new) | |
2442 | (format "New %s" file)) | |
2443 | ((deleted) | |
2444 | (format "Deleted %s" file)) | |
2445 | ((renamed) | |
2446 | (format "Renamed %s (from %s)" | |
2447 | file file2)) | |
2448 | ((modified) | |
2449 | (format "Modified %s" file)) | |
2450 | ((typechange) | |
2451 | (format "Typechange %s" file)) | |
2452 | (t | |
2453 | (format "? %s" file))))) | |
2439 | ((unmerged) | |
2440 | (format "Unmerged %s" file)) | |
2441 | ((new) | |
2442 | (format "New %s" file)) | |
2443 | ((deleted) | |
2444 | (format "Deleted %s" file)) | |
2445 | ((renamed) | |
2446 | (format "Renamed %s (from %s)" | |
2447 | file file2)) | |
2448 | ((modified) | |
2449 | (format "Modified %s" file)) | |
2450 | ((typechange) | |
2451 | (format "Typechange %s" file)) | |
2452 | (t | |
2453 | (format "? %s" file))))) | |
2454 | 2454 | (insert (make-string magit-indentation-level ?\t) status-text "\n"))) |
2455 | 2455 | |
2456 | 2456 | (defvar magit-current-diff-range nil |
2477 | 2477 | |
2478 | 2478 | (defun magit-wash-diff-section () |
2479 | 2479 | (cond ((looking-at "^\\* Unmerged path \\(.*\\)") |
2480 | (let ((file (match-string-no-properties 1))) | |
2481 | (delete-region (point) (line-end-position)) | |
2482 | (insert "\tUnmerged " file "\n") | |
2483 | (magit-set-section-info (list 'unmerged file nil)) | |
2484 | t)) | |
2485 | ((looking-at "^diff") | |
2486 | (let ((file (magit-diff-line-file)) | |
2487 | (end (save-excursion | |
2488 | (forward-line) ;; skip over "diff" line | |
2489 | (if (search-forward-regexp "^diff\\|^@@" nil t) | |
2490 | (goto-char (match-beginning 0)) | |
2491 | (goto-char (point-max))) | |
2492 | (point-marker)))) | |
2493 | (let* ((status (cond | |
2494 | ((looking-at "^diff --cc") | |
2495 | 'unmerged) | |
2496 | ((save-excursion | |
2497 | (search-forward-regexp "^new file" end t)) | |
2498 | 'new) | |
2499 | ((save-excursion | |
2500 | (search-forward-regexp "^deleted" end t)) | |
2501 | 'deleted) | |
2502 | ((save-excursion | |
2503 | (search-forward-regexp "^rename" end t)) | |
2504 | 'renamed) | |
2505 | (t | |
2506 | 'modified))) | |
2507 | (file2 (cond | |
2508 | ((save-excursion | |
2509 | (search-forward-regexp "^rename from \\(.*\\)" | |
2510 | end t)) | |
2511 | (match-string-no-properties 1))))) | |
2480 | (let ((file (match-string-no-properties 1))) | |
2481 | (delete-region (point) (line-end-position)) | |
2482 | (insert "\tUnmerged " file "\n") | |
2483 | (magit-set-section-info (list 'unmerged file nil)) | |
2484 | t)) | |
2485 | ((looking-at "^diff") | |
2486 | (let ((file (magit-diff-line-file)) | |
2487 | (end (save-excursion | |
2488 | (forward-line) ;; skip over "diff" line | |
2489 | (if (search-forward-regexp "^diff\\|^@@" nil t) | |
2490 | (goto-char (match-beginning 0)) | |
2491 | (goto-char (point-max))) | |
2492 | (point-marker)))) | |
2493 | (let* ((status (cond | |
2494 | ((looking-at "^diff --cc") | |
2495 | 'unmerged) | |
2496 | ((save-excursion | |
2497 | (search-forward-regexp "^new file" end t)) | |
2498 | 'new) | |
2499 | ((save-excursion | |
2500 | (search-forward-regexp "^deleted" end t)) | |
2501 | 'deleted) | |
2502 | ((save-excursion | |
2503 | (search-forward-regexp "^rename" end t)) | |
2504 | 'renamed) | |
2505 | (t | |
2506 | 'modified))) | |
2507 | (file2 (cond | |
2508 | ((save-excursion | |
2509 | (search-forward-regexp "^rename from \\(.*\\)" | |
2510 | end t)) | |
2511 | (match-string-no-properties 1))))) | |
2512 | 2512 | (magit-set-section-info (list status |
2513 | 2513 | file |
2514 | 2514 | (or file2 file) |
2515 | 2515 | magit-current-diff-range)) |
2516 | (magit-insert-diff-title status file file2) | |
2516 | (magit-insert-diff-title status file file2) | |
2517 | 2517 | (when (search-forward-regexp "\\(--- \\(.*\\)\n\\+\\+\\+ \\(.*\\)\n\\)" () t) |
2518 | 2518 | (when (match-string 1) |
2519 | 2519 | (add-text-properties (match-beginning 1) (match-end 1) |
2522 | 2522 | '(face magit-diff-file-header)) |
2523 | 2523 | (add-text-properties (match-beginning 3) (match-end 3) |
2524 | 2524 | '(face magit-diff-file-header)))) |
2525 | (goto-char end) | |
2526 | (let ((magit-section-hidden-default nil)) | |
2527 | (magit-wash-sequence #'magit-wash-hunk)))) | |
2528 | t) | |
2529 | (t | |
2530 | nil))) | |
2525 | (goto-char end) | |
2526 | (let ((magit-section-hidden-default nil)) | |
2527 | (magit-wash-sequence #'magit-wash-hunk)))) | |
2528 | t) | |
2529 | (t | |
2530 | nil))) | |
2531 | 2531 | |
2532 | 2532 | (defun magit-wash-diff () |
2533 | 2533 | (let ((magit-section-hidden-default magit-hide-diffs)) |
2548 | 2548 | |
2549 | 2549 | (defun magit-wash-hunk () |
2550 | 2550 | (cond ((looking-at "\\(^@+\\)[^@]*@+.*") |
2551 | (let ((n-columns (1- (length (match-string 1)))) | |
2552 | (head (match-string 0))) | |
2553 | (magit-with-section head 'hunk | |
2554 | (add-text-properties (match-beginning 0) (match-end 0) | |
2555 | '(face magit-diff-hunk-header)) | |
2556 | (forward-line) | |
2557 | (while (not (or (eobp) | |
2558 | (looking-at "^diff\\|^@@"))) | |
2551 | (let ((n-columns (1- (length (match-string 1)))) | |
2552 | (head (match-string 0))) | |
2553 | (magit-with-section head 'hunk | |
2554 | (add-text-properties (match-beginning 0) (match-end 0) | |
2555 | '(face magit-diff-hunk-header)) | |
2556 | (forward-line) | |
2557 | (while (not (or (eobp) | |
2558 | (looking-at "^diff\\|^@@"))) | |
2559 | 2559 | (magit-highlight-line-whitespace) |
2560 | (let ((prefix (buffer-substring-no-properties | |
2561 | (point) (min (+ (point) n-columns) (point-max))))) | |
2562 | (cond ((string-match "\\+" prefix) | |
2563 | (magit-put-line-property 'face 'magit-diff-add)) | |
2564 | ((string-match "-" prefix) | |
2565 | (magit-put-line-property 'face 'magit-diff-del)) | |
2566 | (t | |
2567 | (magit-put-line-property 'face 'magit-diff-none)))) | |
2568 | (forward-line)))) | |
2569 | t) | |
2570 | (t | |
2571 | nil))) | |
2560 | (let ((prefix (buffer-substring-no-properties | |
2561 | (point) (min (+ (point) n-columns) (point-max))))) | |
2562 | (cond ((string-match "\\+" prefix) | |
2563 | (magit-put-line-property 'face 'magit-diff-add)) | |
2564 | ((string-match "-" prefix) | |
2565 | (magit-put-line-property 'face 'magit-diff-del)) | |
2566 | (t | |
2567 | (magit-put-line-property 'face 'magit-diff-none)))) | |
2568 | (forward-line)))) | |
2569 | t) | |
2570 | (t | |
2571 | nil))) | |
2572 | 2572 | |
2573 | 2573 | (defvar magit-diff-options nil) |
2574 | 2574 | |
2575 | 2575 | (defun magit-insert-diff (file status) |
2576 | 2576 | (let ((cmd magit-git-executable) |
2577 | (args (append (list "diff") | |
2578 | (list (magit-diff-U-arg)) | |
2579 | magit-diff-options | |
2580 | (list "--" file)))) | |
2577 | (args (append (list "diff") | |
2578 | (list (magit-diff-U-arg)) | |
2579 | magit-diff-options | |
2580 | (list "--" file)))) | |
2581 | 2581 | (let ((p (point))) |
2582 | 2582 | (magit-git-insert args) |
2583 | 2583 | (if (not (eq (char-before) ?\n)) |
2584 | (insert "\n")) | |
2584 | (insert "\n")) | |
2585 | 2585 | (save-restriction |
2586 | (narrow-to-region p (point)) | |
2587 | (goto-char p) | |
2586 | (narrow-to-region p (point)) | |
2587 | (goto-char p) | |
2588 | 2588 | (cond |
2589 | 2589 | ((eq status 'typechange) |
2590 | 2590 | (magit-insert-diff-title status file file) |
2591 | 2591 | (magit-wash-typechange-section file)) |
2592 | 2592 | (t |
2593 | 2593 | (magit-wash-diff-section))) |
2594 | (goto-char (point-max)))))) | |
2594 | (goto-char (point-max)))))) | |
2595 | 2595 | |
2596 | 2596 | (defvar magit-last-raw-diff nil) |
2597 | 2597 | (defvar magit-ignore-unmerged-raw-diffs nil) |
2604 | 2604 | (if (looking-at |
2605 | 2605 | ":\\([0-7]+\\) \\([0-7]+\\) [0-9a-f]+ [0-9a-f]+ \\(.\\)[0-9]*\t\\([^\t\n]+\\)$") |
2606 | 2606 | (let ((old-perm (match-string-no-properties 1)) |
2607 | (new-perm (match-string-no-properties 2)) | |
2608 | (status (case (string-to-char (match-string-no-properties 3)) | |
2609 | (?A 'new) | |
2610 | (?D 'deleted) | |
2611 | (?M 'modified) | |
2612 | (?U 'unmerged) | |
2613 | (?T 'typechange) | |
2614 | (t nil))) | |
2615 | (file (match-string-no-properties 4))) | |
2616 | ;; If this is for the same file as the last diff, ignore it. | |
2617 | ;; Unmerged files seem to get two entries. | |
2618 | ;; We also ignore unmerged files when told so. | |
2619 | (if (or (equal file magit-last-raw-diff) | |
2620 | (and magit-ignore-unmerged-raw-diffs (eq status 'unmerged))) | |
2621 | (delete-region (point) (+ (line-end-position) 1)) | |
2622 | (setq magit-last-raw-diff file) | |
2623 | ;; The 'diff' section that is created here will not work with | |
2624 | ;; magit-insert-diff-item-patch etc when we leave it empty. | |
2625 | ;; Luckily, raw diffs are only produced for staged and | |
2626 | ;; unstaged changes, and we never call | |
2627 | ;; magit-insert-diff-item-patch on them. This is a bit | |
2628 | ;; brittle, of course. | |
2629 | (let ((magit-section-hidden-default magit-hide-diffs)) | |
2630 | (magit-with-section file 'diff | |
2631 | (delete-region (point) (+ (line-end-position) 1)) | |
2632 | (if (not (magit-section-hidden magit-top-section)) | |
2633 | (magit-insert-diff file status) | |
2634 | (magit-set-section-info (list status file nil)) | |
2635 | (magit-set-section-needs-refresh-on-show t) | |
2636 | (magit-insert-diff-title status file nil))))) | |
2637 | t) | |
2607 | (new-perm (match-string-no-properties 2)) | |
2608 | (status (case (string-to-char (match-string-no-properties 3)) | |
2609 | (?A 'new) | |
2610 | (?D 'deleted) | |
2611 | (?M 'modified) | |
2612 | (?U 'unmerged) | |
2613 | (?T 'typechange) | |
2614 | (t nil))) | |
2615 | (file (match-string-no-properties 4))) | |
2616 | ;; If this is for the same file as the last diff, ignore it. | |
2617 | ;; Unmerged files seem to get two entries. | |
2618 | ;; We also ignore unmerged files when told so. | |
2619 | (if (or (equal file magit-last-raw-diff) | |
2620 | (and magit-ignore-unmerged-raw-diffs (eq status 'unmerged))) | |
2621 | (delete-region (point) (+ (line-end-position) 1)) | |
2622 | (setq magit-last-raw-diff file) | |
2623 | ;; The 'diff' section that is created here will not work with | |
2624 | ;; magit-insert-diff-item-patch etc when we leave it empty. | |
2625 | ;; Luckily, raw diffs are only produced for staged and | |
2626 | ;; unstaged changes, and we never call | |
2627 | ;; magit-insert-diff-item-patch on them. This is a bit | |
2628 | ;; brittle, of course. | |
2629 | (let ((magit-section-hidden-default magit-hide-diffs)) | |
2630 | (magit-with-section file 'diff | |
2631 | (delete-region (point) (+ (line-end-position) 1)) | |
2632 | (if (not (magit-section-hidden magit-top-section)) | |
2633 | (magit-insert-diff file status) | |
2634 | (magit-set-section-info (list status file nil)) | |
2635 | (magit-set-section-needs-refresh-on-show t) | |
2636 | (magit-insert-diff-title status file nil))))) | |
2637 | t) | |
2638 | 2638 | nil)) |
2639 | 2639 | |
2640 | 2640 | (defun magit-hunk-item-diff (hunk) |
2641 | 2641 | (let ((diff (magit-section-parent hunk))) |
2642 | 2642 | (or (eq (magit-section-type diff) 'diff) |
2643 | (error "Huh? Parent of hunk not a diff")) | |
2643 | (error "Huh? Parent of hunk not a diff")) | |
2644 | 2644 | diff)) |
2645 | 2645 | |
2646 | 2646 | (defun magit-diff-item-insert-header (diff buf) |
2647 | 2647 | (let ((beg (save-excursion |
2648 | (goto-char (magit-section-beginning diff)) | |
2649 | (forward-line) | |
2650 | (point))) | |
2651 | (end (if (magit-section-children diff) | |
2652 | (magit-section-beginning (car (magit-section-children diff))) | |
2653 | (magit-section-end diff)))) | |
2648 | (goto-char (magit-section-beginning diff)) | |
2649 | (forward-line) | |
2650 | (point))) | |
2651 | (end (if (magit-section-children diff) | |
2652 | (magit-section-beginning (car (magit-section-children diff))) | |
2653 | (magit-section-end diff)))) | |
2654 | 2654 | (magit-insert-region beg end buf))) |
2655 | 2655 | |
2656 | 2656 | (defun magit-insert-diff-item-patch (diff buf) |
2657 | 2657 | (let ((beg (save-excursion |
2658 | (goto-char (magit-section-beginning diff)) | |
2659 | (forward-line) | |
2660 | (point))) | |
2661 | (end (magit-section-end diff))) | |
2658 | (goto-char (magit-section-beginning diff)) | |
2659 | (forward-line) | |
2660 | (point))) | |
2661 | (end (magit-section-end diff))) | |
2662 | 2662 | (magit-insert-region beg end buf))) |
2663 | 2663 | |
2664 | 2664 | (defun magit-insert-hunk-item-patch (hunk buf) |
2665 | 2665 | (magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf) |
2666 | 2666 | (magit-insert-region (magit-section-beginning hunk) (magit-section-end hunk) |
2667 | buf)) | |
2667 | buf)) | |
2668 | 2668 | |
2669 | 2669 | (defun magit-insert-hunk-item-region-patch (hunk reverse beg end buf) |
2670 | 2670 | (magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf) |
2674 | 2674 | (forward-line) |
2675 | 2675 | (let ((copy-op (if reverse "+" "-"))) |
2676 | 2676 | (while (< (point) (magit-section-end hunk)) |
2677 | (if (and (<= beg (point)) (< (point) end)) | |
2678 | (magit-insert-current-line buf) | |
2679 | (cond ((looking-at " ") | |
2680 | (magit-insert-current-line buf)) | |
2681 | ((looking-at copy-op) | |
2682 | (let ((text (buffer-substring-no-properties | |
2683 | (+ (point) 1) (line-beginning-position 2)))) | |
2684 | (with-current-buffer buf | |
2685 | (insert " " text)))))) | |
2686 | (forward-line)))) | |
2677 | (if (and (<= beg (point)) (< (point) end)) | |
2678 | (magit-insert-current-line buf) | |
2679 | (cond ((looking-at " ") | |
2680 | (magit-insert-current-line buf)) | |
2681 | ((looking-at copy-op) | |
2682 | (let ((text (buffer-substring-no-properties | |
2683 | (+ (point) 1) (line-beginning-position 2)))) | |
2684 | (with-current-buffer buf | |
2685 | (insert " " text)))))) | |
2686 | (forward-line)))) | |
2687 | 2687 | (with-current-buffer buf |
2688 | 2688 | (diff-fixup-modifs (point-min) (point-max)))) |
2689 | 2689 | |
2690 | 2690 | (defun magit-hunk-item-is-conflict-p (hunk) |
2691 | 2691 | ;;; XXX - Using the title is a bit too clever... |
2692 | 2692 | (string-match "^diff --cc" |
2693 | (magit-section-title (magit-hunk-item-diff hunk)))) | |
2693 | (magit-section-title (magit-hunk-item-diff hunk)))) | |
2694 | 2694 | |
2695 | 2695 | (defun magit-hunk-item-target-line (hunk) |
2696 | 2696 | (save-excursion |
2698 | 2698 | (let ((line (line-number-at-pos))) |
2699 | 2699 | (goto-char (magit-section-beginning hunk)) |
2700 | 2700 | (if (not (looking-at "@@+ .* \\+\\([0-9]+\\)\\(,[0-9]+\\)? @@+")) |
2701 | (error "Hunk header not found")) | |
2701 | (error "Hunk header not found")) | |
2702 | 2702 | (let ((target (string-to-number (match-string 1)))) |
2703 | (forward-line) | |
2704 | (while (< (line-number-at-pos) line) | |
2705 | ;; XXX - deal with combined diffs | |
2706 | (if (not (looking-at "-")) | |
2707 | (setq target (+ target 1))) | |
2708 | (forward-line)) | |
2709 | target)))) | |
2703 | (forward-line) | |
2704 | (while (< (line-number-at-pos) line) | |
2705 | ;; XXX - deal with combined diffs | |
2706 | (if (not (looking-at "-")) | |
2707 | (setq target (+ target 1))) | |
2708 | (forward-line)) | |
2709 | target)))) | |
2710 | 2710 | |
2711 | 2711 | (defun magit-show (commit filename &optional select prefix) |
2712 | 2712 | "Returns a buffer containing the contents of the file FILENAME, as stored in |
2737 | 2737 | (with-current-buffer buffer |
2738 | 2738 | (let ((tmpname (match-string 1 checkout-string))) |
2739 | 2739 | (magit-with-silent-modifications |
2740 | (insert-file-contents tmpname nil nil nil t)) | |
2740 | (insert-file-contents tmpname nil nil nil t)) | |
2741 | 2741 | (delete-file tmpname))))) |
2742 | 2742 | (t |
2743 | 2743 | (with-current-buffer buffer |
2756 | 2756 | |
2757 | 2757 | (defmacro with-magit-tmp-buffer (var &rest body) |
2758 | 2758 | (declare (indent 1) |
2759 | (debug (symbolp &rest form))) | |
2759 | (debug (symbolp &rest form))) | |
2760 | 2760 | `(let ((,var (generate-new-buffer magit-tmp-buffer-name))) |
2761 | 2761 | (unwind-protect |
2762 | (progn ,@body) | |
2762 | (progn ,@body) | |
2763 | 2763 | (kill-buffer ,var)))) |
2764 | 2764 | |
2765 | 2765 | (defun magit-apply-diff-item (diff &rest args) |
2768 | 2768 | (with-magit-tmp-buffer tmp |
2769 | 2769 | (magit-insert-diff-item-patch diff tmp) |
2770 | 2770 | (apply #'magit-run-git-with-input tmp |
2771 | "apply" (append args (list "-"))))) | |
2771 | "apply" (append args (list "-"))))) | |
2772 | 2772 | |
2773 | 2773 | (defun magit-apply-hunk-item* (hunk reverse &rest args) |
2774 | 2774 | (when (zerop magit-diff-context-lines) |
2775 | 2775 | (setq args (cons "--unidiff-zero" args))) |
2776 | 2776 | (with-magit-tmp-buffer tmp |
2777 | 2777 | (if (magit-use-region-p) |
2778 | (magit-insert-hunk-item-region-patch | |
2779 | hunk reverse (region-beginning) (region-end) tmp) | |
2780 | (magit-insert-hunk-item-patch hunk tmp)) | |
2778 | (magit-insert-hunk-item-region-patch | |
2779 | hunk reverse (region-beginning) (region-end) tmp) | |
2780 | (magit-insert-hunk-item-patch hunk tmp)) | |
2781 | 2781 | (apply #'magit-run-git-with-input tmp |
2782 | "apply" (append args (list "-"))))) | |
2782 | "apply" (append args (list "-"))))) | |
2783 | 2783 | |
2784 | 2784 | (defun magit-apply-hunk-item (hunk &rest args) |
2785 | 2785 | (apply #'magit-apply-hunk-item* hunk nil args)) |
2809 | 2809 | |
2810 | 2810 | ;;; Logs and Commits |
2811 | 2811 | |
2812 | ; Note: making this a plain defcustom would probably let users break | |
2813 | ; the parser too easily | |
2812 | ; Note: making this a plain defcustom would probably let users break | |
2813 | ; the parser too easily | |
2814 | 2814 | (defvar magit-git-log-options |
2815 | 2815 | '("--pretty=format:* %H %s")) |
2816 | ; --decorate=full otherwise some ref prefixes are stripped | |
2817 | ; '("--pretty=format:* %H%d %s" "--decorate=full")) | |
2818 | ||
2816 | ; --decorate=full otherwise some ref prefixes are stripped | |
2817 | ; '("--pretty=format:* %H%d %s" "--decorate=full")) | |
2819 | 2818 | |
2820 | 2819 | ;; |
2821 | 2820 | ;; Regexps for parsing ref names |
2829 | 2828 | |
2830 | 2829 | (defconst magit-ref-nonslash-re |
2831 | 2830 | (concat "\\(?:" |
2832 | ;; "no slash-separated component can begin with a dot ." (rule 1) | |
2833 | "[^" magit-ref-nonchars "./]" | |
2834 | ;; "cannot have two consecutive dots .. anywhere." (rule 3) | |
2835 | "\\.?" | |
2831 | ;; "no slash-separated component can begin with a dot ." (rule 1) | |
2832 | "[^" magit-ref-nonchars "./]" | |
2833 | ;; "cannot have two consecutive dots .. anywhere." (rule 3) | |
2834 | "\\.?" | |
2836 | 2835 | "\\)*") |
2837 | 2836 | "Regexp that matches the non-slash parts of a ref name. |
2838 | 2837 | |
2839 | 2838 | Evaluate (man \"git-check-ref-format\") for details") |
2840 | 2839 | |
2841 | 2840 | (defconst magit-refname-re |
2842 | (concat | |
2843 | "\\(?:HEAD\\|" | |
2844 | ||
2845 | "\\(?:tag: \\)?" | |
2846 | ||
2847 | ;; optional non-slash sequence at the beginning | |
2848 | magit-ref-nonslash-re | |
2849 | ||
2850 | ;; any number of slash-prefixed sequences | |
2851 | "\\(?:" | |
2852 | "/" | |
2853 | magit-ref-nonslash-re | |
2854 | "\\)*" | |
2855 | ||
2856 | "/" ;; "must contain at least one /." (rule 2) | |
2857 | magit-ref-nonslash-re | |
2858 | ||
2859 | ;; "cannot end with a slash / nor a dot .." (rule 5) | |
2860 | "[^" magit-ref-nonchars "./]" | |
2861 | ||
2862 | "\\)" | |
2863 | ) | |
2841 | (concat | |
2842 | "\\(?:HEAD\\|" | |
2843 | ||
2844 | "\\(?:tag: \\)?" | |
2845 | ||
2846 | ;; optional non-slash sequence at the beginning | |
2847 | magit-ref-nonslash-re | |
2848 | ||
2849 | ;; any number of slash-prefixed sequences | |
2850 | "\\(?:" | |
2851 | "/" | |
2852 | magit-ref-nonslash-re | |
2853 | "\\)*" | |
2854 | ||
2855 | "/" ;; "must contain at least one /." (rule 2) | |
2856 | magit-ref-nonslash-re | |
2857 | ||
2858 | ;; "cannot end with a slash / nor a dot .." (rule 5) | |
2859 | "[^" magit-ref-nonchars "./]" | |
2860 | ||
2861 | "\\)" | |
2862 | ) | |
2864 | 2863 | "Regexp that matches a git symbolic reference name. |
2865 | 2864 | |
2866 | 2865 | Evaluate (man \"git-check-ref-format\") for details") |
2870 | 2869 | "^\\([_\\*|/ -.]+\\)?" ; graph (1) |
2871 | 2870 | "\\(?:commit \\)?" ; this happens in long mode |
2872 | 2871 | "\\(?:" |
2873 | "\\([0-9a-fA-F]\\{40\\}\\)" ; sha1 (2) | |
2874 | ||
2875 | ||
2876 | "\\(?:" ; refs (3) | |
2877 | " " | |
2878 | "\\(" | |
2879 | "(" | |
2880 | magit-refname-re "\\(?:, " magit-refname-re "\\)*" | |
2881 | ")" | |
2882 | "\\)" | |
2883 | "\\)?" | |
2872 | "\\([0-9a-fA-F]\\{40\\}\\)" ; sha1 (2) | |
2873 | ||
2874 | "\\(?:" ; refs (3) | |
2875 | " " | |
2876 | "\\(" | |
2877 | "(" | |
2878 | magit-refname-re "\\(?:, " magit-refname-re "\\)*" | |
2879 | ")" | |
2880 | "\\)" | |
2881 | "\\)?" | |
2884 | 2882 | "\\)?" |
2885 | 2883 | |
2886 | 2884 | " ?\\(.*\\)$" ; msg (4) |
2981 | 2979 | (magit-with-section "longer" 'longer |
2982 | 2980 | (insert "type \"e\" to show more logs\n"))))))) |
2983 | 2981 | |
2984 | ||
2985 | 2982 | (defun magit-wash-log-line () |
2986 | 2983 | (beginning-of-line) |
2987 | 2984 | (let ((line-re magit-log-oneline-re)) |
2991 | 2988 | (sha1 (match-string 2)) |
2992 | 2989 | (msg (match-string 4)) |
2993 | 2990 | (refs (when (match-string 3) |
2994 | (delq nil | |
2995 | (mapcar | |
2996 | (lambda (s) | |
2997 | (and (not | |
2998 | (or (string= s "tag:") | |
2999 | (string= s "HEAD"))) ; as of 1.6.6 | |
3000 | s)) | |
3001 | (split-string (match-string 3) "[(), ]" t)))))) | |
2991 | (delq nil | |
2992 | (mapcar | |
2993 | (lambda (s) | |
2994 | (and (not | |
2995 | (or (string= s "tag:") | |
2996 | (string= s "HEAD"))) ; as of 1.6.6 | |
2997 | s)) | |
2998 | (split-string (match-string 3) "[(), ]" t)))))) | |
3002 | 2999 | (delete-region (point-at-bol) (point-at-eol)) |
3003 | 3000 | (insert (funcall magit-present-log-line-function chart sha1 refs msg)) |
3004 | 3001 | (goto-char (point-at-bol)) |
3086 | 3083 | (magit-configure-have-decorate) |
3087 | 3084 | (magit-create-buffer-sections |
3088 | 3085 | (apply #'magit-git-section nil nil |
3089 | 'magit-wash-commit | |
3090 | "log" | |
3086 | 'magit-wash-commit | |
3087 | "log" | |
3091 | 3088 | "--max-count=1" |
3092 | 3089 | "--pretty=medium" |
3093 | 3090 | `(,@(if magit-have-abbrev (list "--no-abbrev-commit")) |
3193 | 3190 | (defun magit-refresh-marked-commits-in-buffer () |
3194 | 3191 | (if (not magit-mark-overlay) |
3195 | 3192 | (let ((ov (make-overlay 1 1))) |
3196 | (overlay-put ov 'face 'magit-item-mark) | |
3197 | (setq magit-mark-overlay ov))) | |
3193 | (overlay-put ov 'face 'magit-item-mark) | |
3194 | (setq magit-mark-overlay ov))) | |
3198 | 3195 | (delete-overlay magit-mark-overlay) |
3199 | 3196 | (magit-for-all-sections |
3200 | 3197 | (lambda (section) |
3201 | 3198 | (when (and (eq (magit-section-type section) 'commit) |
3202 | (equal (magit-section-info section) | |
3203 | magit-marked-commit)) | |
3199 | (equal (magit-section-info section) | |
3200 | magit-marked-commit)) | |
3204 | 3201 | (move-overlay magit-mark-overlay |
3205 | (magit-section-beginning section) | |
3206 | (magit-section-end section) | |
3207 | (current-buffer)))))) | |
3202 | (magit-section-beginning section) | |
3203 | (magit-section-end section) | |
3204 | (current-buffer)))))) | |
3208 | 3205 | |
3209 | 3206 | (defun magit-set-marked-commit (commit) |
3210 | 3207 | (setq magit-marked-commit commit) |
3243 | 3240 | (let ((merge (magit-get "branch" local-branch "merge"))) |
3244 | 3241 | (save-match-data |
3245 | 3242 | (if (and merge (string-match "^refs/heads/\\(.+\\)" merge)) |
3246 | (concat (if prepend-remote-name | |
3243 | (concat (if prepend-remote-name | |
3247 | 3244 | (concat "remotes/" |
3248 | 3245 | (magit-get "branch" local-branch "remote") |
3249 | 3246 | "/")) |
3257 | 3254 | (cond |
3258 | 3255 | ((string= "." remote) |
3259 | 3256 | (format "branch %s" |
3260 | (propertize remote-branch 'face 'magit-branch))) | |
3257 | (propertize remote-branch 'face 'magit-branch))) | |
3261 | 3258 | (remote |
3262 | (concat | |
3263 | (propertize remote-branch 'face 'magit-branch) | |
3264 | " @ " | |
3265 | remote | |
3266 | " (" | |
3267 | (magit-get "remote" remote "url") | |
3268 | ")")) | |
3259 | (concat | |
3260 | (propertize remote-branch 'face 'magit-branch) | |
3261 | " @ " | |
3262 | remote | |
3263 | " (" | |
3264 | (magit-get "remote" remote "url") | |
3265 | ")")) | |
3269 | 3266 | (t |
3270 | 3267 | (run-hook-with-args-until-success 'magit-remote-string-hook)))) |
3271 | 3268 | |
3275 | 3272 | (magit-create-buffer-sections |
3276 | 3273 | (magit-with-section 'status nil |
3277 | 3274 | (let* ((branch (magit-get-current-branch)) |
3278 | (remote (and branch (magit-get "branch" branch "remote"))) | |
3279 | (remote-branch (or (and branch (magit-remote-branch-for branch)) branch)) | |
3280 | (remote-string (magit-remote-string remote remote-branch)) | |
3281 | (head (magit-git-string | |
3282 | "log" "--max-count=1" "--abbrev-commit" "--pretty=oneline")) | |
3283 | (no-commit (not head))) | |
3284 | (when remote-string | |
3285 | (insert "Remote: " remote-string "\n")) | |
3286 | (insert (format "Local: %s %s\n" | |
3287 | (propertize (magit--bisect-info-for-status branch) | |
3288 | 'face 'magit-branch) | |
3289 | (abbreviate-file-name default-directory))) | |
3290 | (insert (format "Head: %s\n" | |
3291 | (if no-commit "nothing commited (yet)" head))) | |
3292 | (let ((merge-heads (magit-file-lines ".git/MERGE_HEAD"))) | |
3293 | (if merge-heads | |
3294 | (insert (format "Merging: %s\n" | |
3295 | (mapconcat 'identity | |
3275 | (remote (and branch (magit-get "branch" branch "remote"))) | |
3276 | (remote-branch (or (and branch (magit-remote-branch-for branch)) branch)) | |
3277 | (remote-string (magit-remote-string remote remote-branch)) | |
3278 | (head (magit-git-string | |
3279 | "log" "--max-count=1" "--abbrev-commit" "--pretty=oneline")) | |
3280 | (no-commit (not head))) | |
3281 | (when remote-string | |
3282 | (insert "Remote: " remote-string "\n")) | |
3283 | (insert (format "Local: %s %s\n" | |
3284 | (propertize (magit--bisect-info-for-status branch) | |
3285 | 'face 'magit-branch) | |
3286 | (abbreviate-file-name default-directory))) | |
3287 | (insert (format "Head: %s\n" | |
3288 | (if no-commit "nothing commited (yet)" head))) | |
3289 | (let ((merge-heads (magit-file-lines ".git/MERGE_HEAD"))) | |
3290 | (if merge-heads | |
3291 | (insert (format "Merging: %s\n" | |
3292 | (mapconcat 'identity | |
3296 | 3293 | (mapcar 'magit-name-rev merge-heads) |
3297 | 3294 | ", "))))) |
3298 | (let ((rebase (magit-rebase-info))) | |
3299 | (if rebase | |
3300 | (insert (apply 'format "Rebasing: onto %s (%s of %s); Press \"R\" to Abort, Skip, or Continue\n" rebase)))) | |
3301 | (insert "\n") | |
3302 | (magit-git-exit-code "update-index" "--refresh") | |
3303 | (magit-insert-stashes) | |
3295 | (let ((rebase (magit-rebase-info))) | |
3296 | (if rebase | |
3297 | (insert (apply 'format "Rebasing: onto %s (%s of %s); Press \"R\" to Abort, Skip, or Continue\n" rebase)))) | |
3298 | (insert "\n") | |
3299 | (magit-git-exit-code "update-index" "--refresh") | |
3300 | (magit-insert-stashes) | |
3304 | 3301 | (magit-insert-untracked-files) |
3305 | (magit-insert-pending-changes) | |
3306 | (magit-insert-pending-commits) | |
3307 | (magit-insert-unpulled-commits remote remote-branch) | |
3308 | (let ((staged (or no-commit (magit-anything-staged-p)))) | |
3309 | (magit-insert-unstaged-changes | |
3310 | (if staged "Unstaged changes:" "Changes:")) | |
3311 | (magit-insert-staged-changes staged no-commit)) | |
3312 | (magit-insert-unpushed-commits remote remote-branch) | |
3313 | (run-hooks 'magit-refresh-status-hook))))) | |
3302 | (magit-insert-pending-changes) | |
3303 | (magit-insert-pending-commits) | |
3304 | (magit-insert-unpulled-commits remote remote-branch) | |
3305 | (let ((staged (or no-commit (magit-anything-staged-p)))) | |
3306 | (magit-insert-unstaged-changes | |
3307 | (if staged "Unstaged changes:" "Changes:")) | |
3308 | (magit-insert-staged-changes staged no-commit)) | |
3309 | (magit-insert-unpushed-commits remote remote-branch) | |
3310 | (run-hooks 'magit-refresh-status-hook))))) | |
3314 | 3311 | |
3315 | 3312 | (defun magit-init (dir) |
3316 | 3313 | "Initialize git repository in the DIR directory." |
3317 | 3314 | (interactive (list (read-directory-name "Directory for Git repository: "))) |
3318 | 3315 | (let ((topdir (magit-get-top-dir dir))) |
3319 | 3316 | (when (or (not topdir) |
3320 | (yes-or-no-p | |
3321 | (format | |
3322 | (if (string-equal topdir (expand-file-name dir)) | |
3323 | "There is already a Git repository in %s. Reinitialize? " | |
3324 | "There is a Git repository in %s. Create another in %s? ") | |
3325 | topdir dir))) | |
3317 | (yes-or-no-p | |
3318 | (format | |
3319 | (if (string-equal topdir (expand-file-name dir)) | |
3320 | "There is already a Git repository in %s. Reinitialize? " | |
3321 | "There is a Git repository in %s. Create another in %s? ") | |
3322 | topdir dir))) | |
3326 | 3323 | (unless (file-directory-p dir) |
3327 | (and (y-or-n-p (format "Directory %s does not exists. Create it? " dir)) | |
3328 | (make-directory dir))) | |
3324 | (and (y-or-n-p (format "Directory %s does not exists. Create it? " dir)) | |
3325 | (make-directory dir))) | |
3329 | 3326 | (let ((default-directory dir)) |
3330 | (magit-run* (list magit-git-executable "init")))))) | |
3327 | (magit-run* (list magit-git-executable "init")))))) | |
3331 | 3328 | |
3332 | 3329 | (define-derived-mode magit-status-mode magit-mode "Magit" |
3333 | "Mode for looking at git status. | |
3330 | "Mode for looking at git status. | |
3334 | 3331 | |
3335 | 3332 | \\{magit-status-mode-map}" |
3336 | 3333 | :group 'magit) |
3360 | 3357 | predicate-function) |
3361 | 3358 | (when msg |
3362 | 3359 | (message msg))))) |
3363 | ||
3364 | 3360 | |
3365 | 3361 | (defun magit-save-buffers-predicate-all () |
3366 | 3362 | "Prompt to save all buffers with unsaved changes" |
3393 | 3389 | (let ((topdir (magit-get-top-dir dir))) |
3394 | 3390 | (unless topdir |
3395 | 3391 | (when (y-or-n-p (format "There is no Git repository in %S. Create one? " |
3396 | dir)) | |
3397 | (magit-init dir) | |
3398 | (setq topdir (magit-get-top-dir dir)))) | |
3392 | dir)) | |
3393 | (magit-init dir) | |
3394 | (setq topdir (magit-get-top-dir dir)))) | |
3399 | 3395 | (when topdir |
3400 | 3396 | (let ((buf (or (magit-find-status-buffer topdir) |
3401 | (generate-new-buffer | |
3402 | (concat "*magit: " | |
3403 | (file-name-nondirectory | |
3404 | (directory-file-name topdir)) "*"))))) | |
3397 | (generate-new-buffer | |
3398 | (concat "*magit: " | |
3399 | (file-name-nondirectory | |
3400 | (directory-file-name topdir)) "*"))))) | |
3405 | 3401 | (funcall magit-status-buffer-switch-function buf) |
3406 | 3402 | (magit-mode-init topdir 'magit-status-mode #'magit-refresh-status))))) |
3407 | 3403 | |
3458 | 3454 | (magit-apply-hunk-item-reverse item "--cached")) |
3459 | 3455 | ((staged diff) |
3460 | 3456 | (if (eq (car info) 'unmerged) |
3461 | (error "Can't unstage an unmerged file. Resolve it first")) | |
3457 | (error "Can't unstage an unmerged file. Resolve it first")) | |
3462 | 3458 | (if (magit-no-commit-p) |
3463 | (magit-run-git "rm" "--cached" "--" (magit-diff-item-file item)) | |
3464 | (magit-run-git "reset" "-q" "HEAD" "--" (magit-diff-item-file item)))) | |
3459 | (magit-run-git "rm" "--cached" "--" (magit-diff-item-file item)) | |
3460 | (magit-run-git "reset" "-q" "HEAD" "--" (magit-diff-item-file item)))) | |
3465 | 3461 | ((unstaged *) |
3466 | 3462 | (error "Already unstaged")) |
3467 | 3463 | ((diff diff) |
3553 | 3549 | magit-uninteresting-refs))))) |
3554 | 3550 | (if revision |
3555 | 3551 | (when (not (magit-maybe-create-local-tracking-branch revision)) |
3556 | (magit-save-some-buffers) | |
3557 | (magit-run-git "checkout" (magit-rev-to-git revision)) | |
3558 | (magit-update-vc-modeline default-directory)))) | |
3552 | (magit-save-some-buffers) | |
3553 | (magit-run-git "checkout" (magit-rev-to-git revision)) | |
3554 | (magit-update-vc-modeline default-directory)))) | |
3559 | 3555 | |
3560 | 3556 | (defun magit-read-create-branch-args () |
3561 | 3557 | (let* ((cur-branch (magit-get-current-branch)) |
3562 | (cur-point (magit-default-rev)) | |
3563 | (branch (read-string "Create branch: ")) | |
3564 | (parent (magit-read-rev "Parent" | |
3565 | (cond | |
3566 | ((eq magit-create-branch-behaviour 'at-point) cur-point) | |
3567 | ((eq magit-create-branch-behaviour 'at-head) cur-branch) | |
3568 | (t cur-branch))))) | |
3558 | (cur-point (magit-default-rev)) | |
3559 | (branch (read-string "Create branch: ")) | |
3560 | (parent (magit-read-rev "Parent" | |
3561 | (cond | |
3562 | ((eq magit-create-branch-behaviour 'at-point) cur-point) | |
3563 | ((eq magit-create-branch-behaviour 'at-head) cur-branch) | |
3564 | (t cur-branch))))) | |
3569 | 3565 | (list branch parent))) |
3570 | 3566 | |
3571 | 3567 | (magit-define-command create-branch (branch parent) |
3574 | 3570 | \('git checkout -b BRANCH REVISION')." |
3575 | 3571 | (interactive (magit-read-create-branch-args)) |
3576 | 3572 | (when (and branch (not (string= branch "")) |
3577 | parent) | |
3573 | parent) | |
3578 | 3574 | (magit-save-some-buffers) |
3579 | 3575 | (magit-run-git "checkout" "-b" |
3580 | branch | |
3581 | (append | |
3582 | magit-custom-options | |
3583 | (magit-rev-to-git parent))) | |
3576 | branch | |
3577 | (append | |
3578 | magit-custom-options | |
3579 | (magit-rev-to-git parent))) | |
3584 | 3580 | (magit-update-vc-modeline default-directory))) |
3585 | 3581 | |
3586 | 3582 | (defun magit-delete-branch (branch) |
3590 | 3586 | (interactive (list (magit-read-rev "Branch to delete" (magit-default-rev)))) |
3591 | 3587 | (when (and branch (string= branch (magit-get-current-branch))) |
3592 | 3588 | (if (y-or-n-p "Cannot delete current branch. Switch to master first? ") |
3593 | (magit-checkout "master") | |
3589 | (magit-checkout "master") | |
3594 | 3590 | (setq branch nil))) |
3595 | 3591 | (when branch |
3596 | 3592 | (magit-run-git "branch" "-d" (append magit-custom-options |
3597 | (magit-rev-to-git branch))))) | |
3593 | (magit-rev-to-git branch))))) | |
3598 | 3594 | |
3599 | 3595 | (defun magit-delete-branch-forced (branch) |
3600 | 3596 | "Asks for a branch and deletes it, irrespective of its merged status. |
3614 | 3610 | If the branch is the current one, offers to switch to `master' first. |
3615 | 3611 | \('git branch -m OLD NEW')." |
3616 | 3612 | (interactive (list (magit-read-rev "Old name" (magit-default-rev)) |
3617 | (magit-read-rev "New name" (magit-default-rev)))) | |
3613 | (magit-read-rev "New name" (magit-default-rev)))) | |
3618 | 3614 | (magit-run-git "branch" "-m" (magit-rev-to-git old) new)) |
3619 | 3615 | |
3620 | 3616 | ;;; Merging |
3677 | 3673 | (interactive) |
3678 | 3674 | (let ((info (magit-rebase-info))) |
3679 | 3675 | (if (not info) |
3680 | (let* ((current-branch (magit-get-current-branch)) | |
3676 | (let* ((current-branch (magit-get-current-branch)) | |
3681 | 3677 | (remote (when current-branch |
3682 | 3678 | (magit-get "branch" current-branch "remote"))) |
3683 | 3679 | (remote-branch (when remote |
3691 | 3687 | (cons (concat "refs/heads/" current-branch) |
3692 | 3688 | magit-uninteresting-refs) |
3693 | 3689 | magit-uninteresting-refs)))) |
3694 | (if rev | |
3695 | (magit-run-git "rebase" (magit-rev-to-git rev)))) | |
3690 | (if rev | |
3691 | (magit-run-git "rebase" (magit-rev-to-git rev)))) | |
3696 | 3692 | (let ((cursor-in-echo-area t) |
3697 | 3693 | (message-log-max nil)) |
3698 | 3694 | (message "Rebase in progress. [A]bort, [S]kip, or [C]ontinue? ") |
3714 | 3710 | and staging area are lost. |
3715 | 3711 | \('git reset [--soft|--hard] REVISION')." |
3716 | 3712 | (interactive (list (magit-read-rev (format "%s head to" |
3717 | (if current-prefix-arg | |
3718 | "Hard reset" | |
3719 | "Reset")) | |
3720 | (or (magit-default-rev) | |
3721 | "HEAD^")) | |
3722 | current-prefix-arg)) | |
3713 | (if current-prefix-arg | |
3714 | "Hard reset" | |
3715 | "Reset")) | |
3716 | (or (magit-default-rev) | |
3717 | "HEAD^")) | |
3718 | current-prefix-arg)) | |
3723 | 3719 | (when revision |
3724 | 3720 | (magit-run-git "reset" (if hard "--hard" "--soft") |
3725 | (magit-rev-to-git revision)) | |
3721 | (magit-rev-to-git revision)) | |
3726 | 3722 | (magit-update-vc-modeline default-directory))) |
3727 | 3723 | |
3728 | 3724 | (magit-define-command reset-head-hard (revision) |
3730 | 3726 | Uncomitted changes in both working tree and staging area are lost. |
3731 | 3727 | \('git reset --hard REVISION')." |
3732 | 3728 | (interactive (list (magit-read-rev (format "Hard reset head to") |
3733 | (or (magit-default-rev) | |
3734 | "HEAD")))) | |
3729 | (or (magit-default-rev) | |
3730 | "HEAD")))) | |
3735 | 3731 | (magit-reset-head revision t)) |
3736 | 3732 | |
3737 | 3733 | (magit-define-command reset-working-tree (&optional include-untracked) |
3764 | 3760 | |
3765 | 3761 | (magit-define-inserter pending-commits () |
3766 | 3762 | (let* ((info (magit-read-rewrite-info)) |
3767 | (pending (cdr (assq 'pending info)))) | |
3763 | (pending (cdr (assq 'pending info)))) | |
3768 | 3764 | (when pending |
3769 | 3765 | (magit-with-section 'pending nil |
3770 | (insert (propertize "Pending commits:\n" | |
3771 | 'face 'magit-section-title)) | |
3772 | (dolist (p pending) | |
3773 | (let* ((commit (car p)) | |
3774 | (properties (cdr p)) | |
3775 | (used (plist-get properties 'used))) | |
3776 | (magit-with-section commit 'commit | |
3777 | (magit-set-section-info commit) | |
3778 | (insert (magit-git-string | |
3779 | "log" "--max-count=1" | |
3780 | (if used | |
3781 | "--pretty=format:. %s" | |
3782 | "--pretty=format:* %s") | |
3783 | commit "--") | |
3784 | "\n"))))) | |
3766 | (insert (propertize "Pending commits:\n" | |
3767 | 'face 'magit-section-title)) | |
3768 | (dolist (p pending) | |
3769 | (let* ((commit (car p)) | |
3770 | (properties (cdr p)) | |
3771 | (used (plist-get properties 'used))) | |
3772 | (magit-with-section commit 'commit | |
3773 | (magit-set-section-info commit) | |
3774 | (insert (magit-git-string | |
3775 | "log" "--max-count=1" | |
3776 | (if used | |
3777 | "--pretty=format:. %s" | |
3778 | "--pretty=format:* %s") | |
3779 | commit "--") | |
3780 | "\n"))))) | |
3785 | 3781 | (insert "\n")))) |
3786 | 3782 | |
3787 | 3783 | (defun magit-rewrite-set-commit-property (commit prop value) |
3788 | 3784 | (let* ((info (magit-read-rewrite-info)) |
3789 | (pending (cdr (assq 'pending info))) | |
3790 | (p (assoc commit pending))) | |
3785 | (pending (cdr (assq 'pending info))) | |
3786 | (p (assoc commit pending))) | |
3791 | 3787 | (when p |
3792 | 3788 | (setf (cdr p) (plist-put (cdr p) prop value)) |
3793 | 3789 | (magit-write-rewrite-info info) |
3807 | 3803 | |
3808 | 3804 | (magit-define-inserter pending-changes () |
3809 | 3805 | (let* ((info (magit-read-rewrite-info)) |
3810 | (orig (cadr (assq 'orig info)))) | |
3806 | (orig (cadr (assq 'orig info)))) | |
3811 | 3807 | (when orig |
3812 | 3808 | (let ((magit-hide-diffs t)) |
3813 | (magit-git-section 'pending-changes | |
3814 | "Pending changes" | |
3815 | 'magit-wash-diffs | |
3816 | "diff" (magit-diff-U-arg) "-R" orig))))) | |
3809 | (magit-git-section 'pending-changes | |
3810 | "Pending changes" | |
3811 | 'magit-wash-diffs | |
3812 | "diff" (magit-diff-U-arg) "-R" orig))))) | |
3817 | 3813 | |
3818 | 3814 | (defun magit-rewrite-start (from &optional onto) |
3819 | 3815 | (interactive (list (magit-read-rev "Rewrite from" (magit-default-rev)))) |
3833 | 3829 | (car (magit-commit-parents from)) |
3834 | 3830 | (error "Can't rewrite a parentless commit.")) |
3835 | 3831 | from)) |
3836 | (pending (magit-git-lines "rev-list" (concat base "..")))) | |
3832 | (pending (magit-git-lines "rev-list" (concat base "..")))) | |
3837 | 3833 | (magit-write-rewrite-info `((orig ,orig) |
3838 | (pending ,@(mapcar #'list pending)))) | |
3834 | (pending ,@(mapcar #'list pending)))) | |
3839 | 3835 | (magit-run-git "reset" "--hard" base))) |
3840 | 3836 | |
3841 | 3837 | (defun magit-rewrite-stop (&optional noconfirm) |
3842 | 3838 | (interactive) |
3843 | 3839 | (let* ((info (magit-read-rewrite-info))) |
3844 | 3840 | (or info |
3845 | (error "No rewrite in progress")) | |
3841 | (error "No rewrite in progress")) | |
3846 | 3842 | (when (or noconfirm |
3847 | (yes-or-no-p "Stop rewrite? ")) | |
3843 | (yes-or-no-p "Stop rewrite? ")) | |
3848 | 3844 | (magit-write-rewrite-info nil) |
3849 | 3845 | (magit-refresh)))) |
3850 | 3846 | |
3851 | 3847 | (defun magit-rewrite-abort () |
3852 | 3848 | (interactive) |
3853 | 3849 | (let* ((info (magit-read-rewrite-info)) |
3854 | (orig (cadr (assq 'orig info)))) | |
3850 | (orig (cadr (assq 'orig info)))) | |
3855 | 3851 | (or info |
3856 | (error "No rewrite in progress")) | |
3852 | (error "No rewrite in progress")) | |
3857 | 3853 | (or (magit-everything-clean-p) |
3858 | (error "You have uncommitted changes")) | |
3854 | (error "You have uncommitted changes")) | |
3859 | 3855 | (when (yes-or-no-p "Abort rewrite? ") |
3860 | 3856 | (magit-write-rewrite-info nil) |
3861 | 3857 | (magit-run-git "reset" "--hard" orig)))) |
3868 | 3864 | (defun magit-rewrite-finish-step (first-p) |
3869 | 3865 | (let ((info (magit-read-rewrite-info))) |
3870 | 3866 | (or info |
3871 | (error "No rewrite in progress")) | |
3867 | (error "No rewrite in progress")) | |
3872 | 3868 | (let* ((pending (cdr (assq 'pending info))) |
3873 | (first-unused | |
3874 | (let ((rpend (reverse pending))) | |
3875 | (while (and rpend (plist-get (cdr (car rpend)) 'used)) | |
3876 | (setq rpend (cdr rpend))) | |
3877 | (car rpend))) | |
3878 | (commit (car first-unused))) | |
3869 | (first-unused | |
3870 | (let ((rpend (reverse pending))) | |
3871 | (while (and rpend (plist-get (cdr (car rpend)) 'used)) | |
3872 | (setq rpend (cdr rpend))) | |
3873 | (car rpend))) | |
3874 | (commit (car first-unused))) | |
3879 | 3875 | (cond ((not first-unused) |
3880 | (magit-rewrite-stop t)) | |
3881 | ((magit-apply-commit commit t (not first-p)) | |
3882 | (magit-rewrite-set-commit-property commit 'used t) | |
3883 | (magit-rewrite-finish-step nil)))))) | |
3876 | (magit-rewrite-stop t)) | |
3877 | ((magit-apply-commit commit t (not first-p)) | |
3878 | (magit-rewrite-set-commit-property commit 'used t) | |
3879 | (magit-rewrite-finish-step nil)))))) | |
3884 | 3880 | |
3885 | 3881 | ;;; Updating, pull, and push |
3886 | 3882 | |
3906 | 3902 | "Run git pull against the current remote." |
3907 | 3903 | (interactive) |
3908 | 3904 | (let* ((branch (magit-get-current-branch)) |
3909 | (config-branch (and branch (magit-get "branch" branch "merge"))) | |
3910 | (merge-branch (or (and config-branch (not current-prefix-arg)) | |
3911 | (magit-read-rev (format "Pull from"))))) | |
3905 | (config-branch (and branch (magit-get "branch" branch "merge"))) | |
3906 | (merge-branch (or (and config-branch (not current-prefix-arg)) | |
3907 | (magit-read-rev (format "Pull from"))))) | |
3912 | 3908 | (if (and branch (not config-branch)) |
3913 | (magit-set merge-branch "branch" branch "merge")) | |
3909 | (magit-set merge-branch "branch" branch "merge")) | |
3914 | 3910 | (apply 'magit-run-git-async "pull" "-v" magit-custom-options))) |
3915 | 3911 | |
3916 | 3912 | (eval-when-compile (require 'eshell)) |
3925 | 3921 | "Perform arbitrary shell COMMAND." |
3926 | 3922 | (interactive "sCommand: ") |
3927 | 3923 | (let ((args (magit-parse-arguments command)) |
3928 | (magit-process-popup-time 0)) | |
3924 | (magit-process-popup-time 0)) | |
3929 | 3925 | (magit-run* args nil nil nil t))) |
3930 | 3926 | |
3931 | 3927 | (defun magit-git-command (command) |
3936 | 3932 | (interactive "sRun git like this: ") |
3937 | 3933 | (require 'pcomplete) |
3938 | 3934 | (let ((args (magit-parse-arguments command)) |
3939 | (magit-process-popup-time 0)) | |
3935 | (magit-process-popup-time 0)) | |
3940 | 3936 | (magit-with-refresh |
3941 | 3937 | (magit-run* (append (cons magit-git-executable |
3942 | 3938 | magit-git-standard-options) |
3951 | 3947 | (magit-define-command push () |
3952 | 3948 | (interactive) |
3953 | 3949 | (let* ((branch (or (magit-get-current-branch) |
3954 | (error "Don't push a detached head. That's gross"))) | |
3955 | (branch-remote (magit-get-remote branch)) | |
3956 | (push-remote (if (or current-prefix-arg | |
3957 | (not branch-remote)) | |
3958 | (magit-read-remote (format "Push %s to: " branch) | |
3959 | branch-remote) | |
3960 | branch-remote)) | |
3961 | (ref-branch (magit-get "branch" branch "merge"))) | |
3950 | (error "Don't push a detached head. That's gross"))) | |
3951 | (branch-remote (magit-get-remote branch)) | |
3952 | (push-remote (if (or current-prefix-arg | |
3953 | (not branch-remote)) | |
3954 | (magit-read-remote (format "Push %s to: " branch) | |
3955 | branch-remote) | |
3956 | branch-remote)) | |
3957 | (ref-branch (magit-get "branch" branch "merge"))) | |
3962 | 3958 | (if (and (not ref-branch) |
3963 | 3959 | (eq magit-set-upstream-on-push 'refuse)) |
3964 | 3960 | (error "Not pushing since no upstream has been set.") |
3982 | 3978 | (unless ref-branch |
3983 | 3979 | (magit-set (concat "refs/heads/" branch) "branch" branch "merge")))))) |
3984 | 3980 | |
3985 | ||
3986 | 3981 | ;;; Log edit mode |
3987 | 3982 | |
3988 | 3983 | (defvar magit-log-edit-buffer-name "*magit-edit-log*" |
4001 | 3996 | (define-key map (kbd "C-c C-k") 'magit-log-edit-cancel-log-message) |
4002 | 3997 | (define-key map (kbd "C-c C-]") 'magit-log-edit-cancel-log-message) |
4003 | 3998 | (define-key map (kbd "C-x C-s") (lambda () |
4004 | (interactive) | |
4005 | (message "Not saved. Use C-c C-c to finalize this commit message."))) | |
3999 | (interactive) | |
4000 | (message "Not saved. Use C-c C-c to finalize this commit message."))) | |
4006 | 4001 | map)) |
4007 | 4002 | |
4008 | 4003 | (defvar magit-pre-log-edit-window-configuration nil) |
4017 | 4012 | (goto-char (point-min)) |
4018 | 4013 | (goto-char (point-min)) |
4019 | 4014 | (if (re-search-forward "[ \t\n]*\\'" nil t) |
4020 | (replace-match "\n" nil nil)))) | |
4015 | (replace-match "\n" nil nil)))) | |
4021 | 4016 | |
4022 | 4017 | (defun magit-log-edit-append (str) |
4023 | 4018 | (with-current-buffer (get-buffer-create magit-log-edit-buffer-name) |
4028 | 4023 | |
4029 | 4024 | (defun magit-log-edit-get-fields () |
4030 | 4025 | (let ((buf (get-buffer magit-log-edit-buffer-name)) |
4031 | (result nil)) | |
4026 | (result nil)) | |
4032 | 4027 | (if buf |
4033 | (with-current-buffer buf | |
4034 | (goto-char (point-min)) | |
4028 | (with-current-buffer buf | |
4029 | (goto-char (point-min)) | |
4035 | 4030 | (while (looking-at "^\\([A-Za-z0-9-_]+\\): *\\(.+\\)?$") |
4036 | (setq result (acons (intern (downcase (match-string 1))) | |
4031 | (setq result (acons (intern (downcase (match-string 1))) | |
4037 | 4032 | (read (or (match-string 2) "nil")) |
4038 | result)) | |
4039 | (forward-line)) | |
4040 | (if (not (looking-at (regexp-quote magit-log-header-end))) | |
4041 | (setq result nil)))) | |
4033 | result)) | |
4034 | (forward-line)) | |
4035 | (if (not (looking-at (regexp-quote magit-log-header-end))) | |
4036 | (setq result nil)))) | |
4042 | 4037 | (nreverse result))) |
4043 | 4038 | |
4044 | 4039 | (defun magit-log-edit-set-fields (fields) |
4046 | 4041 | (with-current-buffer buf |
4047 | 4042 | (goto-char (point-min)) |
4048 | 4043 | (if (search-forward-regexp (format "^\\([A-Za-z0-9-_]+:.*\n\\)*%s" |
4049 | (regexp-quote magit-log-header-end)) | |
4050 | nil t) | |
4051 | (delete-region (match-beginning 0) (match-end 0))) | |
4044 | (regexp-quote magit-log-header-end)) | |
4045 | nil t) | |
4046 | (delete-region (match-beginning 0) (match-end 0))) | |
4052 | 4047 | (goto-char (point-min)) |
4053 | 4048 | (when fields |
4054 | (while fields | |
4049 | (while fields | |
4055 | 4050 | (insert (capitalize (symbol-name (caar fields))) ": " |
4056 | 4051 | (prin1-to-string (cdar fields)) "\n") |
4057 | (setq fields (cdr fields))) | |
4058 | (insert magit-log-header-end))))) | |
4052 | (setq fields (cdr fields))) | |
4053 | (insert magit-log-header-end))))) | |
4059 | 4054 | |
4060 | 4055 | (defun magit-log-edit-set-field (name value) |
4061 | 4056 | (let* ((fields (magit-log-edit-get-fields)) |
4062 | (cell (assq name fields))) | |
4057 | (cell (assq name fields))) | |
4063 | 4058 | (cond (cell |
4064 | (if value | |
4065 | (rplacd cell value) | |
4066 | (setq fields (delq cell fields)))) | |
4067 | (t | |
4068 | (if value | |
4069 | (setq fields (append fields (list (cons name value))))))) | |
4059 | (if value | |
4060 | (rplacd cell value) | |
4061 | (setq fields (delq cell fields)))) | |
4062 | (t | |
4063 | (if value | |
4064 | (setq fields (append fields (list (cons name value))))))) | |
4070 | 4065 | (magit-log-edit-set-fields fields))) |
4071 | 4066 | |
4072 | 4067 | (defun magit-log-edit-get-field (name) |
4080 | 4075 | toggled on. When it's toggled on for the first time, return |
4081 | 4076 | 'first." |
4082 | 4077 | (let* ((fields (magit-log-edit-get-fields)) |
4083 | (cell (assq name fields)) yesp) | |
4078 | (cell (assq name fields)) yesp) | |
4084 | 4079 | (if cell |
4085 | 4080 | (progn |
4086 | 4081 | (setq yesp (equal (cdr cell) "yes")) |
4098 | 4093 | Return nil if the input is toggled off, and its valud if it's |
4099 | 4094 | toggled on." |
4100 | 4095 | (let* ((fields (magit-log-edit-get-fields)) |
4101 | (cell (assq name fields)) | |
4096 | (cell (assq name fields)) | |
4102 | 4097 | result) |
4103 | 4098 | (if cell |
4104 | 4099 | (progn |
4127 | 4122 | |
4128 | 4123 | (defun magit-log-edit-push-to-comment-ring (comment) |
4129 | 4124 | (when (or (ring-empty-p log-edit-comment-ring) |
4130 | (not (equal comment (ring-ref log-edit-comment-ring 0)))) | |
4125 | (not (equal comment (ring-ref log-edit-comment-ring 0)))) | |
4131 | 4126 | (ring-insert log-edit-comment-ring comment))) |
4132 | 4127 | |
4133 | 4128 | (defun magit-log-edit-commit () |
4135 | 4130 | \('git commit ...')" |
4136 | 4131 | (interactive) |
4137 | 4132 | (let* ((fields (magit-log-edit-get-fields)) |
4138 | (amend (equal (cdr (assq 'amend fields)) "yes")) | |
4139 | (allow-empty (equal (cdr (assq 'allow-empty fields)) "yes")) | |
4140 | (commit-all (equal (cdr (assq 'commit-all fields)) "yes")) | |
4141 | (sign-off-field (assq 'sign-off fields)) | |
4142 | (sign-off (if sign-off-field | |
4143 | (equal (cdr sign-off-field) "yes") | |
4144 | magit-commit-signoff)) | |
4145 | (tag-rev (cdr (assq 'tag-rev fields))) | |
4146 | (tag-name (cdr (assq 'tag-name fields))) | |
4133 | (amend (equal (cdr (assq 'amend fields)) "yes")) | |
4134 | (allow-empty (equal (cdr (assq 'allow-empty fields)) "yes")) | |
4135 | (commit-all (equal (cdr (assq 'commit-all fields)) "yes")) | |
4136 | (sign-off-field (assq 'sign-off fields)) | |
4137 | (sign-off (if sign-off-field | |
4138 | (equal (cdr sign-off-field) "yes") | |
4139 | magit-commit-signoff)) | |
4140 | (tag-rev (cdr (assq 'tag-rev fields))) | |
4141 | (tag-name (cdr (assq 'tag-name fields))) | |
4147 | 4142 | (author (cdr (assq 'author fields))) |
4148 | 4143 | (tag-options (cdr (assq 'tag-options fields)))) |
4149 | 4144 | (if (or (not (or allow-empty commit-all amend tag-name (magit-anything-staged-p))) |
4154 | 4149 | (magit-log-edit-set-fields nil) |
4155 | 4150 | (magit-log-edit-cleanup) |
4156 | 4151 | (if (= (buffer-size) 0) |
4157 | (insert "(Empty description)\n")) | |
4152 | (insert "(Empty description)\n")) | |
4158 | 4153 | (let ((commit-buf (current-buffer))) |
4159 | 4154 | (with-current-buffer (magit-find-status-buffer default-directory) |
4160 | (cond (tag-name | |
4155 | (cond (tag-name | |
4161 | 4156 | (apply #'magit-run-git-with-input commit-buf |
4162 | 4157 | "tag" (append tag-options (list tag-name "-a" "-F" "-" tag-rev)))) |
4163 | (t | |
4164 | (apply #'magit-run-async-with-input commit-buf | |
4165 | magit-git-executable | |
4166 | (append magit-git-standard-options | |
4158 | (t | |
4159 | (apply #'magit-run-async-with-input commit-buf | |
4160 | magit-git-executable | |
4161 | (append magit-git-standard-options | |
4167 | 4162 | '("commit") |
4168 | 4163 | magit-custom-options |
4169 | 4164 | '("-F" "-") |
4170 | (if (and commit-all (not allow-empty)) '("--all") '()) | |
4171 | (if amend '("--amend") '()) | |
4172 | (if allow-empty '("--allow-empty")) | |
4173 | (if sign-off '("--signoff") '()))))))) | |
4165 | (if (and commit-all (not allow-empty)) '("--all") '()) | |
4166 | (if amend '("--amend") '()) | |
4167 | (if allow-empty '("--allow-empty")) | |
4168 | (if sign-off '("--signoff") '()))))))) | |
4174 | 4169 | (erase-buffer) |
4175 | 4170 | (bury-buffer) |
4176 | 4171 | (when (file-exists-p ".git/MERGE_MSG") |
4184 | 4179 | "Abort edits and erase commit message being composed." |
4185 | 4180 | (interactive) |
4186 | 4181 | (when (or (not magit-log-edit-confirm-cancellation) |
4187 | (yes-or-no-p | |
4188 | "Really cancel editing the log (any changes will be lost)?")) | |
4182 | (yes-or-no-p | |
4183 | "Really cancel editing the log (any changes will be lost)?")) | |
4189 | 4184 | (erase-buffer) |
4190 | 4185 | (bury-buffer) |
4191 | 4186 | (when magit-pre-log-edit-window-configuration |
4223 | 4218 | |
4224 | 4219 | (defun magit-pop-to-log-edit (operation) |
4225 | 4220 | (let ((dir default-directory) |
4226 | (buf (get-buffer-create magit-log-edit-buffer-name))) | |
4221 | (buf (get-buffer-create magit-log-edit-buffer-name))) | |
4227 | 4222 | (setq magit-pre-log-edit-window-configuration |
4228 | (current-window-configuration)) | |
4223 | (current-window-configuration)) | |
4229 | 4224 | (pop-to-buffer buf) |
4230 | 4225 | (when (file-exists-p ".git/MERGE_MSG") |
4231 | 4226 | (insert-file-contents ".git/MERGE_MSG")) |
4273 | 4268 | (defun magit-add-log () |
4274 | 4269 | (interactive) |
4275 | 4270 | (cond ((magit-rebase-info) |
4276 | (if (y-or-n-p "Rebase in progress. Continue it? ") | |
4277 | (magit-run-git-async "rebase" "--continue"))) | |
4278 | (t | |
4279 | (let ((section (magit-current-section))) | |
4280 | (let ((fun (if (eq (magit-section-type section) 'hunk) | |
4281 | (save-window-excursion | |
4282 | (save-excursion | |
4283 | (magit-visit-item) | |
4284 | (add-log-current-defun))) | |
4285 | nil)) | |
4286 | (file (magit-diff-item-file | |
4287 | (cond ((eq (magit-section-type section) 'hunk) | |
4288 | (magit-hunk-item-diff section)) | |
4289 | ((eq (magit-section-type section) 'diff) | |
4290 | section) | |
4291 | (t | |
4292 | (error "No change at point")))))) | |
4293 | (magit-log-edit nil) | |
4294 | (goto-char (point-min)) | |
4295 | (cond ((not (search-forward-regexp | |
4296 | (format "^\\* %s" (regexp-quote file)) nil t)) | |
4297 | ;; No entry for file, create it. | |
4298 | (goto-char (point-max)) | |
4299 | (insert (format "\n* %s" file)) | |
4300 | (if fun | |
4301 | (insert (format " (%s)" fun))) | |
4302 | (insert ": ")) | |
4303 | (fun | |
4304 | ;; found entry for file, look for fun | |
4305 | (let ((limit (or (save-excursion | |
4306 | (and (search-forward-regexp "^\\* " | |
4307 | nil t) | |
4308 | (match-beginning 0))) | |
4309 | (point-max)))) | |
4310 | (cond ((search-forward-regexp (format "(.*\\<%s\\>.*):" | |
4311 | (regexp-quote fun)) | |
4312 | limit t) | |
4313 | ;; found it, goto end of current entry | |
4314 | (if (search-forward-regexp "^(" limit t) | |
4315 | (backward-char 2) | |
4316 | (goto-char limit))) | |
4317 | (t | |
4318 | ;; not found, insert new entry | |
4319 | (goto-char limit) | |
4320 | (if (bolp) | |
4321 | (open-line 1) | |
4322 | (newline)) | |
4323 | (insert (format "(%s): " fun)))))))))))) | |
4271 | (if (y-or-n-p "Rebase in progress. Continue it? ") | |
4272 | (magit-run-git-async "rebase" "--continue"))) | |
4273 | (t | |
4274 | (let ((section (magit-current-section))) | |
4275 | (let ((fun (if (eq (magit-section-type section) 'hunk) | |
4276 | (save-window-excursion | |
4277 | (save-excursion | |
4278 | (magit-visit-item) | |
4279 | (add-log-current-defun))) | |
4280 | nil)) | |
4281 | (file (magit-diff-item-file | |
4282 | (cond ((eq (magit-section-type section) 'hunk) | |
4283 | (magit-hunk-item-diff section)) | |
4284 | ((eq (magit-section-type section) 'diff) | |
4285 | section) | |
4286 | (t | |
4287 | (error "No change at point")))))) | |
4288 | (magit-log-edit nil) | |
4289 | (goto-char (point-min)) | |
4290 | (cond ((not (search-forward-regexp | |
4291 | (format "^\\* %s" (regexp-quote file)) nil t)) | |
4292 | ;; No entry for file, create it. | |
4293 | (goto-char (point-max)) | |
4294 | (insert (format "\n* %s" file)) | |
4295 | (if fun | |
4296 | (insert (format " (%s)" fun))) | |
4297 | (insert ": ")) | |
4298 | (fun | |
4299 | ;; found entry for file, look for fun | |
4300 | (let ((limit (or (save-excursion | |
4301 | (and (search-forward-regexp "^\\* " | |
4302 | nil t) | |
4303 | (match-beginning 0))) | |
4304 | (point-max)))) | |
4305 | (cond ((search-forward-regexp (format "(.*\\<%s\\>.*):" | |
4306 | (regexp-quote fun)) | |
4307 | limit t) | |
4308 | ;; found it, goto end of current entry | |
4309 | (if (search-forward-regexp "^(" limit t) | |
4310 | (backward-char 2) | |
4311 | (goto-char limit))) | |
4312 | (t | |
4313 | ;; not found, insert new entry | |
4314 | (goto-char limit) | |
4315 | (if (bolp) | |
4316 | (open-line 1) | |
4317 | (newline)) | |
4318 | (insert (format "(%s): " fun)))))))))))) | |
4324 | 4319 | |
4325 | 4320 | ;;; Tags |
4326 | 4321 | |
4350 | 4345 | (defun magit-wash-stash () |
4351 | 4346 | (if (search-forward-regexp "stash@{\\(.*?\\)}" (line-end-position) t) |
4352 | 4347 | (let ((stash (match-string-no-properties 0)) |
4353 | (name (match-string-no-properties 1))) | |
4354 | (delete-region (match-beginning 0) (match-end 0)) | |
4355 | (goto-char (match-beginning 0)) | |
4356 | (fixup-whitespace) | |
4357 | (goto-char (line-beginning-position)) | |
4358 | (insert name) | |
4359 | (goto-char (line-beginning-position)) | |
4360 | (magit-with-section stash 'stash | |
4361 | (magit-set-section-info stash) | |
4362 | (forward-line))) | |
4363 | (forward-line)) | |
4348 | (name (match-string-no-properties 1))) | |
4349 | (delete-region (match-beginning 0) (match-end 0)) | |
4350 | (goto-char (match-beginning 0)) | |
4351 | (fixup-whitespace) | |
4352 | (goto-char (line-beginning-position)) | |
4353 | (insert name) | |
4354 | (goto-char (line-beginning-position)) | |
4355 | (magit-with-section stash 'stash | |
4356 | (magit-set-section-info stash) | |
4357 | (forward-line))) | |
4358 | (forward-line)) | |
4364 | 4359 | t) |
4365 | 4360 | |
4366 | 4361 | (defun magit-wash-stashes () |
4369 | 4364 | |
4370 | 4365 | (magit-define-inserter stashes () |
4371 | 4366 | (magit-git-section 'stashes |
4372 | "Stashes:" 'magit-wash-stashes | |
4373 | "stash" "list")) | |
4367 | "Stashes:" 'magit-wash-stashes | |
4368 | "stash" "list")) | |
4374 | 4369 | |
4375 | 4370 | (magit-define-command stash (description) |
4376 | 4371 | "Create new stash of working tree and staging area named DESCRIPTION. |
4386 | 4381 | (interactive) |
4387 | 4382 | (magit-with-refresh |
4388 | 4383 | (magit-run-git "stash" "save" |
4389 | (format-time-string "Snapshot taken at %Y-%m-%d %H:%M:%S" | |
4390 | (current-time))) | |
4384 | (format-time-string "Snapshot taken at %Y-%m-%d %H:%M:%S" | |
4385 | (current-time))) | |
4391 | 4386 | (magit-run-git "stash" "apply" "stash@{0}"))) |
4392 | 4387 | |
4393 | 4388 | (defvar magit-currently-shown-stash nil) |
4394 | 4389 | |
4395 | 4390 | (define-derived-mode magit-stash-mode magit-mode |
4396 | "Mode for looking at a git stash. | |
4391 | "Mode for looking at a git stash. | |
4397 | 4392 | |
4398 | 4393 | \\{magit-stash-mode-map}" |
4399 | 4394 | :group 'magit) |
4405 | 4400 | (when (magit-section-p stash) |
4406 | 4401 | (setq stash (magit-section-info stash))) |
4407 | 4402 | (let ((dir default-directory) |
4408 | (buf (get-buffer-create magit-stash-buffer-name)) | |
4403 | (buf (get-buffer-create magit-stash-buffer-name)) | |
4409 | 4404 | (stash-id (magit-git-string "rev-list" "-1" stash))) |
4410 | 4405 | (cond ((and (equal magit-currently-shown-stash stash-id) |
4411 | 4406 | (with-current-buffer buf |
4442 | 4437 | |
4443 | 4438 | (defun magit-apply-commit (commit &optional docommit noerase revert) |
4444 | 4439 | (let* ((parent-id (magit-choose-parent-id commit "cherry-pick")) |
4445 | (success (magit-run* `(,magit-git-executable | |
4446 | ,@magit-git-standard-options | |
4447 | ,(if revert "revert" "cherry-pick") | |
4448 | ,@(if parent-id | |
4449 | (list "-m" (number-to-string parent-id))) | |
4450 | ,@(if (not docommit) (list "--no-commit")) | |
4451 | ,commit) | |
4452 | nil noerase))) | |
4440 | (success (magit-run* `(,magit-git-executable | |
4441 | ,@magit-git-standard-options | |
4442 | ,(if revert "revert" "cherry-pick") | |
4443 | ,@(if parent-id | |
4444 | (list "-m" (number-to-string parent-id))) | |
4445 | ,@(if (not docommit) (list "--no-commit")) | |
4446 | ,commit) | |
4447 | nil noerase))) | |
4453 | 4448 | (when (and (not docommit) success) |
4454 | 4449 | (cond (revert |
4455 | (magit-log-edit-append | |
4456 | (magit-format-commit commit "Reverting \"%s\""))) | |
4457 | (t | |
4458 | (magit-log-edit-append | |
4459 | (magit-format-commit commit "%s%n%n%b")) | |
4460 | (magit-log-edit-set-field | |
4461 | 'author | |
4462 | (magit-format-commit commit "%an <%ae>, %ai"))))) | |
4450 | (magit-log-edit-append | |
4451 | (magit-format-commit commit "Reverting \"%s\""))) | |
4452 | (t | |
4453 | (magit-log-edit-append | |
4454 | (magit-format-commit commit "%s%n%n%b")) | |
4455 | (magit-log-edit-set-field | |
4456 | 'author | |
4457 | (magit-format-commit commit "%an <%ae>, %ai"))))) | |
4463 | 4458 | success)) |
4464 | 4459 | |
4465 | 4460 | (defun magit-apply-item () |
4526 | 4521 | (interactive "P") |
4527 | 4522 | (make-local-variable 'magit-log-cutoff-length) |
4528 | 4523 | (cond |
4529 | ((numberp arg) | |
4530 | (setq magit-log-cutoff-length (+ magit-log-cutoff-length arg))) | |
4531 | (arg | |
4532 | (setq magit-log-cutoff-length magit-log-infinite-length)) | |
4533 | (t (setq magit-log-cutoff-length (* magit-log-cutoff-length 2)))) | |
4524 | ((numberp arg) | |
4525 | (setq magit-log-cutoff-length (+ magit-log-cutoff-length arg))) | |
4526 | (arg | |
4527 | (setq magit-log-cutoff-length magit-log-infinite-length)) | |
4528 | (t (setq magit-log-cutoff-length (* magit-log-cutoff-length 2)))) | |
4534 | 4529 | (let ((old-point (point))) |
4535 | 4530 | (magit-refresh) |
4536 | 4531 | (goto-char old-point))) |
4542 | 4537 | (setq magit-current-range range) |
4543 | 4538 | (magit-create-log-buffer-sections |
4544 | 4539 | (apply #'magit-git-section nil |
4545 | (magit-rev-range-describe range "Commits") | |
4546 | 'magit-wash-log | |
4547 | `("log" | |
4548 | ,(format "--max-count=%s" magit-log-cutoff-length) | |
4549 | ,style | |
4550 | ,@(if magit-have-decorate (list "--decorate=full")) | |
4551 | ,@(if magit-have-graph (list "--graph")) | |
4552 | ,@(if magit-have-abbrev (list "--no-abbrev-commit")) | |
4553 | ,@args | |
4554 | "--")))) | |
4540 | (magit-rev-range-describe range "Commits") | |
4541 | 'magit-wash-log | |
4542 | `("log" | |
4543 | ,(format "--max-count=%s" magit-log-cutoff-length) | |
4544 | ,style | |
4545 | ,@(if magit-have-decorate (list "--decorate=full")) | |
4546 | ,@(if magit-have-graph (list "--graph")) | |
4547 | ,@(if magit-have-abbrev (list "--no-abbrev-commit")) | |
4548 | ,@args | |
4549 | "--")))) | |
4555 | 4550 | |
4556 | 4551 | (define-derived-mode magit-log-mode magit-mode "Magit" |
4557 | "Mode for looking at git log. | |
4552 | "Mode for looking at git log. | |
4558 | 4553 | |
4559 | 4554 | \\{magit-log-mode-map}" |
4560 | 4555 | :group 'magit) |
4572 | 4567 | (let* ((log-range (if ask-for-range |
4573 | 4568 | (magit-read-rev-range "Log" "HEAD") |
4574 | 4569 | "HEAD")) |
4575 | (topdir (magit-get-top-dir default-directory)) | |
4576 | (args (nconc (list (magit-rev-range-to-git log-range)) | |
4570 | (topdir (magit-get-top-dir default-directory)) | |
4571 | (args (nconc (list (magit-rev-range-to-git log-range)) | |
4577 | 4572 | magit-custom-options |
4578 | 4573 | extra-args))) |
4579 | 4574 | (magit-buffer-switch magit-log-buffer-name) |
4580 | 4575 | (magit-mode-init topdir 'magit-log-mode #'magit-refresh-log-buffer log-range |
4581 | "--pretty=oneline" args))) | |
4576 | "--pretty=oneline" args))) | |
4582 | 4577 | |
4583 | 4578 | (define-obsolete-function-alias 'magit-display-log 'magit-log) |
4584 | 4579 | |
4589 | 4584 | (magit-define-command log-long (&optional ranged) |
4590 | 4585 | (interactive) |
4591 | 4586 | (let* ((range (if ranged |
4592 | (magit-read-rev-range "Long log" "HEAD") | |
4593 | "HEAD")) | |
4594 | (topdir (magit-get-top-dir default-directory)) | |
4595 | (args (append (list (magit-rev-range-to-git range)) | |
4596 | magit-custom-options))) | |
4587 | (magit-read-rev-range "Long log" "HEAD") | |
4588 | "HEAD")) | |
4589 | (topdir (magit-get-top-dir default-directory)) | |
4590 | (args (append (list (magit-rev-range-to-git range)) | |
4591 | magit-custom-options))) | |
4597 | 4592 | (magit-buffer-switch magit-log-buffer-name) |
4598 | 4593 | (magit-mode-init topdir 'magit-log-mode #'magit-refresh-log-buffer range |
4599 | "--stat" args))) | |
4594 | "--stat" args))) | |
4600 | 4595 | |
4601 | 4596 | ;;; Reflog |
4602 | 4597 | |
4617 | 4612 | args))))) |
4618 | 4613 | |
4619 | 4614 | (define-derived-mode magit-reflog-mode magit-log-mode "Magit" |
4620 | "Mode for looking at git reflog. | |
4615 | "Mode for looking at git reflog. | |
4621 | 4616 | |
4622 | 4617 | \\{magit-reflog-mode-map}" |
4623 | 4618 | :group 'magit) |
4712 | 4707 | "diff" (magit-diff-U-arg) args)))) |
4713 | 4708 | |
4714 | 4709 | (define-derived-mode magit-diff-mode magit-mode "Magit" |
4715 | "Mode for looking at a git diff. | |
4710 | "Mode for looking at a git diff. | |
4716 | 4711 | |
4717 | 4712 | \\{magit-diff-mode-map}" |
4718 | 4713 | :group 'magit) |
4734 | 4729 | (defun magit-diff-with-mark () |
4735 | 4730 | (interactive) |
4736 | 4731 | (magit-diff (cons (magit-marked-commit) |
4737 | (magit-commit-at-point)))) | |
4732 | (magit-commit-at-point)))) | |
4738 | 4733 | |
4739 | 4734 | ;;; Wazzup |
4740 | 4735 | |
4751 | 4746 | (defun magit-wazzup-toggle-ignore (branch edit) |
4752 | 4747 | (let ((ignore-file ".git/info/wazzup-exclude")) |
4753 | 4748 | (if edit |
4754 | (setq branch (read-string "Branch to ignore for wazzup: " branch))) | |
4749 | (setq branch (read-string "Branch to ignore for wazzup: " branch))) | |
4755 | 4750 | (let ((ignored (magit-file-lines ignore-file))) |
4756 | 4751 | (cond ((member branch ignored) |
4757 | (when (or (not edit) | |
4758 | (y-or-n-p "Branch %s is already ignored. Unignore? ")) | |
4759 | (setq ignored (delete branch ignored)))) | |
4760 | (t | |
4761 | (setq ignored (append ignored (list branch))))) | |
4752 | (when (or (not edit) | |
4753 | (y-or-n-p "Branch %s is already ignored. Unignore? ")) | |
4754 | (setq ignored (delete branch ignored)))) | |
4755 | (t | |
4756 | (setq ignored (append ignored (list branch))))) | |
4762 | 4757 | (magit-write-file-lines ignore-file ignored) |
4763 | 4758 | (magit-need-refresh)))) |
4764 | 4759 | |
4769 | 4764 | (unless head (setq head "HEAD")) |
4770 | 4765 | (magit-create-buffer-sections |
4771 | 4766 | (magit-with-section 'wazzupbuf nil |
4772 | (insert (format "Wazzup, %s\n\n" branch-desc)) | |
4773 | (let* ((excluded (magit-file-lines ".git/info/wazzup-exclude")) | |
4774 | (all-branches (magit-list-interesting-refs)) | |
4775 | (branches (if all all-branches | |
4776 | (delq nil (mapcar | |
4777 | (lambda (b) | |
4778 | (and (not | |
4779 | (member (cdr b) excluded)) | |
4780 | b)) | |
4781 | all-branches)))) | |
4782 | (reported (make-hash-table :test #'equal))) | |
4783 | (dolist (branch branches) | |
4784 | (let* ((name (car branch)) | |
4785 | (ref (cdr branch)) | |
4786 | (hash (magit-rev-parse ref)) | |
4787 | (reported-branch (gethash hash reported))) | |
4788 | (unless (or (and reported-branch | |
4789 | (string= (file-name-nondirectory ref) | |
4790 | reported-branch)) | |
4791 | (not (magit-git-string "merge-base" head ref))) | |
4792 | (puthash hash (file-name-nondirectory ref) reported) | |
4793 | (let* ((n (length (magit-git-lines "log" "--pretty=oneline" | |
4794 | (concat head ".." ref)))) | |
4795 | (section | |
4796 | (let ((magit-section-hidden-default t)) | |
4797 | (magit-git-section | |
4798 | (cons ref 'wazzup) | |
4799 | (format "%s unmerged commits in %s%s" | |
4800 | n name | |
4801 | (if (member ref excluded) | |
4802 | " (normally ignored)" | |
4803 | "")) | |
4804 | 'magit-wash-log | |
4805 | "log" | |
4806 | (format "--max-count=%s" magit-log-cutoff-length) | |
4807 | "--graph" | |
4808 | "--pretty=oneline" | |
4809 | (format "%s..%s" head ref) | |
4810 | "--")))) | |
4811 | (magit-set-section-info ref section)))))))))) | |
4767 | (insert (format "Wazzup, %s\n\n" branch-desc)) | |
4768 | (let* ((excluded (magit-file-lines ".git/info/wazzup-exclude")) | |
4769 | (all-branches (magit-list-interesting-refs)) | |
4770 | (branches (if all all-branches | |
4771 | (delq nil (mapcar | |
4772 | (lambda (b) | |
4773 | (and (not | |
4774 | (member (cdr b) excluded)) | |
4775 | b)) | |
4776 | all-branches)))) | |
4777 | (reported (make-hash-table :test #'equal))) | |
4778 | (dolist (branch branches) | |
4779 | (let* ((name (car branch)) | |
4780 | (ref (cdr branch)) | |
4781 | (hash (magit-rev-parse ref)) | |
4782 | (reported-branch (gethash hash reported))) | |
4783 | (unless (or (and reported-branch | |
4784 | (string= (file-name-nondirectory ref) | |
4785 | reported-branch)) | |
4786 | (not (magit-git-string "merge-base" head ref))) | |
4787 | (puthash hash (file-name-nondirectory ref) reported) | |
4788 | (let* ((n (length (magit-git-lines "log" "--pretty=oneline" | |
4789 | (concat head ".." ref)))) | |
4790 | (section | |
4791 | (let ((magit-section-hidden-default t)) | |
4792 | (magit-git-section | |
4793 | (cons ref 'wazzup) | |
4794 | (format "%s unmerged commits in %s%s" | |
4795 | n name | |
4796 | (if (member ref excluded) | |
4797 | " (normally ignored)" | |
4798 | "")) | |
4799 | 'magit-wash-log | |
4800 | "log" | |
4801 | (format "--max-count=%s" magit-log-cutoff-length) | |
4802 | "--graph" | |
4803 | "--pretty=oneline" | |
4804 | (format "%s..%s" head ref) | |
4805 | "--")))) | |
4806 | (magit-set-section-info ref section)))))))))) | |
4812 | 4807 | |
4813 | 4808 | (define-derived-mode magit-wazzup-mode magit-mode |
4814 | "Mode for looking at commits that could be merged from other branches. | |
4809 | "Mode for looking at commits that could be merged from other branches. | |
4815 | 4810 | |
4816 | 4811 | \\{magit-wazzup-mode-map}" |
4817 | 4812 | :group 'magit) |
4819 | 4814 | (defun magit-wazzup (&optional all) |
4820 | 4815 | (interactive "P") |
4821 | 4816 | (let ((topdir (magit-get-top-dir default-directory)) |
4822 | (current-branch (magit-get-current-branch))) | |
4817 | (current-branch (magit-get-current-branch))) | |
4823 | 4818 | (magit-buffer-switch "*magit-wazzup*") |
4824 | 4819 | (magit-mode-init topdir 'magit-wazzup-mode |
4825 | #'magit-refresh-wazzup-buffer | |
4826 | current-branch all))) | |
4820 | #'magit-refresh-wazzup-buffer | |
4821 | current-branch all))) | |
4827 | 4822 | |
4828 | 4823 | ;;; Miscellaneous |
4829 | 4824 | |
4830 | 4825 | (defun magit-ignore-file (file edit local) |
4831 | 4826 | (let ((ignore-file (if local ".git/info/exclude" ".gitignore"))) |
4832 | 4827 | (if edit |
4833 | (setq file (read-string "File to ignore: " file))) | |
4828 | (setq file (read-string "File to ignore: " file))) | |
4834 | 4829 | (with-temp-buffer |
4835 | 4830 | (when (file-exists-p ignore-file) |
4836 | 4831 | (insert-file-contents ignore-file)) |
4837 | 4832 | (goto-char (point-max)) |
4838 | 4833 | (unless (bolp) |
4839 | (insert "\n")) | |
4834 | (insert "\n")) | |
4840 | 4835 | (insert "/" file "\n") |
4841 | 4836 | (write-region nil nil ignore-file)) |
4842 | 4837 | (magit-need-refresh))) |
4857 | 4852 | |
4858 | 4853 | (defun magit-discard-diff (diff stagedp) |
4859 | 4854 | (let ((kind (magit-diff-item-kind diff)) |
4860 | (file (magit-diff-item-file diff))) | |
4855 | (file (magit-diff-item-file diff))) | |
4861 | 4856 | (cond ((eq kind 'deleted) |
4862 | (when (yes-or-no-p (format "Resurrect %s? " file)) | |
4863 | (magit-run-git "reset" "-q" "--" file) | |
4864 | (magit-run-git "checkout" "--" file))) | |
4865 | ((eq kind 'new) | |
4866 | (if (yes-or-no-p (format "Delete %s? " file)) | |
4867 | (magit-run-git "rm" "-f" "--" file))) | |
4868 | (t | |
4869 | (if (yes-or-no-p (format "Discard changes to %s? " file)) | |
4870 | (if stagedp | |
4871 | (magit-run-git "checkout" "HEAD" "--" file) | |
4872 | (magit-run-git "checkout" "--" file))))))) | |
4857 | (when (yes-or-no-p (format "Resurrect %s? " file)) | |
4858 | (magit-run-git "reset" "-q" "--" file) | |
4859 | (magit-run-git "checkout" "--" file))) | |
4860 | ((eq kind 'new) | |
4861 | (if (yes-or-no-p (format "Delete %s? " file)) | |
4862 | (magit-run-git "rm" "-f" "--" file))) | |
4863 | (t | |
4864 | (if (yes-or-no-p (format "Discard changes to %s? " file)) | |
4865 | (if stagedp | |
4866 | (magit-run-git "checkout" "HEAD" "--" file) | |
4867 | (magit-run-git "checkout" "--" file))))))) | |
4873 | 4868 | |
4874 | 4869 | (defun magit-discard-item () |
4875 | 4870 | (interactive) |
4883 | 4878 | (magit-refresh-buffer))) |
4884 | 4879 | ((untracked) |
4885 | 4880 | (if (yes-or-no-p "Delete all untracked files and directories? ") |
4886 | (magit-run-git "clean" "-df"))) | |
4881 | (magit-run-git "clean" "-df"))) | |
4887 | 4882 | ((unstaged diff hunk) |
4888 | 4883 | (when (yes-or-no-p (if (magit-use-region-p) |
4889 | "Discard changes in region? " | |
4890 | "Discard hunk? ")) | |
4884 | "Discard changes in region? " | |
4885 | "Discard hunk? ")) | |
4891 | 4886 | (magit-apply-hunk-item-reverse item))) |
4892 | 4887 | ((staged diff hunk) |
4893 | 4888 | (if (magit-file-uptodate-p (magit-diff-item-file |
4894 | (magit-hunk-item-diff item))) | |
4895 | (when (yes-or-no-p (if (magit-use-region-p) | |
4896 | "Discard changes in region? " | |
4897 | "Discard hunk? ")) | |
4898 | (magit-apply-hunk-item-reverse item "--index")) | |
4889 | (magit-hunk-item-diff item))) | |
4890 | (when (yes-or-no-p (if (magit-use-region-p) | |
4891 | "Discard changes in region? " | |
4892 | "Discard hunk? ")) | |
4893 | (magit-apply-hunk-item-reverse item "--index")) | |
4899 | 4894 | (error "Can't discard this hunk. Please unstage it first"))) |
4900 | 4895 | ((unstaged diff) |
4901 | 4896 | (magit-discard-diff item nil)) |
4902 | 4897 | ((staged diff) |
4903 | 4898 | (if (magit-file-uptodate-p (magit-diff-item-file item)) |
4904 | (magit-discard-diff item t) | |
4899 | (magit-discard-diff item t) | |
4905 | 4900 | (error "Can't discard staged changes to this file. Please unstage it first"))) |
4906 | 4901 | ((diff diff) |
4907 | 4902 | (save-excursion |
4924 | 4919 | new-entry put-new-entry-on-new-line) |
4925 | 4920 | "Add a change log entry for current change." |
4926 | 4921 | (interactive (list current-prefix-arg |
4927 | (prompt-for-change-log-name))) | |
4922 | (prompt-for-change-log-name))) | |
4928 | 4923 | (let ((marker |
4929 | 4924 | (save-window-excursion |
4930 | 4925 | (magit-visit-item) |
4934 | 4929 | (goto-char marker) |
4935 | 4930 | (if (>= (magit-max-args-internal 'add-change-log-entry) 5) |
4936 | 4931 | (add-change-log-entry whoami file-name other-window |
4937 | new-entry put-new-entry-on-new-line) | |
4932 | new-entry put-new-entry-on-new-line) | |
4938 | 4933 | (add-change-log-entry whoami file-name other-window new-entry) |
4939 | 4934 | (if put-new-entry-on-new-line |
4940 | 4935 | (display-warning 'magit (format "Emacs %s does not support `put-new-entry-on-new-line' option to `add-change-log-entry'" emacs-version)))))))) |
4942 | 4937 | (defun magit-add-change-log-entry-other-window (&optional whoami file-name) |
4943 | 4938 | "Add a change log entry for current change in other window." |
4944 | 4939 | (interactive (if current-prefix-arg |
4945 | (list current-prefix-arg | |
4946 | (prompt-for-change-log-name)))) | |
4940 | (list current-prefix-arg | |
4941 | (prompt-for-change-log-name)))) | |
4947 | 4942 | (magit-add-change-log-entry whoami file-name t)) |
4948 | 4943 | |
4949 | 4944 | (defun magit-visit-item (&optional other-window) |
4964 | 4959 | file))) |
4965 | 4960 | ((hunk) |
4966 | 4961 | (let ((file (magit-diff-item-file (magit-hunk-item-diff item))) |
4967 | (line (magit-hunk-item-target-line item))) | |
4962 | (line (magit-hunk-item-target-line item))) | |
4968 | 4963 | (if (not (file-exists-p file)) |
4969 | 4964 | (error "Can't visit deleted file: %s" file)) |
4970 | 4965 | (funcall |
5009 | 5004 | (magit-section-action (item info "mark") |
5010 | 5005 | ((commit) |
5011 | 5006 | (magit-set-marked-commit (if (eq magit-marked-commit info) |
5012 | nil | |
5013 | info)))))) | |
5007 | nil | |
5008 | info)))))) | |
5014 | 5009 | |
5015 | 5010 | (defun magit-describe-item () |
5016 | 5011 | (interactive) |
5017 | 5012 | (let ((section (magit-current-section))) |
5018 | 5013 | (message "Section: %s %s-%s %S %S %S" |
5019 | (magit-section-type section) | |
5020 | (magit-section-beginning section) | |
5021 | (magit-section-end section) | |
5022 | (magit-section-title section) | |
5023 | (magit-section-info section) | |
5024 | (magit-section-context-type section)))) | |
5014 | (magit-section-type section) | |
5015 | (magit-section-beginning section) | |
5016 | (magit-section-end section) | |
5017 | (magit-section-title section) | |
5018 | (magit-section-info section) | |
5019 | (magit-section-context-type section)))) | |
5025 | 5020 | |
5026 | 5021 | (defun magit-copy-item-as-kill () |
5027 | 5022 | "Copy sha1 of commit at point into kill ring." |
5037 | 5032 | "Test whether server is running (works with < 23 as well). |
5038 | 5033 | |
5039 | 5034 | Return values: |
5040 | nil the server is definitely not running. | |
5041 | t the server seems to be running. | |
5035 | nil the server is definitely not running. | |
5036 | t the server seems to be running. | |
5042 | 5037 | something else we cannot determine whether it's running without using |
5043 | commands which may have to wait for a long time." | |
5038 | commands which may have to wait for a long time." | |
5044 | 5039 | (require 'server) |
5045 | 5040 | (if (functionp 'server-running-p) |
5046 | 5041 | (server-running-p) |
5047 | 5042 | (condition-case nil |
5048 | (if (and (boundp 'server-use-tcp) | |
5043 | (if (and (boundp 'server-use-tcp) | |
5049 | 5044 | server-use-tcp) |
5050 | (with-temp-buffer | |
5051 | (insert-file-contents-literally (expand-file-name server-name server-auth-dir)) | |
5052 | (or (and (looking-at "127\\.0\\.0\\.1:[0-9]+ \\([0-9]+\\)") | |
5053 | (assq 'comm | |
5054 | (process-attributes | |
5055 | (string-to-number (match-string 1)))) | |
5056 | t) | |
5057 | :other)) | |
5058 | (delete-process | |
5059 | (make-network-process | |
5060 | :name "server-client-test" :family 'local :server nil :noquery t | |
5061 | :service (expand-file-name server-name server-socket-dir))) | |
5062 | t) | |
5045 | (with-temp-buffer | |
5046 | (insert-file-contents-literally (expand-file-name server-name server-auth-dir)) | |
5047 | (or (and (looking-at "127\\.0\\.0\\.1:[0-9]+ \\([0-9]+\\)") | |
5048 | (assq 'comm | |
5049 | (process-attributes | |
5050 | (string-to-number (match-string 1)))) | |
5051 | t) | |
5052 | :other)) | |
5053 | (delete-process | |
5054 | (make-network-process | |
5055 | :name "server-client-test" :family 'local :server nil :noquery t | |
5056 | :service (expand-file-name server-name server-socket-dir))) | |
5057 | t) | |
5063 | 5058 | (file-error nil)))) |
5064 | 5059 | |
5065 | 5060 | (defun magit-interactive-rebase () |
5068 | 5063 | (unless (magit-server-running-p) |
5069 | 5064 | (server-start)) |
5070 | 5065 | (let* ((section (get-text-property (point) 'magit-section)) |
5071 | (commit (and (member 'commit (magit-section-context-type section)) | |
5072 | (magit-section-info section))) | |
5073 | (old-editor (getenv "GIT_EDITOR"))) | |
5066 | (commit (and (member 'commit (magit-section-context-type section)) | |
5067 | (magit-section-info section))) | |
5068 | (old-editor (getenv "GIT_EDITOR"))) | |
5074 | 5069 | (setenv "GIT_EDITOR" (locate-file "emacsclient" exec-path)) |
5075 | 5070 | (unwind-protect |
5076 | (magit-run-git-async "rebase" "-i" | |
5077 | (or (and commit (concat commit "^")) | |
5078 | (magit-read-rev "Interactively rebase to" (magit-guess-branch)))) | |
5071 | (magit-run-git-async "rebase" "-i" | |
5072 | (or (and commit (concat commit "^")) | |
5073 | (magit-read-rev "Interactively rebase to" (magit-guess-branch)))) | |
5079 | 5074 | (if old-editor |
5080 | (setenv "GIT_EDITOR" old-editor))))) | |
5075 | (setenv "GIT_EDITOR" old-editor))))) | |
5081 | 5076 | |
5082 | 5077 | (define-derived-mode magit-show-branches-mode magit-mode |
5083 | 5078 | "Magit Branches") |
5109 | 5104 | (interactive "P") |
5110 | 5105 | (let* ((branch-section (magit-current-section)) |
5111 | 5106 | (args (list "branch" |
5112 | (if force "-D" "-d") | |
5113 | (when (magit--is-branch-section-remote branch-section) "-r") | |
5114 | (magit-remove-remote (magit--branch-name-from-section branch-section))))) | |
5107 | (if force "-D" "-d") | |
5108 | (when (magit--is-branch-section-remote branch-section) "-r") | |
5109 | (magit-remove-remote (magit--branch-name-from-section branch-section))))) | |
5115 | 5110 | (if (and (magit--is-branch-section-remote branch-section) |
5116 | 5111 | (yes-or-no-p "Remove branch in remote repository as well? ")) |
5117 | 5112 | (magit-remove-branch-in-remote-repo (magit--branch-name-from-section branch-section)) |
5118 | (apply 'magit-run-git (remq nil args))))) | |
5113 | (apply 'magit-run-git (remq nil args))))) | |
5119 | 5114 | |
5120 | 5115 | (defun magit--remotes () |
5121 | 5116 | "Return a list of names for known remotes." |
5195 | 5190 | (cons 'sha1 (match-string 3 branch-line)) |
5196 | 5191 | (cons 'msg (match-string 5 branch-line))) |
5197 | 5192 | res)))) |
5198 | ||
5199 | ||
5200 | ||
5201 | 5193 | |
5202 | 5194 | (defun magit-show-branches () |
5203 | 5195 | "Show all of the current branches." |
5235 | 5227 | 'face 'magit-log-head-label-remote) |
5236 | 5228 | "]") |
5237 | 5229 | ""))) |
5238 | (insert "\n"))))) | |
5230 | (insert "\n"))))) | |
5239 | 5231 | (magit-show-branches-mode) |
5240 | 5232 | (goto-char (point-min)) |
5241 | 5233 | (if buffer-existed |
5284 | 5276 | (defun magit-interactive-resolve (file) |
5285 | 5277 | (require 'ediff) |
5286 | 5278 | (let ((merge-status (magit-git-string "ls-files" "-u" "--" file)) |
5287 | (base-buffer (generate-new-buffer (concat file ".base"))) | |
5288 | (our-buffer (generate-new-buffer (concat file ".current"))) | |
5289 | (their-buffer (generate-new-buffer (concat file ".merged"))) | |
5290 | (windows (current-window-configuration))) | |
5279 | (base-buffer (generate-new-buffer (concat file ".base"))) | |
5280 | (our-buffer (generate-new-buffer (concat file ".current"))) | |
5281 | (their-buffer (generate-new-buffer (concat file ".merged"))) | |
5282 | (windows (current-window-configuration))) | |
5291 | 5283 | (if (null merge-status) |
5292 | (error "Cannot resolve %s" file)) | |
5284 | (error "Cannot resolve %s" file)) | |
5293 | 5285 | (with-current-buffer base-buffer |
5294 | 5286 | (if (string-match "^[0-9]+ [0-9a-f]+ 1" merge-status) |
5295 | 5287 | (insert (magit-git-output `("cat-file" "blob" ,(concat ":1:" file)))))) |
5311 | 5303 | (setq magit-ediff-windows windows) |
5312 | 5304 | (make-local-variable 'ediff-quit-hook) |
5313 | 5305 | (add-hook 'ediff-quit-hook |
5314 | (lambda () | |
5315 | (let ((buffer-A ediff-buffer-A) | |
5316 | (buffer-B ediff-buffer-B) | |
5317 | (buffer-C ediff-buffer-C) | |
5318 | (buffer-Ancestor ediff-ancestor-buffer) | |
5319 | (file magit-ediff-file) | |
5320 | (file-buffer) | |
5321 | (windows magit-ediff-windows)) | |
5322 | (ediff-cleanup-mess) | |
5323 | (find-file file) | |
5324 | (setq file-buffer (current-buffer)) | |
5325 | (erase-buffer) | |
5326 | (insert-buffer-substring buffer-C) | |
5327 | (kill-buffer buffer-A) | |
5328 | (kill-buffer buffer-B) | |
5329 | (kill-buffer buffer-C) | |
5330 | (when (bufferp buffer-Ancestor) (kill-buffer buffer-Ancestor)) | |
5331 | (set-window-configuration windows) | |
5332 | (magit-save-some-buffers | |
5333 | "Conflict resolution finished; you may save the buffer" | |
5334 | (lambda () (eq (current-buffer) file-buffer))))))))) | |
5306 | (lambda () | |
5307 | (let ((buffer-A ediff-buffer-A) | |
5308 | (buffer-B ediff-buffer-B) | |
5309 | (buffer-C ediff-buffer-C) | |
5310 | (buffer-Ancestor ediff-ancestor-buffer) | |
5311 | (file magit-ediff-file) | |
5312 | (file-buffer) | |
5313 | (windows magit-ediff-windows)) | |
5314 | (ediff-cleanup-mess) | |
5315 | (find-file file) | |
5316 | (setq file-buffer (current-buffer)) | |
5317 | (erase-buffer) | |
5318 | (insert-buffer-substring buffer-C) | |
5319 | (kill-buffer buffer-A) | |
5320 | (kill-buffer buffer-B) | |
5321 | (kill-buffer buffer-C) | |
5322 | (when (bufferp buffer-Ancestor) (kill-buffer buffer-Ancestor)) | |
5323 | (set-window-configuration windows) | |
5324 | (magit-save-some-buffers | |
5325 | "Conflict resolution finished; you may save the buffer" | |
5326 | (lambda () (eq (current-buffer) file-buffer))))))))) | |
5335 | 5327 | |
5336 | 5328 | (defun magit-interactive-resolve-item () |
5337 | 5329 | (interactive) |