magit.el 24 KB
Newer Older
1
;;; magit.el --- A Git porcelain inside Emacs  -*- lexical-binding: t; coding: utf-8 -*-
Marius Vollmer's avatar
Marius Vollmer committed
2

Jonas Bernoulli's avatar
Jonas Bernoulli committed
3
;; Copyright (C) 2008-2018  The Magit Project Contributors
4
;;
5 6
;; You should have received a copy of the AUTHORS.md file which
;; lists all contributors.  If not, see http://magit.vc/authors.
7

8
;; Author: Marius Vollmer <marius.vollmer@gmail.com>
9
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
10 11
;;	Kyle Meyer        <kyle@kyleam.com>
;;	Noam Postavsky    <npostavs@users.sourceforge.net>
12
;; Former-Maintainers:
13
;;	Nicolas Dudebout  <nicolas.dudebout@gatech.edu>
14 15
;;	Peter J. Weisberg <pj@irregularexpressions.net>
;;	Phil Jackson      <phil@shellarchive.co.uk>
16 17
;;	Rémi Vanicat      <vanicat@debian.org>
;;	Yann Hodique      <yann.hodique@gmail.com>
18

19 20
;; Keywords: git tools vc
;; Homepage: https://github.com/magit/magit
Phil Jackson's avatar
Phil Jackson committed
21

22
;; Magit requires at least GNU Emacs 25.1 and Git 2.0.0.
23

Marius Vollmer's avatar
Marius Vollmer committed
24
;; Magit is free software; you can redistribute it and/or modify it
Marius Vollmer's avatar
Marius Vollmer committed
25 26 27
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
Marius Vollmer's avatar
Marius Vollmer committed
28
;;
Marius Vollmer's avatar
Marius Vollmer committed
29
;; Magit is distributed in the hope that it will be useful, but WITHOUT
Marius Vollmer's avatar
Marius Vollmer committed
30 31 32
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
;; License for more details.
Marius Vollmer's avatar
Marius Vollmer committed
33 34
;;
;; You should have received a copy of the GNU General Public License
35
;; along with Magit.  If not, see http://www.gnu.org/licenses.
Marius Vollmer's avatar
Marius Vollmer committed
36

37
;;; Commentary:
Marius Vollmer's avatar
Marius Vollmer committed
38

39
;; Magit is an interface to the version control system Git,
40 41 42 43 44 45 46
;; implemented as an Emacs package.  Magit aspires to be a complete
;; Git porcelain.  While we cannot (yet) claim, that Magit wraps and
;; improves upon each and every Git command, it is complete enough to
;; allow even experienced Git users to perform almost all of their
;; daily version control tasks directly from within Emacs.  While many
;; fine Git clients exist, only Magit and Git itself deserve to be
;; called porcelains.
Marius Vollmer's avatar
Marius Vollmer committed
47

Phil Jackson's avatar
Phil Jackson committed
48
;;; Code:
49

50 51 52
(require 'cl-lib)
(require 'dash)

53 54 55
(eval-when-compile
  (require 'subr-x))

56
(require 'with-editor)
57
(require 'git-commit)
58 59 60 61
(require 'magit-core)
(require 'magit-diff)
(require 'magit-apply)
(require 'magit-log)
62
(require 'magit-repos)
63

64
(require 'format-spec)
65
(require 'package nil t) ; used in `magit-version'
66

67
(defconst magit--minimal-git "2.0.0")
68
(defconst magit--minimal-emacs "25.1")
69

70
;;; Faces
71

72 73
(defface magit-header-line
  '((t :inherit magit-section-heading))
74 75 76 77 78 79 80 81 82
  "Face for the `header-line' in some Magit modes.
Note that some modes, such as `magit-log-select-mode', have their
own faces for the `header-line', or for parts of the
`header-line'."
  :group 'magit-faces)

(defface magit-header-line-key
  '((t :inherit magit-popup-key))
  "Face for keys in the `header-line'."
83 84
  :group 'magit-faces)

Jonas Bernoulli's avatar
Jonas Bernoulli committed
85 86 87 88
(defface magit-dimmed
  '((((class color) (background light)) :foreground "grey50")
    (((class color) (background  dark)) :foreground "grey50"))
  "Face for text that shouldn't stand out."
89
  :group 'magit-faces)
90

Jonas Bernoulli's avatar
Jonas Bernoulli committed
91 92 93 94
(defface magit-hash
  '((((class color) (background light)) :foreground "grey60")
    (((class color) (background  dark)) :foreground "grey40"))
  "Face for the sha1 part of the log output."
95 96
  :group 'magit-faces)

97
(defface magit-tag
98 99
  '((((class color) (background light)) :foreground "Goldenrod4")
    (((class color) (background  dark)) :foreground "LightGoldenrod2"))
100
  "Face for tag labels shown in log buffer."
101
  :group 'magit-faces)
102

103
(defface magit-branch-remote
104 105
  '((((class color) (background light)) :foreground "DarkOliveGreen4")
    (((class color) (background  dark)) :foreground "DarkSeaGreen2"))
106
  "Face for remote branch head labels shown in log buffer."
107
  :group 'magit-faces)
108

109 110 111 112 113 114
(defface magit-branch-remote-head
  '((((class color) (background light)) :inherit magit-branch-remote :box t)
    (((class color) (background  dark)) :inherit magit-branch-remote :box t))
  "Face for current branch."
  :group 'magit-faces)

115
(defface magit-branch-local
116 117
  '((((class color) (background light)) :foreground "SkyBlue4")
    (((class color) (background  dark)) :foreground "LightSkyBlue1"))
118
  "Face for local branches."
119 120
  :group 'magit-faces)

121 122
(defface magit-branch-current
  '((((class color) (background light)) :inherit magit-branch-local :box t)
123
    (((class color) (background  dark)) :inherit magit-branch-local :box t))
124
  "Face for current branch."
125 126
  :group 'magit-faces)

127 128 129 130 131 132 133 134
(defface magit-branch-upstream
  '((t :slant italic))
  "Face for upstream branch.
This face is only used in logs and it gets combined
 with `magit-branch-local', `magit-branch-remote'
and/or `magit-branch-remote-head'."
  :group 'magit-faces)

135
(defface magit-head
136
  '((((class color) (background light)) :inherit magit-branch-local)
137
    (((class color) (background  dark)) :inherit magit-branch-local))
138
  "Face for the symbolic ref `HEAD'."
139 140
  :group 'magit-faces)

141
(defface magit-refname
142 143
  '((((class color) (background light)) :foreground "grey30")
    (((class color) (background  dark)) :foreground "grey80"))
144
  "Face for refnames without a dedicated face."
145 146
  :group 'magit-faces)

147 148
(defface magit-refname-stash
  '((t :inherit magit-refname))
149
  "Face for stash refnames."
150 151
  :group 'magit-faces)

152
(defface magit-refname-wip
153
  '((t :inherit magit-refname))
154
  "Face for wip refnames."
155 156
  :group 'magit-faces)

157 158 159 160 161
(defface magit-refname-pullreq
  '((t :inherit magit-refname))
  "Face for pullreq refnames."
  :group 'magit-faces)

162 163 164
(defface magit-keyword
  '((t :inherit font-lock-string-face))
  "Face for parts of commit messages inside brackets."
165 166 167 168 169
  :group 'magit-faces)

(defface magit-keyword-squash
  '((t :inherit font-lock-warning-face))
  "Face for squash! and fixup! keywords in commit messages."
170 171
  :group 'magit-faces)

172 173 174 175 176 177
(defface magit-signature-good
  '((t :foreground "green"))
  "Face for good signatures."
  :group 'magit-faces)

(defface magit-signature-bad
178
  '((t :foreground "red" :weight bold))
179 180 181 182 183 184 185 186
  "Face for bad signatures."
  :group 'magit-faces)

(defface magit-signature-untrusted
  '((t :foreground "cyan"))
  "Face for good untrusted signatures."
  :group 'magit-faces)

187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
(defface magit-signature-expired
  '((t :foreground "orange"))
  "Face for signatures that have expired."
  :group 'magit-faces)

(defface magit-signature-expired-key
  '((t :inherit magit-signature-expired))
  "Face for signatures made by an expired key."
  :group 'magit-faces)

(defface magit-signature-revoked
  '((t :foreground "violet red"))
  "Face for signatures made by a revoked key."
  :group 'magit-faces)

(defface magit-signature-error
  '((t :foreground "firebrick3"))
  "Face for signatures that cannot be checked (e.g. missing key)."
  :group 'magit-faces)

207 208
(defface magit-cherry-unmatched
  '((t :foreground "cyan"))
209 210
  "Face for unmatched cherry commits."
  :group 'magit-faces)
211 212 213

(defface magit-cherry-equivalent
  '((t :foreground "magenta"))
214 215
  "Face for equivalent cherry commits."
  :group 'magit-faces)
216

217 218 219 220 221
(defface magit-filename
  '((t :weight normal))
  "Face for filenames."
  :group 'magit-faces)

222
;;; Dispatch Popup
223

Jonas Bernoulli's avatar
Jonas Bernoulli committed
224
;;;###autoload (autoload 'magit-dispatch-popup "magit" nil t)
225 226
(magit-define-popup magit-dispatch-popup
  "Popup console for dispatching other popups."
227
  :actions '("Popup and dwim commands"
228 229
             (?A "Cherry-picking"  magit-cherry-pick-popup)
             (?b "Branching"       magit-branch-popup)
230 231 232
             (?B "Bisecting"       magit-bisect-popup)
             (?c "Committing"      magit-commit-popup)
             (?d "Diffing"         magit-diff-popup)
233 234 235
             (?D "Change diffs"    magit-diff-refresh-popup)
             (?e "Ediff dwimming"  magit-ediff-dwim)
             (?E "Ediffing"        magit-ediff-popup)
236 237 238
             (?f "Fetching"        magit-fetch-popup)
             (?F "Pulling"         magit-pull-popup)
             (?l "Logging"         magit-log-popup)
239
             (?L "Change logs"     magit-log-refresh-popup)
240 241
             (?m "Merging"         magit-merge-popup)
             (?M "Remoting"        magit-remote-popup)
242
             (?o "Submodules"      magit-submodule-popup)
243
             (?O "Subtrees"        magit-subtree-popup)
244 245 246
             (?P "Pushing"         magit-push-popup)
             (?r "Rebasing"        magit-rebase-popup)
             (?t "Tagging"         magit-tag-popup)
247
             (?T "Notes"           magit-notes-popup)
248
             (?V "Reverting"       magit-revert-popup)
249 250
             (?w "Apply patches"   magit-am-popup)
             (?W "Format patches"  magit-patch-popup)
251
             (?X "Resetting"       magit-reset-popup)
252
             (?y "Show Refs"       magit-show-refs-popup)
253 254
             (?z "Stashing"        magit-stash-popup)
             (?! "Running"         magit-run-popup)
255
             (?% "Worktree"        magit-worktree-popup)
256 257 258 259
             (lambda ()
               (and (with-current-buffer magit-pre-popup-buffer
                      (derived-mode-p 'magit-mode))
                    (propertize "Applying changes" 'face 'magit-popup-heading)))
260 261 262 263 264 265 266
             (?a "Apply"           magit-apply)
             (?s "Stage"           magit-stage)
             (?u "Unstage"         magit-unstage)
             (?v "Reverse"         magit-reverse)
             (?S "Stage all"       magit-stage-modified)
             (?U "Unstage all"     magit-unstage-all)
             (?k "Discard"         magit-discard)
267 268 269 270
             (lambda ()
               (and (with-current-buffer magit-pre-popup-buffer
                      (derived-mode-p 'magit-mode))
                    (propertize "Essential commands" 'face 'magit-popup-heading)))
271
             (?g  "    refresh current buffer"   magit-refresh)
272
             ;; These bindings only work because of :setup-function.
273 274
             (?\t   "  toggle section at point"  magit-section-toggle)
             (?\r   "  visit thing at point"     magit-visit-thing)
275 276
             ;; This binding has no effect and only appears to do
             ;; so because it is identical to the global binding.
277
             ("C-h m" "show all key bindings"    describe-mode))
278
  :setup-function 'magit-dispatch-popup-setup
279 280 281 282
  :max-action-columns (lambda (heading)
                        (pcase heading
                          ("Popup and dwim commands" 4)
                          ("Applying changes" 3)
283
                          ("Essential commands" 1))))
284

285
(defvar magit-dispatch-popup-map
Jonas Bernoulli's avatar
Jonas Bernoulli committed
286
  (let ((map (make-sparse-keymap)))
287
    (set-keymap-parent map magit-popup-mode-map)
288 289 290 291 292 293
    (cond ((featurep 'jkl)
           (define-key map [tab]    'magit-invoke-popup-action)
           (define-key map [return] 'magit-invoke-popup-action))
          (t
           (define-key map (kbd "C-i") 'magit-invoke-popup-action)
           (define-key map (kbd "C-m") 'magit-invoke-popup-action)))
294 295 296
    map)
  "Keymap used by `magit-dispatch-popup'.")

297 298
(defun magit-dispatch-popup-setup (val def)
  (magit-popup-default-setup val def)
299 300 301 302
  (use-local-map magit-dispatch-popup-map)
  ;; This is necessary for users (i.e. me) who have broken the
  ;; connection between C-i (aka TAB) and tab, and C-m (aka RET)
  ;; and return.
303 304 305 306 307
  (magit-popup-put
   :actions (nconc (magit-popup-get :actions)
                   (list (make-magit-popup-event :key 'tab
                                                 :fun 'magit-section-toggle)
                         (make-magit-popup-event :key 'return
308
                                                 :fun 'magit-visit-thing)))))
309

310
;;; Git Popup
311

312 313 314 315
(defcustom magit-shell-command-verbose-prompt t
  "Whether to show the working directory when reading a command.
This affects `magit-git-command', `magit-git-command-topdir',
`magit-shell-command', and `magit-shell-command-topdir'."
316
  :package-version '(magit . "2.11.0")
317 318 319
  :group 'magit-commands
  :type 'boolean)

320 321
(defvar magit-git-command-history nil)

Jonas Bernoulli's avatar
Jonas Bernoulli committed
322
;;;###autoload (autoload 'magit-run-popup "magit" nil t)
323 324
(magit-define-popup magit-run-popup
  "Popup console for running raw Git commands."
325 326 327
  :actions '((?! "Git Subcommand (in topdir)" magit-git-command-topdir)
             (?k "Gitk"                       magit-run-gitk)
             (?p "Git Subcommand (in pwd)"    magit-git-command)
328
             (?a "Gitk --all"                 magit-run-gitk-all)
329
             (?s "Shell command (in topdir)"  magit-shell-command-topdir)
330 331 332
             (?b "Gitk --branches"            magit-run-gitk-branches)
             (?S "Shell command (in pwd)"     magit-shell-command)
             (?g "Git Gui"                    magit-run-git-gui))
333 334
  :default-action 'magit-git-command
  :max-action-columns 2)
335 336

;;;###autoload
337
(defun magit-git-command (command)
Philipp Stephani's avatar
Philipp Stephani committed
338
  "Execute COMMAND asynchronously; display output.
339 340 341 342 343 344

Interactively, prompt for COMMAND in the minibuffer. \"git \" is
used as initial input, but can be deleted to run another command.

With a prefix argument COMMAND is run in the top-level directory
of the current working tree, otherwise in `default-directory'."
345
  (interactive (list (magit-read-shell-command nil "git ")))
346
  (magit--shell-command command))
347

348
;;;###autoload
349
(defun magit-git-command-topdir (command)
Philipp Stephani's avatar
Philipp Stephani committed
350
  "Execute COMMAND asynchronously; display output.
351 352 353 354 355 356

Interactively, prompt for COMMAND in the minibuffer. \"git \" is
used as initial input, but can be deleted to run another command.

COMMAND is run in the top-level directory of the current
working tree."
357
  (interactive (list (magit-read-shell-command t "git ")))
358
  (magit--shell-command command (magit-toplevel)))
359 360

;;;###autoload
361
(defun magit-shell-command (command)
Philipp Stephani's avatar
Philipp Stephani committed
362
  "Execute COMMAND asynchronously; display output.
363 364 365 366

Interactively, prompt for COMMAND in the minibuffer.  With a
prefix argument COMMAND is run in the top-level directory of
the current working tree, otherwise in `default-directory'."
367
  (interactive (list (magit-read-shell-command)))
368
  (magit--shell-command command))
369 370

;;;###autoload
371
(defun magit-shell-command-topdir (command)
Philipp Stephani's avatar
Philipp Stephani committed
372
  "Execute COMMAND asynchronously; display output.
373 374 375

Interactively, prompt for COMMAND in the minibuffer.  COMMAND
is run in the top-level directory of the current working tree."
376
  (interactive (list (magit-read-shell-command t)))
377 378 379
  (magit--shell-command command (magit-toplevel)))

(defun magit--shell-command (command &optional directory)
380 381 382
  (let ((default-directory (or directory default-directory))
        (process-environment process-environment))
    (push "GIT_PAGER=cat" process-environment)
383 384 385
    (magit-start-process shell-file-name nil
                         shell-command-switch command))
  (magit-process-buffer))
386

387 388 389 390
(defun magit-read-shell-command (&optional toplevel initial-input)
  (let ((dir (abbreviate-file-name
              (if (or toplevel current-prefix-arg)
                  (or (magit-toplevel)
391
                      (magit--not-inside-repository-error))
392 393 394 395
                default-directory))))
    (read-shell-command (if magit-shell-command-verbose-prompt
                            (format "Async shell command in %s: " dir)
                          "Async shell command: ")
396
                        initial-input 'magit-git-command-history)))
397

398
;;; Font-Lock Keywords
399

400 401
(defconst magit-font-lock-keywords
  (eval-when-compile
402 403 404
    `((,(concat "(\\(magit-define-section-jumper\\)\\_>"
                "[ \t'\(]*"
                "\\(\\(?:\\sw\\|\\s_\\)+\\)?")
405 406
       (1 'font-lock-keyword-face)
       (2 'font-lock-function-name-face nil t))
407 408 409
      (,(concat "(" (regexp-opt '("magit-insert-section"
                                  "magit-section-case"
                                  "magit-bind-match-strings"
410
                                  "magit-with-temp-index"
411 412
                                  "magit-with-blob"
                                  "magit-with-toplevel") t)
413
                "\\_>")
414 415 416
       . 1))))

(font-lock-add-keywords 'emacs-lisp-mode magit-font-lock-keywords)
417

418
;;; Version
419

420 421 422 423
(defvar magit-version 'undefined
  "The version of Magit that you're using.
Use the function by the same name instead of this variable.")

424
;;;###autoload
425
(defun magit-version (&optional print-dest)
426
  "Return the version of Magit currently in use.
427
If optional argument PRINT-DEST is non-nil, output
428 429 430 431
stream (interactively, the echo area, or the current buffer with
a prefix argument), also print the used versions of Magit, Git,
and Emacs to it."
  (interactive (list (if current-prefix-arg (current-buffer) t)))
432
  (let ((magit-git-global-arguments nil)
433 434
        (toplib (or load-file-name buffer-file-name))
        debug)
435 436
    (unless (and toplib
                 (equal (file-name-nondirectory toplib) "magit.el"))
437 438
      (setq toplib (locate-library "magit.el")))
    (setq toplib (and toplib (file-chase-links toplib)))
439
    (push toplib debug)
440
    (when toplib
441
      (let* ((topdir (file-name-directory toplib))
442
             (gitdir (expand-file-name
443 444
                      ".git" (file-name-directory
                              (directory-file-name topdir))))
445 446
             (static (locate-library "magit-version.el" nil (list topdir)))
             (static (and static (file-chase-links static))))
447 448 449 450 451 452 453 454 455
        (or (progn
              (push 'repo debug)
              (when (and (file-exists-p gitdir)
                         ;; It is a repo, but is it the Magit repo?
                         (file-exists-p
                          (expand-file-name "../lisp/magit.el" gitdir)))
                (push t debug)
                ;; Inside the repo the version file should only exist
                ;; while running make.
456
                (when (and static (not noninteractive))
457 458 459 460 461 462
                  (ignore-errors (delete-file static)))
                (setq magit-version
                      (let ((default-directory topdir))
                        (magit-git-string "describe" "--tags" "--dirty")))))
            (progn
              (push 'static debug)
463
              (when (and static (file-exists-p static))
464 465 466 467 468 469 470 471 472 473 474
                (push t debug)
                (load-file static)
                magit-version))
            (when (featurep 'package)
              (push 'elpa debug)
              (ignore-errors
                (--when-let (assq 'magit package-alist)
                  (push t debug)
                  (setq magit-version
                        (and (fboundp 'package-desc-version)
                             (package-version-join
475 476
                              (package-desc-version (cadr it))))))))
            (progn
477
              (push 'dirname debug)
478 479 480 481 482
              (let ((dirname (file-name-nondirectory
                              (directory-file-name topdir))))
                (when (string-match "\\`magit-\\([0-9]\\{8\\}\\.[0-9]*\\)"
                                    dirname)
                  (setq magit-version (match-string 1 dirname))))))))
483
    (if (stringp magit-version)
484 485 486
        (when print-dest
          (princ (format "Magit %s, Git %s, Emacs %s, %s"
                         (or magit-version "(unknown)")
487 488 489 490 491 492
                         (or (let ((magit-git-debug
                                    (lambda (err)
                                      (display-warning '(magit git)
                                                       err :error))))
                               (magit-git-version t))
                             "(unknown)")
493 494 495
                         emacs-version
                         system-type)
                 print-dest))
496
      (setq debug (reverse debug))
497
      (setq magit-version 'error)
498 499
      (when magit-version
        (push magit-version debug))
500
      (unless (equal (getenv "TRAVIS") "true")
501 502
        ;; The repository is a sparse clone.
        (message "Cannot determine Magit's version %S" debug)))
503 504
    magit-version))

505 506
;;; Debugging Tools

507
(defun magit-debug-git-executable ()
508 509
  "Display a buffer with information about `magit-git-executable'.
See info node `(magit)Debugging Tools' for more information."
510 511 512 513
  (interactive)
  (with-current-buffer (get-buffer-create "*magit-git-debug*")
    (pop-to-buffer (current-buffer))
    (erase-buffer)
514 515
    (insert (concat
             (format "magit-git-executable: %S" magit-git-executable)
516 517
             (and (not (file-name-absolute-p magit-git-executable))
                  (format " [%S]" (executable-find magit-git-executable)))
518 519 520 521
             (format " (%s)\n"
                     (let* ((errmsg nil)
                            (magit-git-debug (lambda (err) (setq errmsg err))))
                       (or (magit-git-version t) errmsg)))))
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
    (insert (format "exec-path: %S\n" exec-path))
    (--when-let (cl-set-difference
                 (-filter #'file-exists-p (remq nil (parse-colon-path
                                                     (getenv "PATH"))))
                 (-filter #'file-exists-p (remq nil exec-path))
                 :test #'file-equal-p)
      (insert (format "  entries in PATH, but not in exec-path: %S\n" it)))
    (dolist (execdir exec-path)
      (insert (format "  %s (%s)\n" execdir (car (file-attributes execdir))))
      (when (file-directory-p execdir)
        (dolist (exec (directory-files
                       execdir t (concat
                                  "\\`git" (regexp-opt exec-suffixes) "\\'")))
          (insert (format "    %s (%s)\n" exec
                          (let* ((magit-git-executable exec)
                                 (errmsg nil)
                                 (magit-git-debug (lambda (err) (setq errmsg err))))
                            (or (magit-git-version t) errmsg)))))))))

541
;;; Startup Asserts
542

543
(defun magit-startup-asserts ()
544 545 546 547 548 549 550 551
  (when-let ((val (getenv "GIT_DIR")))
    (setenv "GIT_DIR")
    (message "Magit unset $GIT_DIR (was %S).  See \
https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val))
  (when-let ((val (getenv "GIT_WORK_TREE")))
    (setenv "GIT_WORK_TREE")
    (message "Magit unset $GIT_WORK_TREE (was %S).  See \
https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val))
552
  (let ((version (magit-git-version)))
553 554 555 556
    (when (and version
               (version< version magit--minimal-git)
               (not (equal (getenv "TRAVIS") "true")))
      (display-warning 'magit (format "\
557
Magit requires Git >= %s, you are using %s.
558 559 560 561 562 563 564 565 566 567 568 569

If this comes as a surprise to you, because you do actually have
a newer version installed, then that probably means that the
older version happens to appear earlier on the `$PATH'.  If you
always start Emacs from a shell, then that can be fixed in the
shell's init file.  If you start Emacs by clicking on an icon,
or using some sort of application launcher, then you probably
have to adjust the environment as seen by graphical interface.
For X11 something like ~/.xinitrc should work.

If you use Tramp to work inside remote Git repositories, then you
have to make sure a suitable Git is used on the remote machines
570 571
too.\n" magit--minimal-git version) :error)))
  (when (version< emacs-version magit--minimal-emacs)
572
    (display-warning 'magit (format "\
573
Magit requires Emacs >= %s, you are using %s.
574 575 576 577 578 579 580 581

If this comes as a surprise to you, because you do actually have
a newer version installed, then that probably means that the
older version happens to appear earlier on the `$PATH'.  If you
always start Emacs from a shell, then that can be fixed in the
shell's init file.  If you start Emacs by clicking on an icon,
or using some sort of application launcher, then you probably
have to adjust the environment as seen by graphical interface.
582 583
For X11 something like ~/.xinitrc should work.\n"
                                    magit--minimal-emacs emacs-version)
584
                     :error)))
585

586
;;; Loading Libraries
587

Remi Vanicat's avatar
Remi Vanicat committed
588
(provide 'magit)
Roger Crew's avatar
Roger Crew committed
589

590
(cl-eval-when (load eval)
591
  (require 'magit-status)
592
  (require 'magit-refs)
593
  (require 'magit-files)
594
  (require 'magit-collab)
595
  (require 'magit-reset)
596
  (require 'magit-branch)
597 598
  (require 'magit-merge)
  (require 'magit-tag)
599
  (require 'magit-worktree)
600
  (require 'magit-notes)
601 602 603
  (require 'magit-sequence)
  (require 'magit-commit)
  (require 'magit-remote)
604 605 606 607
  (require 'magit-clone)
  (require 'magit-fetch)
  (require 'magit-pull)
  (require 'magit-push)
608 609
  (require 'magit-bisect)
  (require 'magit-stash)
610
  (require 'magit-blame)
611
  (require 'magit-obsolete)
612
  (require 'magit-submodule)
613
  (unless (load "magit-autoloads" t t)
614
    (require 'magit-subtree)
615
    (require 'magit-ediff)
616
    (require 'magit-extras)
617
    (require 'git-rebase)
Yuri Khan's avatar
Yuri Khan committed
618 619 620 621 622
    (require 'magit-imenu)
    (require 'magit-bookmark)))

(eval-after-load 'bookmark
  '(require 'magit-bookmark))
623

624
(if after-init-time
625 626 627 628
    (progn (magit-startup-asserts)
           (magit-version))
  (add-hook 'after-init-hook #'magit-startup-asserts t)
  (add-hook 'after-init-hook #'magit-version t))
629

630
;;; magit.el ends here