From c8acbf81dd058141fa710cbdc5521d1303f505c3 Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Fri, 17 May 2019 12:04:33 +0200 Subject: [PATCH] update magit. --- bba.org | 5 + elpa/magit-1.2.0/dir | 18 - elpa/magit-1.2.0/magit-autoloads.el | 158 - elpa/magit-1.2.0/magit-bisect.el | 195 - elpa/magit-1.2.0/magit-blame.el | 303 - elpa/magit-1.2.0/magit-key-mode.el | 521 -- elpa/magit-1.2.0/magit-pkg.el | 1 - elpa/magit-1.2.0/magit-stgit.el | 288 - elpa/magit-1.2.0/magit-svn.el | 240 - elpa/magit-1.2.0/magit-topgit.el | 191 - elpa/magit-1.2.0/magit-wip.el | 153 - elpa/magit-1.2.0/magit.el | 6001 ----------------- elpa/magit-1.2.0/magit.el-e | 6001 ----------------- elpa/magit-1.2.0/magit.info | 1359 ---- elpa/magit-1.2.0/rebase-mode.el | 322 - elpa/magit-20190122.503/magit-bookmark.el | 371 - elpa/magit-20190122.503/magit-clone.el | 104 - elpa/magit-20190122.503/magit-gitignore.el | 98 - elpa/magit-20190122.503/magit-obsolete.el | 55 - elpa/magit-20190122.503/magit-patch.el | 188 - elpa/magit-20190122.503/magit-pkg.el | 10 - elpa/magit-20190122.503/magit-pull.el | 151 - elpa/magit-20190122.503/magit.info | 187 - .../AUTHORS.md | 10 + .../LICENSE | 0 .../dir | 0 .../git-rebase.el | 380 +- .../magit-apply.el | 72 +- .../magit-autoloads.el | 778 +-- .../magit-autorevert.el | 71 +- .../magit-bisect.el | 53 +- .../magit-blame.el | 113 +- elpa/magit-20190514.1814/magit-bookmark.el | 202 + .../magit-branch.el | 667 +- elpa/magit-20190514.1814/magit-clone.el | 267 + .../magit-commit.el | 205 +- .../magit-core.el | 11 +- .../magit-diff.el | 1609 +++-- .../magit-ediff.el | 37 +- .../magit-extras.el | 58 +- .../magit-fetch.el | 99 +- .../magit-files.el | 194 +- .../magit-git.el | 579 +- elpa/magit-20190514.1814/magit-gitignore.el | 155 + .../magit-imenu.el | 4 +- .../magit-log.el | 1115 ++- .../magit-margin.el | 22 +- .../magit-merge.el | 98 +- .../magit-mode.el | 471 +- .../magit-notes.el | 152 +- elpa/magit-20190514.1814/magit-obsolete.el | 103 + elpa/magit-20190514.1814/magit-patch.el | 267 + elpa/magit-20190514.1814/magit-pkg.el | 12 + .../magit-process.el | 84 +- elpa/magit-20190514.1814/magit-pull.el | 163 + .../magit-push.el | 276 +- elpa/magit-20190514.1814/magit-reflog.el | 211 + .../magit-refs.el | 184 +- .../magit-remote.el | 274 +- .../magit-repos.el | 21 +- .../magit-reset.el | 29 +- .../magit-section.el | 12 +- .../magit-sequence.el | 434 +- .../magit-stash.el | 147 +- .../magit-status.el | 214 +- .../magit-submodule.el | 136 +- .../magit-subtree.el | 147 +- .../magit-tag.el | 46 +- elpa/magit-20190514.1814/magit-transient.el | 198 + .../magit-utils.el | 109 +- .../magit-wip.el | 22 +- .../magit-worktree.el | 38 +- .../magit.el | 173 +- elpa/magit-20190514.1814/magit.info | 191 + .../magit.info-1 | 2524 ++++--- .../magit.info-2 | 1969 ++++-- .../dir | 0 .../magit-popup-autoloads.el | 0 .../magit-popup-pkg.el | 2 +- .../magit-popup.el | 21 +- .../magit-popup.info | 47 +- elpa/magit-popup-readme.txt | 17 +- elpa/magit-readme.txt | 8 + .../magit-todos-pkg.el | 2 - .../magit-todos-autoloads.el | 0 .../magit-todos-pkg.el | 2 + .../magit-todos.el | 179 +- 87 files changed, 9291 insertions(+), 23313 deletions(-) delete mode 100644 elpa/magit-1.2.0/dir delete mode 100644 elpa/magit-1.2.0/magit-autoloads.el delete mode 100644 elpa/magit-1.2.0/magit-bisect.el delete mode 100644 elpa/magit-1.2.0/magit-blame.el delete mode 100644 elpa/magit-1.2.0/magit-key-mode.el delete mode 100644 elpa/magit-1.2.0/magit-pkg.el delete mode 100644 elpa/magit-1.2.0/magit-stgit.el delete mode 100644 elpa/magit-1.2.0/magit-svn.el delete mode 100644 elpa/magit-1.2.0/magit-topgit.el delete mode 100644 elpa/magit-1.2.0/magit-wip.el delete mode 100644 elpa/magit-1.2.0/magit.el delete mode 100644 elpa/magit-1.2.0/magit.el-e delete mode 100644 elpa/magit-1.2.0/magit.info delete mode 100644 elpa/magit-1.2.0/rebase-mode.el delete mode 100644 elpa/magit-20190122.503/magit-bookmark.el delete mode 100644 elpa/magit-20190122.503/magit-clone.el delete mode 100644 elpa/magit-20190122.503/magit-gitignore.el delete mode 100644 elpa/magit-20190122.503/magit-obsolete.el delete mode 100644 elpa/magit-20190122.503/magit-patch.el delete mode 100644 elpa/magit-20190122.503/magit-pkg.el delete mode 100644 elpa/magit-20190122.503/magit-pull.el delete mode 100644 elpa/magit-20190122.503/magit.info rename elpa/{magit-20190122.503 => magit-20190514.1814}/AUTHORS.md (96%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/LICENSE (100%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/dir (100%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/git-rebase.el (62%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-apply.el (93%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-autoloads.el (81%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-autorevert.el (79%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-bisect.el (81%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-blame.el (93%) create mode 100644 elpa/magit-20190514.1814/magit-bookmark.el rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-branch.el (61%) create mode 100644 elpa/magit-20190514.1814/magit-clone.el rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-commit.el (79%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-core.el (93%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-diff.el (71%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-ediff.el (95%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-extras.el (93%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-fetch.el (59%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-files.el (73%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-git.el (85%) create mode 100644 elpa/magit-20190514.1814/magit-gitignore.el rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-imenu.el (99%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-log.el (64%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-margin.el (93%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-merge.el (79%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-mode.el (81%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-notes.el (57%) create mode 100644 elpa/magit-20190514.1814/magit-obsolete.el create mode 100644 elpa/magit-20190514.1814/magit-patch.el create mode 100644 elpa/magit-20190514.1814/magit-pkg.el rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-process.el (94%) create mode 100644 elpa/magit-20190514.1814/magit-pull.el rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-push.el (52%) create mode 100644 elpa/magit-20190514.1814/magit-reflog.el rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-refs.el (87%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-remote.el (59%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-repos.el (95%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-reset.el (83%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-section.el (99%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-sequence.el (73%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-stash.el (82%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-status.el (78%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-submodule.el (87%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-subtree.el (51%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-tag.el (86%) create mode 100644 elpa/magit-20190514.1814/magit-transient.el rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-utils.el (94%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-wip.el (96%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit-worktree.el (81%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit.el (78%) create mode 100644 elpa/magit-20190514.1814/magit.info rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit.info-1 (80%) rename elpa/{magit-20190122.503 => magit-20190514.1814}/magit.info-2 (75%) rename elpa/{magit-popup-20181204.2031 => magit-popup-20190223.2234}/dir (100%) rename elpa/{magit-popup-20181204.2031 => magit-popup-20190223.2234}/magit-popup-autoloads.el (100%) rename elpa/{magit-popup-20181204.2031 => magit-popup-20190223.2234}/magit-popup-pkg.el (83%) rename elpa/{magit-popup-20181204.2031 => magit-popup-20190223.2234}/magit-popup.el (98%) rename elpa/{magit-popup-20181204.2031 => magit-popup-20190223.2234}/magit-popup.info (96%) create mode 100644 elpa/magit-readme.txt delete mode 100644 elpa/magit-todos-20190114.1450/magit-todos-pkg.el rename elpa/{magit-todos-20190114.1450 => magit-todos-20190508.757}/magit-todos-autoloads.el (100%) create mode 100644 elpa/magit-todos-20190508.757/magit-todos-pkg.el rename elpa/{magit-todos-20190114.1450 => magit-todos-20190508.757}/magit-todos.el (87%) diff --git a/bba.org b/bba.org index d1be951e..4446bdc0 100644 --- a/bba.org +++ b/bba.org @@ -304,6 +304,9 @@ Display open TODO items in magit-status. #+BEGIN_SRC emacs-lisp :tangle yes (require 'magit-todos) (magit-todos-mode) + (setq magit-todos-keywords-list + (append '("BUGBUG") + magit-todos-keywords-list)) #+END_SRC do a stash, pull, pop. @@ -318,6 +321,8 @@ in the end use magit-stash. #+END_SRC #+BEGIN_SRC emacs-lisp :tangle yes + (require 'magit-gitflow) + (add-hook 'magit-mode-hook 'turn-on-magit-gitflow) #+END_SRC * fullframe diff --git a/elpa/magit-1.2.0/dir b/elpa/magit-1.2.0/dir deleted file mode 100644 index 2e646dbd..00000000 --- a/elpa/magit-1.2.0/dir +++ /dev/null @@ -1,18 +0,0 @@ -This is the file .../info/dir, which contains the -topmost node of the Info hierarchy, called (dir)Top. -The first time you invoke Info you start off looking at this node. - -File: dir, Node: Top This is the top of the INFO tree - - This (the Directory node) gives a menu of major topics. - Typing "q" exits, "?" lists all Info commands, "d" returns here, - "h" gives a primer for first-timers, - "mEmacs" visits the Emacs manual, etc. - - In Emacs, you can click mouse button 2 on a menu item or cross reference - to select it. - -* Menu: - -Emacs -* Magit: (magit). Using Git from Emacs with Magit. diff --git a/elpa/magit-1.2.0/magit-autoloads.el b/elpa/magit-1.2.0/magit-autoloads.el deleted file mode 100644 index 98afb1c2..00000000 --- a/elpa/magit-1.2.0/magit-autoloads.el +++ /dev/null @@ -1,158 +0,0 @@ -;;; magit-autoloads.el --- automatically extracted autoloads -;; -;;; Code: - - -;;;### (autoloads (magit-status) "magit" "magit.el" (21205 9255)) -;;; Generated autoloads from magit.el - -(autoload 'magit-status "magit" "\ -Open a Magit status buffer for the Git repository containing -DIR. If DIR is not within a Git repository, offer to create a -Git repository in DIR. - -Interactively, a prefix argument means to ask the user which Git -repository to use even if `default-directory' is under Git control. -Two prefix arguments means to ignore `magit-repo-dirs' when asking for -user input. - -\(fn DIR)" t nil) - -;;;*** - -;;;### (autoloads (magit-blame-mode) "magit-blame" "magit-blame.el" -;;;;;; (21205 9255)) -;;; Generated autoloads from magit-blame.el - -(autoload 'magit-blame-mode "magit-blame" "\ -Display blame information inline. - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads (turn-on-magit-stgit magit-stgit-mode) "magit-stgit" -;;;;;; "magit-stgit.el" (21205 9255)) -;;; Generated autoloads from magit-stgit.el - -(autoload 'magit-stgit-mode "magit-stgit" "\ -StGit support for Magit - -\(fn &optional ARG)" t nil) - -(autoload 'turn-on-magit-stgit "magit-stgit" "\ -Unconditionally turn on `magit-stgit-mode'. - -\(fn)" nil nil) - -;;;*** - -;;;### (autoloads (turn-on-magit-svn magit-svn-mode) "magit-svn" -;;;;;; "magit-svn.el" (21205 9255)) -;;; Generated autoloads from magit-svn.el - -(autoload 'magit-svn-mode "magit-svn" "\ -SVN support for Magit - -\(fn &optional ARG)" t nil) - -(autoload 'turn-on-magit-svn "magit-svn" "\ -Unconditionally turn on `magit-svn-mode'. - -\(fn)" nil nil) - -;;;*** - -;;;### (autoloads (turn-on-magit-topgit magit-topgit-mode) "magit-topgit" -;;;;;; "magit-topgit.el" (21205 9255)) -;;; Generated autoloads from magit-topgit.el - -(autoload 'magit-topgit-mode "magit-topgit" "\ -Topgit support for Magit - -\(fn &optional ARG)" t nil) - -(autoload 'turn-on-magit-topgit "magit-topgit" "\ -Unconditionally turn on `magit-topgit-mode'. - -\(fn)" nil nil) - -;;;*** - -;;;### (autoloads (global-magit-wip-save-mode magit-wip-save-mode -;;;;;; magit-wip-mode) "magit-wip" "magit-wip.el" (21205 9255)) -;;; Generated autoloads from magit-wip.el - -(defvar magit-wip-mode nil "\ -Non-nil if Magit-Wip mode is enabled. -See the command `magit-wip-mode' for a description of this minor mode. -Setting this variable directly does not take effect; -either customize it (see the info node `Easy Customization') -or call the function `magit-wip-mode'.") - -(custom-autoload 'magit-wip-mode "magit-wip" nil) - -(autoload 'magit-wip-mode "magit-wip" "\ -In Magit log buffers; give wip refs a special appearance. - -\(fn &optional ARG)" t nil) - -(autoload 'magit-wip-save-mode "magit-wip" "\ -Magit support for committing to a work-in-progress ref. - -When this minor mode is turned on and a file is saved inside a writable -git repository then it is also committed to a special work-in-progress -ref. - -\(fn &optional ARG)" t nil) - -(defvar global-magit-wip-save-mode nil "\ -Non-nil if Global-Magit-Wip-Save mode is enabled. -See the command `global-magit-wip-save-mode' for a description of this minor mode. -Setting this variable directly does not take effect; -either customize it (see the info node `Easy Customization') -or call the function `global-magit-wip-save-mode'.") - -(custom-autoload 'global-magit-wip-save-mode "magit-wip" nil) - -(autoload 'global-magit-wip-save-mode "magit-wip" "\ -Toggle Magit-Wip-Save mode in every possible buffer. -With prefix ARG, turn Global-Magit-Wip-Save mode on if and only if ARG is positive. -Magit-Wip-Save mode is enabled in all buffers where `turn-on-magit-wip-save' would do it. -See `magit-wip-save-mode' for more information on Magit-Wip-Save mode. - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads (rebase-mode) "rebase-mode" "rebase-mode.el" (21205 -;;;;;; 9256)) -;;; Generated autoloads from rebase-mode.el - -(autoload 'rebase-mode "rebase-mode" "\ -Major mode for editing of a Git rebase file. - -Rebase files are generated when you run 'git rebase -i' or run -`magit-interactive-rebase'. They describe how Git should perform -the rebase. See the documentation for git-rebase (e.g., by -running 'man git-rebase' at the command line) for details. - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("git-rebase-todo" . rebase-mode)) - -;;;*** - -;;;### (autoloads nil nil ("magit-bisect.el" "magit-key-mode.el" -;;;;;; "magit-pkg.el") (21205 9256 127962)) - -;;;*** - -(provide 'magit-autoloads) -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; magit-autoloads.el ends here diff --git a/elpa/magit-1.2.0/magit-bisect.el b/elpa/magit-1.2.0/magit-bisect.el deleted file mode 100644 index cdb6455e..00000000 --- a/elpa/magit-1.2.0/magit-bisect.el +++ /dev/null @@ -1,195 +0,0 @@ -(require 'magit) - -(defvar magit--bisect-last-pos) -(defvar magit--bisect-tmp-file) -(defvar magit--bisect-info nil) -(make-variable-buffer-local 'magit--bisect-info) -(put 'magit--bisect-info 'permanent-local t) - -(defun magit--bisecting-p (&optional required-status) - "Return t if a bisect session is running. -If REQUIRED-STATUS is not nil then the current status must also -match REQUIRED-STATUS." - (and (file-exists-p (concat (magit-git-dir) "BISECT_LOG")) - (or (not required-status) - (eq (plist-get (magit--bisect-info) :status) - required-status)))) - -(defun magit--bisect-info () - (with-current-buffer (magit-find-status-buffer) - (or (if (local-variable-p 'magit--bisect-info) magit--bisect-info) - (list :status (if (magit--bisecting-p) 'running 'not-running))))) - -(defun magit--bisect-cmd (&rest args) - "Run `git bisect ...' and update the status buffer" - (with-current-buffer (magit-find-status-buffer) - (let* ((output (apply 'magit-git-lines (append '("bisect") args))) - (cmd (car args)) - (first-line (car output))) - (save-match-data - (setq magit--bisect-info - (cond ((string= cmd "reset") - (list :status 'not-running)) - ;; Bisecting: 78 revisions left to test after this (roughly 6 steps) - ((string-match "^Bisecting:\\s-+\\([0-9]+\\).+roughly\\s-+\\([0-9]+\\)" first-line) - (list :status 'running - :revs (match-string 1 first-line) - :steps (match-string 2 first-line))) - ;; e2596955d9253a80aec9071c18079705597fa102 is the first bad commit - ((string-match "^\\([a-f0-9]+\\)\\s-.*first bad commit" first-line) - (list :status 'finished - :bad (match-string 1 first-line))) - (t - (list :status 'error))))))) - (magit-refresh)) - -(defun magit--bisect-info-for-status (branch) - "Return bisect info suitable for display in the status buffer" - (let* ((info (magit--bisect-info)) - (status (plist-get info :status))) - (cond ((eq status 'not-running) - (or branch "(detached)")) - ((eq status 'running) - (format "(bisecting; %s revisions & %s steps left)" - (or (plist-get info :revs) "unknown number of") - (or (plist-get info :steps) "unknown number of"))) - ((eq status 'finished) - (format "(bisected: first bad revision is %s)" (plist-get info :bad))) - (t - "(bisecting; unknown error occured)")))) - -(defun magit-bisect-start () - "Start a bisect session" - (interactive) - (if (magit--bisecting-p) - (error "Already bisecting")) - (let ((bad (magit-read-rev "Start bisect with known bad revision" "HEAD")) - (good (magit-read-rev "Good revision" (magit-default-rev)))) - (magit--bisect-cmd "start" bad good))) - -(defun magit-bisect-reset () - "Quit a bisect session" - (interactive) - (unless (magit--bisecting-p) - (error "Not bisecting")) - (magit--bisect-cmd "reset")) - -(defun magit-bisect-good () - "Tell git that the current revision is good during a bisect session" - (interactive) - (unless (magit--bisecting-p 'running) - (error "Not bisecting")) - (magit--bisect-cmd "good")) - -(defun magit-bisect-bad () - "Tell git that the current revision is bad during a bisect session" - (interactive) - (unless (magit--bisecting-p 'running) - (error "Not bisecting")) - (magit--bisect-cmd "bad")) - -(defun magit-bisect-skip () - "Tell git to skip the current revision during a bisect session." - (interactive) - (unless (magit--bisecting-p 'running) - (error "Not bisecting")) - (magit--bisect-cmd "skip")) - -(defun magit-bisect-log () - "Show the bisect log" - (interactive) - (unless (magit--bisecting-p) - (error "Not bisecting")) - (magit-run-git "bisect" "log") - (magit-display-process)) - -(defun magit-bisect-visualize () - "Show the remaining suspects with gitk" - (interactive) - (unless (magit--bisecting-p) - (error "Not bisecting")) - (magit-run-git "bisect" "visualize") - (unless (getenv "DISPLAY") - (magit-display-process))) - -(easy-mmode-defmap magit-bisect-minibuffer-local-map - '(("\C-i" . comint-dynamic-complete-filename)) - "Keymap for minibuffer prompting of rebase command." - :inherit minibuffer-local-map) - -(defvar magit-bisect-mode-history nil - "Previously run bisect commands.") - -(defun magit-bisect-run (command) - "Bisect automatically by running commands after each step" - (interactive - (list - (read-from-minibuffer "Run command (like this): " - "" - magit-bisect-minibuffer-local-map - nil - 'magit-bisect-mode-history))) - (unless (magit--bisecting-p) - (error "Not bisecting")) - (let ((file (make-temp-file "magit-bisect-run")) - buffer) - (with-temp-buffer - (insert "#!/bin/sh\n" command "\n") - (write-region (point-min) (point-max) file)) - (set-file-modes file #o755) - (magit-run-git-async "bisect" "run" file) - (magit-display-process) - (setq buffer (get-buffer magit-process-buffer-name)) - (with-current-buffer buffer - (set (make-local-variable 'magit--bisect-last-pos) 0) - (set (make-local-variable 'magit--bisect-tmp-file) file)) - (set-process-filter (get-buffer-process buffer) 'magit--bisect-run-filter) - (set-process-sentinel (get-buffer-process buffer) 'magit--bisect-run-sentinel))) - -(defun magit--bisect-run-filter (process output) - (with-current-buffer (process-buffer process) - (save-match-data - (let ((inhibit-read-only t) - line new-info) - (insert output) - (goto-char magit--bisect-last-pos) - (beginning-of-line) - (while (< (point) (point-max)) - (cond ( ;; Bisecting: 78 revisions left to test after this (roughly 6 steps) - (looking-at "^Bisecting:\\s-+\\([0-9]+\\).+roughly\\s-+\\([0-9]+\\)") - (setq new-info (list :status 'running - :revs (match-string 1) - :steps (match-string 2)))) - ( ;; e2596955d9253a80aec9071c18079705597fa102 is the first bad commit - (looking-at "^\\([a-f0-9]+\\)\\s-.*first bad commit") - (setq new-info (list :status 'finished - :bad (match-string 1))))) - (forward-line 1)) - (goto-char (point-max)) - (setq magit--bisect-last-pos (point)) - (if new-info - (with-current-buffer (magit-find-status-buffer) - (setq magit--bisect-info new-info) - (magit--bisect-update-status-buffer))))))) - -(defun magit--bisect-run-sentinel (process event) - (if (string-match-p "^finish" event) - (with-current-buffer (process-buffer process) - (delete-file magit--bisect-tmp-file))) - (magit-process-sentinel process event)) - -(defun magit--bisect-update-status-buffer () - (with-current-buffer (magit-find-status-buffer) - (save-excursion - (save-match-data - (let ((inhibit-read-only t)) - (goto-char (point-min)) - (when (search-forward-regexp "Local:" nil t) - (beginning-of-line) - (kill-line) - (insert (format "Local: %s %s" - (propertize (magit--bisect-info-for-status (magit-get-current-branch)) - 'face 'magit-branch) - (abbreviate-file-name default-directory))))))))) - -(provide 'magit-bisect) diff --git a/elpa/magit-1.2.0/magit-blame.el b/elpa/magit-1.2.0/magit-blame.el deleted file mode 100644 index 8518dcb4..00000000 --- a/elpa/magit-1.2.0/magit-blame.el +++ /dev/null @@ -1,303 +0,0 @@ -;;; magit-blame.el --- blame support for magit - -;; Copyright (C) 2012 Rüdiger Sonderfeld -;; Copyright (C) 2012 Yann Hodique -;; Copyright (C) 2011 byplayer -;; Copyright (C) 2010 Alexander Prusov -;; Copyright (C) 2009 Tim Moore -;; Copyright (C) 2008 Linh Dang -;; Copyright (C) 2008 Marius Vollmer - -;; Author: Yann Hodique -;; Keywords: - -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see . - -;;; Commentary: - -;; This code has been backported from Egg (Magit fork) to Magit - -;;; Code: - -(eval-when-compile (require 'cl)) -(require 'magit) - -(defface magit-blame-header - '((t :inherit magit-header)) - "Face for blame header." - :group 'magit-faces) - -(defface magit-blame-sha1 - '((t :inherit (magit-log-sha1 - magit-blame-header))) - "Face for blame sha1." - :group 'magit-faces) - -(defface magit-blame-culprit - '((t :inherit magit-blame-header)) - "Face for blame culprit." - :group 'magit-faces) - -(defface magit-blame-time - '((t :inherit magit-blame-header)) - "Face for blame time." - :group 'magit-faces) - -(defface magit-blame-subject - '((t :inherit (magit-log-message magit-blame-header))) - "Face for blame tag line." - :group 'magit-faces) - -(defconst magit-blame-map - (let ((map (make-sparse-keymap "Magit:Blame"))) - (define-key map (kbd "l") 'magit-blame-locate-commit) - (define-key map (kbd "RET") 'magit-blame-locate-commit) - (define-key map (kbd "q") 'magit-blame-mode) - (define-key map (kbd "n") 'magit-blame-next-chunk) - (define-key map (kbd "p") 'magit-blame-previous-chunk) - map) - "Keymap for an annotated section.\\{magit-blame-map}") - -(defvar magit-blame-buffer-read-only) -(make-variable-buffer-local 'magit-blame-buffer-read-only) - -;;;###autoload -(define-minor-mode magit-blame-mode - "Display blame information inline." - :keymap magit-blame-map - :lighter " blame" - (unless (buffer-file-name) - (error "Current buffer has no associated file!")) - (when (and (buffer-modified-p) - (y-or-n-p (format "save %s first? " (buffer-file-name)))) - (save-buffer)) - - (if magit-blame-mode - (progn - (setq magit-blame-buffer-read-only buffer-read-only) - (magit-blame-file-on (current-buffer)) - (set-buffer-modified-p nil) - (setq buffer-read-only t)) - (magit-blame-file-off (current-buffer)) - (set-buffer-modified-p nil) - (setq buffer-read-only magit-blame-buffer-read-only))) - -(defun magit-blame-file-off (buffer) - (save-excursion - (save-restriction - (with-current-buffer buffer - (widen) - (mapc (lambda (ov) - (if (overlay-get ov :blame) - (delete-overlay ov))) - (overlays-in (point-min) (point-max))))))) - -(defun magit-blame-file-on (buffer) - (magit-blame-file-off buffer) - (save-excursion - (with-current-buffer buffer - (save-restriction - (with-temp-buffer - (magit-git-insert (list "blame" "--porcelain" "--" - (file-name-nondirectory - (buffer-file-name buffer)))) - (magit-blame-parse buffer (current-buffer))))))) - -(defun magit-blame-locate-commit (pos) - "Jump to a commit in the branch history from an annotated blame section." - (interactive "d") - (let ((overlays (overlays-at pos)) - sha1) - (dolist (ov overlays) - (if (overlay-get ov :blame) - (setq sha1 (plist-get (nth 3 (overlay-get ov :blame)) :sha1)))) - (if sha1 - (magit-show-commit sha1)))) - -(defun magit-find-next-overlay-change (BEG END PROP) - "Return the next position after BEG where an overlay matching a -property PROP starts or ends. If there are no matching overlay -boundaries from BEG to END, the return value is nil." - (save-excursion - (goto-char BEG) - (catch 'found - (flet ((overlay-change (pos) - (if (< BEG END) (next-overlay-change pos) - (previous-overlay-change pos))) - (within-bounds-p (pos) - (if (< BEG END) (< pos END) - (> pos END)))) - (let ((ov-pos BEG)) - ;; iterate through overlay changes from BEG to END - (while (within-bounds-p ov-pos) - (let* ((next-ov-pos (overlay-change ov-pos)) - ;; search for an overlay with a PROP property - (next-ov - (let ((overlays (overlays-at next-ov-pos))) - (while (and overlays - (not (overlay-get (car overlays) PROP))) - (setq overlays (cdr overlays))) - (car overlays)))) - (if next-ov - ;; found the next overlay with prop PROP at next-ov-pos - (throw 'found next-ov-pos) - ;; no matching overlay found, keep looking - (setq ov-pos next-ov-pos))))))))) - -(defun magit-blame-next-chunk (pos) - "Go to the next blame chunk." - (interactive "d") - (let ((next-chunk-pos (magit-find-next-overlay-change pos (point-max) :blame))) - (when next-chunk-pos - (goto-char next-chunk-pos)))) - -(defun magit-blame-previous-chunk (pos) - "Go to the previous blame chunk." - (interactive "d") - (let ((prev-chunk-pos (magit-find-next-overlay-change pos (point-min) :blame))) - (when prev-chunk-pos - (goto-char prev-chunk-pos)))) - -(defcustom magit-time-format-string "%Y-%m-%dT%T%z" - "How to format time in magit-blame header." - :group 'magit - :type 'string) - -(defun magit-blame-decode-time (unixtime &optional tz) - "Decode UNIXTIME into (HIGH LOW) format. - -The second argument TZ can be used to add the timezone in (-)HHMM -format to UNIXTIME. UNIXTIME should be either a number -containing seconds since epoch or Emacs's (HIGH LOW -. IGNORED) format." - (when (numberp tz) - (unless (numberp unixtime) - (setq unixtime (float-time unixtime))) - (let* ((ptz (abs tz)) - (min (+ (* (/ ptz 100) 60) - (mod ptz 100)))) - (setq unixtime (+ (* (if (< tz 0) (- min) min) 60) unixtime)))) - - (when (numberp unixtime) - (setq unixtime (seconds-to-time unixtime))) - unixtime) - -(defun magit-blame-format-time-string (format &optional unixtime tz) - "Use FORMAT to format the time UNIXTIME, or now if omitted. - -UNIXTIME is specified as a number containing seconds since epoch -or Emacs's (HIGH LOW . IGNORED) format. The optional argument TZ -can be used to set the time zone. If TZ is a number it is -treated as a (-)HHMM offset to Universal Time. If TZ is not -a number and non-nil the time is printed in UTC. If TZ is nil -the local zime zone is used. The format of the function is -similar to `format-time-string' except for %Z which is not -officially supported at the moment." - (unless unixtime - (setq unixtime (current-time))) - (when (numberp tz) ;; TODO add support for %Z - (setq format (replace-regexp-in-string "%z" (format "%+05d" tz) format))) - (format-time-string format (magit-blame-decode-time unixtime tz) tz)) - -(defun magit-blame-parse (target-buf blame-buf) - "Parse blame-info in buffer BLAME-BUF and decorate TARGET-BUF buffer." - (save-match-data - (let ((blank (propertize " " 'face 'magit-blame-header)) - (nl (propertize "\n" 'face 'magit-blame-header)) - (commit-hash (make-hash-table :test 'equal :size 577)) - commit commit-info old-line new-line num old-file subject author - author-time author-timezone info ov beg end blame) - (with-current-buffer blame-buf - (goto-char (point-min)) - ;; search for a ful commit info - (while (re-search-forward "^\\([0-9a-f]\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)$" nil t) - (setq commit (match-string-no-properties 1) - old-line (string-to-number - (match-string-no-properties 2)) - new-line (string-to-number - (match-string-no-properties 3)) - num (string-to-number - (match-string-no-properties 4))) - ;; was this commit already seen (and stored in the hash)? - (setq commit-info (gethash commit commit-hash)) - ;; Nope, this is the 1st time, the full commit-info follow. - (unless commit-info - (re-search-forward "^author \\(.+\\)$") - (setq author (match-string-no-properties 1)) - (re-search-forward "^author-time \\(.+\\)$") - (setq author-time (string-to-number - (match-string-no-properties 1))) - (re-search-forward "^author-tz \\(.+\\)$") - (setq author-timezone (string-to-number - (match-string-no-properties 1))) - (re-search-forward "^summary \\(.+\\)$") - (setq subject (match-string-no-properties 1)) - (re-search-forward "^filename \\(.+\\)$") - (setq old-file (match-string-no-properties 1)) - (setq commit-info (list :sha1 commit :author author - :author-time author-time - :author-timezone author-timezone - :subject subject :file old-file)) - ;; save it in the hash - (puthash commit commit-info commit-hash)) - ;; add the current blame-block into the list INFO. - (setq info (cons (list old-line new-line num commit-info) - info)))) - ;; now do from beginning - (setq info (nreverse info)) - (with-current-buffer target-buf - ;; for every blame chunk - (dolist (chunk info) - (setq commit-info (nth 3 chunk) - old-line (nth 0 chunk) - new-line (nth 1 chunk) - num (nth 2 chunk) - commit (plist-get commit-info :sha1) - author (plist-get commit-info :author) - author-time (plist-get commit-info :author-time) - author-timezone (plist-get commit-info :author-timezone) - subject (plist-get commit-info :subject)) - - (goto-char (point-min)) - (forward-line (1- new-line)) - - (setq beg (line-beginning-position) - end (save-excursion - (forward-line num) - (line-beginning-position))) - ;; mark the blame chunk - (put-text-property beg end :blame chunk) - - ;; make an overlay with blame info as 'before-string - ;; on the current chunk. - (setq ov (make-overlay beg end)) - (overlay-put ov :blame chunk) - (setq blame (concat - (propertize (substring-no-properties commit 0 8) - 'face 'magit-blame-sha1) - blank - (propertize (format "%-20s" author) - 'face 'magit-blame-culprit) - blank - (propertize (magit-blame-format-time-string - magit-time-format-string - author-time author-timezone) - 'face 'magit-blame-time) - blank - (propertize subject 'face 'magit-blame-subject) - blank nl)) - (overlay-put ov 'before-string blame)))))) - -(provide 'magit-blame) -;;; magit-blame.el ends here diff --git a/elpa/magit-1.2.0/magit-key-mode.el b/elpa/magit-1.2.0/magit-key-mode.el deleted file mode 100644 index 2fcf2964..00000000 --- a/elpa/magit-1.2.0/magit-key-mode.el +++ /dev/null @@ -1,521 +0,0 @@ -(require 'magit) - -(eval-when-compile (require 'cl)) - -(defvar magit-key-mode-key-maps '() - "This will be filled lazily with proper `define-key' built - keymaps as they're requested.") - -(defvar magit-key-mode-buf-name "*magit-key*" - "Name of the buffer.") - -(defvar magit-key-mode-current-args '() - "Will contain the arguments to be passed to git.") - -(defvar magit-key-mode-current-options '() - "Will contain the arguments to be passed to git.") - -(defvar magit-log-mode-window-conf nil - "Will hold the pre-menu configuration of magit.") - -(defvar magit-key-mode-groups - '((logging - (man-page "git-log") - (actions - ("l" "Short" magit-log) - ("L" "Long" magit-log-long) - ("h" "Reflog" magit-reflog) - ("rl" "Ranged short" magit-log-ranged) - ("rL" "Ranged long" magit-log-long-ranged) - ("rh" "Ranged reflog" magit-reflog-ranged)) - (switches - ("-m" "Only merge commits" "--merges") - ("-f" "First parent" "--first-parent") - ("-i" "Case insensitive patterns" "-i") - ("-pr" "Pickaxe regex" "--pickaxe-regex") - ("-n" "Name only" "--name-only") - ("-am" "All match" "--all-match") - ("-al" "All" "--all")) - (arguments - ("=r" "Relative" "--relative=" read-directory-name) - ("=c" "Committer" "--committer=" read-from-minibuffer) - ("=>" "Since" "--since=" read-from-minibuffer) - ("=<" "Before" "--before=" read-from-minibuffer) - ("=s" "Pickaxe search" "-S" read-from-minibuffer) - ("=a" "Author" "--author=" read-from-minibuffer) - ("=g" "Grep" "--grep=" read-from-minibuffer))) - - (running - (actions - ("!" "Command from root" magit-shell-command) - (":" "Git command" magit-git-command) - ("g" "git gui" magit-run-git-gui) - ("k" "gitk" magit-run-gitk))) - - (fetching - (man-page "git-fetch") - (actions - ("f" "Current" magit-fetch-current) - ("a" "All" magit-remote-update) - ("o" "Other" magit-fetch)) - (switches - ("-p" "Prune" "--prune"))) - - (pushing - (man-page "git-push") - (actions - ("P" "Push" magit-push) - ("t" "Push tags" magit-push-tags)) - (switches - ("-f" "Force" "--force") - ("-d" "Dry run" "-n") - ("-u" "Set upstream" "-u"))) - - (pulling - (man-page "git-pull") - (actions - ("F" "Pull" magit-pull)) - (switches - ("-r" "Rebase" "--rebase"))) - - (branching - (man-page "git-branch") - (actions - ("v" "Branch manager" magit-branch-manager) - ("c" "Create" magit-create-branch) - ("r" "Rename" magit-move-branch) - ("k" "Delete" magit-delete-branch) - ("b" "Checkout" magit-checkout))) - - (remoting - (man-page "git-remote") - (actions - ("v" "Branch manager" magit-branch-manager) - ("a" "Add" magit-add-remote) - ("r" "Rename" magit-rename-remote) - ("k" "Remove" magit-remove-remote))) - - (tagging - (man-page "git-tag") - (actions - ("t" "Lightweight" magit-tag) - ("a" "Annotated" magit-annotated-tag)) - (switches - ("-f" "Force" "-f"))) - - (stashing - (man-page "git-stash") - (actions - ("z" "Save" magit-stash) - ("s" "Snapshot" magit-stash-snapshot)) - (switches - ("-k" "Keep index" "--keep-index") - ("-u" "Include untracked files" "--include-untracked") - ("-a" "Include all files" "--all"))) - - (merging - (man-page "git-merge") - (actions - ("m" "Merge" magit-manual-merge)) - (switches - ("-ff" "Fast-forward only" "--ff-only") - ("-nf" "No fast-forward" "--no-ff") - ("-sq" "Squash" "--squash")) - (arguments - ("-st" "Strategy" "--strategy=" read-from-minibuffer))) - - (rewriting - (actions - ("b" "Begin" magit-rewrite-start) - ("s" "Stop" magit-rewrite-stop) - ("a" "Abort" magit-rewrite-abort) - ("f" "Finish" magit-rewrite-finish) - ("*" "Set unused" magit-rewrite-set-unused) - ("." "Set used" magit-rewrite-set-used))) - - (submodule - (man-page "git-submodule") - (actions - ("u" "Update" magit-submodule-update) - ("b" "Both update and init" magit-submodule-update-init) - ("i" "Init" magit-submodule-init) - ("s" "Sync" magit-submodule-sync))) - - (bisecting - (man-page "git-bisect") - (actions - ("b" "Bad" magit-bisect-bad) - ("g" "Good" magit-bisect-good) - ("k" "Skip" magit-bisect-skip) - ("l" "Log" magit-bisect-log) - ("r" "Reset" magit-bisect-reset) - ("s" "Start" magit-bisect-start) - ("u" "Run" magit-bisect-run) - ("v" "Visualize" magit-bisect-visualize)))) - "Holds the key, help, function mapping for the log-mode. If you - modify this make sure you reset `magit-key-mode-key-maps' to - nil.") - -(defun magit-key-mode-delete-group (group) - "Delete a group from `magit-key-mode-key-maps'." - (let ((items (assoc group magit-key-mode-groups))) - (when items - ;; reset the cache - (setq magit-key-mode-key-maps nil) - ;; delete the whole group - (setq magit-key-mode-groups - (delq items magit-key-mode-groups)) - ;; unbind the defun - (magit-key-mode-de-generate group)) - magit-key-mode-groups)) - -(defun magit-key-mode-add-group (group) - "Add a new group to `magit-key-mode-key-maps'. If there's -already a group of that name then this will completely remove it -and put in its place an empty one of the same name." - (when (assoc group magit-key-mode-groups) - (magit-key-mode-delete-group group)) - (setq magit-key-mode-groups - (cons (list group (list 'actions)) magit-key-mode-groups))) - -(defun magit-key-mode-key-defined-p (for-group key) - "If KEY is defined as any of switch, argument or action within -FOR-GROUP then return t" - (catch 'result - (let ((options (magit-key-mode-options-for-group for-group))) - (dolist (type '(actions switches arguments)) - (when (assoc key (assoc type options)) - (throw 'result t)))))) - -(defun magit-key-mode-update-group (for-group thing &rest args) - "Abstraction for setting values in `magit-key-mode-key-maps'." - (let* ((options (magit-key-mode-options-for-group for-group)) - (things (assoc thing options)) - (key (car args))) - (if (cdr things) - (if (magit-key-mode-key-defined-p for-group key) - (error "%s is already defined in the %s group." key for-group) - (setcdr (cdr things) (cons args (cddr things)))) - (setcdr things (list args))) - (setq magit-key-mode-key-maps nil) - things)) - -(defun magit-key-mode-insert-argument (for-group key desc arg read-func) - "Add a new binding (KEY) in FOR-GROUP which will use READ-FUNC -to receive input to apply to argument ARG git is run. DESC should -be a brief description of the binding." - (magit-key-mode-update-group for-group 'arguments key desc arg read-func)) - -(defun magit-key-mode-insert-switch (for-group key desc switch) - "Add a new binding (KEY) in FOR-GROUP which will add SWITCH to git's -command line when it runs. DESC should be a brief description of -the binding." - (magit-key-mode-update-group for-group 'switches key desc switch)) - -(defun magit-key-mode-insert-action (for-group key desc func) - "Add a new binding (KEY) in FOR-GROUP which will run command -FUNC. DESC should be a brief description of the binding." - (magit-key-mode-update-group for-group 'actions key desc func)) - -(defun magit-key-mode-options-for-group (for-group) - "Retrieve the options (switches, commands and arguments) for -the group FOR-GROUP." - (or (cdr (assoc for-group magit-key-mode-groups)) - (error "Unknown group '%s'" for-group))) - -(defun magit-key-mode-help (for-group) - "Provide help for a key (which the user is prompted for) within -FOR-GROUP." - (let* ((opts (magit-key-mode-options-for-group for-group)) - (man-page (cadr (assoc 'man-page opts))) - (seq (read-key-sequence - (format "Enter command prefix%s: " - (if man-page - (format ", `?' for man `%s'" man-page) - "")))) - (actions (cdr (assoc 'actions opts)))) - (cond - ;; if it is an action popup the help for the to-be-run function - ((assoc seq actions) (describe-function (nth 2 (assoc seq actions)))) - ;; if there is "?" show a man page if there is one - ((equal seq "?") - (if man-page - (man man-page) - (error "No man page associated with `%s'" for-group))) - (t (error "No help associated with `%s'" seq))))) - -(defun magit-key-mode-exec-at-point () - "Run action/args/option at point." - (interactive) - (let* ((key (or (get-text-property (point) 'key-group-executor) - (error "Nothing at point to do."))) - (def (lookup-key (current-local-map) key))) - (call-interactively def))) -(defun magit-key-mode-jump-to-next-exec () - "Jump to the next action/args/option point." - (interactive) - (let* ((oldp (point)) - (old (get-text-property oldp 'key-group-executor)) - (p (if (= oldp (point-max)) (point-min) (1+ oldp)))) - (while (let ((new (get-text-property p 'key-group-executor))) - (and (not (= p oldp)) (or (not new) (eq new old)))) - (setq p (if (= p (point-max)) (point-min) (1+ p)))) - (goto-char p) - (skip-chars-forward " "))) - -(defun magit-key-mode-build-keymap (for-group) - "Construct a normal looking keymap for the key mode to use and -put it in magit-key-mode-key-maps for fast lookup." - (let* ((options (magit-key-mode-options-for-group for-group)) - (actions (cdr (assoc 'actions options))) - (switches (cdr (assoc 'switches options))) - (arguments (cdr (assoc 'arguments options))) - (map (make-sparse-keymap))) - (suppress-keymap map 'nodigits) - ;; ret dwim - (define-key map (kbd "RET") 'magit-key-mode-exec-at-point) - ;; tab jumps to the next "button" - (define-key map (kbd "TAB") 'magit-key-mode-jump-to-next-exec) - - ;; all maps should `quit' with `C-g' or `q' - (define-key map (kbd "C-g") `(lambda () - (interactive) - (magit-key-mode-command nil))) - (define-key map (kbd "q") `(lambda () - (interactive) - (magit-key-mode-command nil))) - ;; run help - (define-key map (kbd "?") `(lambda () - (interactive) - (magit-key-mode-help ',for-group))) - - (flet ((defkey (k action) - (when (and (lookup-key map (car k)) - (not (numberp (lookup-key map (car k))))) - (message "Warning: overriding binding for `%s' in %S" - (car k) for-group) - (ding) - (sit-for 2)) - (define-key map (car k) - `(lambda () (interactive) ,action)))) - (when actions - (dolist (k actions) - (defkey k `(magit-key-mode-command ',(nth 2 k))))) - (when switches - (dolist (k switches) - (defkey k `(magit-key-mode-add-option ',for-group ,(nth 2 k))))) - (when arguments - (dolist (k arguments) - (defkey k `(magit-key-mode-add-argument - ',for-group ,(nth 2 k) ',(nth 3 k)))))) - - (push (cons for-group map) magit-key-mode-key-maps) - map)) - -(defvar magit-key-mode-prefix nil - "For internal use. Holds the prefix argument to the command -that brought up the key-mode window, so it can be used by the -command that's eventually invoked.") - -(defun magit-key-mode-command (func) - (let ((args '())) - ;; why can't maphash return a list?! - (maphash (lambda (k v) - (push (concat k (shell-quote-argument v)) args)) - magit-key-mode-current-args) - (let ((magit-custom-options (append args magit-key-mode-current-options)) - (current-prefix-arg (or current-prefix-arg magit-key-mode-prefix))) - (set-window-configuration magit-log-mode-window-conf) - (when func - (call-interactively func)) - (magit-key-mode-kill-buffer)))) - -(defvar magit-key-mode-current-args nil - "A hash-table of current argument set (which will eventually - make it to the git command-line).") - -(defun magit-key-mode-add-argument (for-group arg-name input-func) - (let ((input (funcall input-func (concat arg-name ": ")))) - (puthash arg-name input magit-key-mode-current-args) - (magit-key-mode-redraw for-group))) - -(defvar magit-key-mode-current-options '() - "Current option set (which will eventually make it to the git - command-line).") - -(defun magit-key-mode-add-option (for-group option-name) - "Toggles the appearance of OPTION-NAME in -`magit-key-mode-current-options'." - (if (not (member option-name magit-key-mode-current-options)) - (add-to-list 'magit-key-mode-current-options option-name) - (setq magit-key-mode-current-options - (delete option-name magit-key-mode-current-options))) - (magit-key-mode-redraw for-group)) - -(defun magit-key-mode-kill-buffer () - (interactive) - (kill-buffer magit-key-mode-buf-name)) - -(defvar magit-log-mode-window-conf nil - "Pre-popup window configuration.") - -(defun magit-key-mode (for-group &optional original-opts) - "Mode for magit key selection. All commands, switches and -options can be toggled/actioned with the key combination -highlighted before the description." - (interactive) - ;; save the window config to restore it as was (no need to make this - ;; buffer local) - (setq magit-log-mode-window-conf - (current-window-configuration)) - ;; setup the mode, draw the buffer - (let ((buf (get-buffer-create magit-key-mode-buf-name))) - (delete-other-windows) - (split-window-vertically) - (other-window 1) - (switch-to-buffer buf) - (kill-all-local-variables) - (set (make-local-variable - 'magit-key-mode-current-options) - original-opts) - (set (make-local-variable - 'magit-key-mode-current-args) - (make-hash-table)) - (set (make-local-variable 'magit-key-mode-prefix) current-prefix-arg) - (magit-key-mode-redraw for-group)) - (message - (concat - "Type a prefix key to toggle it. Run 'actions' with their prefixes. " - "'?' for more help."))) - -(defun magit-key-mode-get-key-map (for-group) - "Get or build the keymap for FOR-GROUP." - (or (cdr (assoc for-group magit-key-mode-key-maps)) - (magit-key-mode-build-keymap for-group))) - -(defun magit-key-mode-redraw (for-group) - "(re)draw the magit key buffer." - (let ((buffer-read-only nil) - (old-point (point)) - (is-first (zerop (buffer-size))) - (actions-p nil)) - (erase-buffer) - (make-local-variable 'font-lock-defaults) - (use-local-map (magit-key-mode-get-key-map for-group)) - (setq actions-p (magit-key-mode-draw for-group)) - (delete-trailing-whitespace) - (setq mode-name "magit-key-mode" major-mode 'magit-key-mode) - (if (and is-first actions-p) - (progn (goto-char actions-p) - (magit-key-mode-jump-to-next-exec)) - (goto-char old-point))) - (setq buffer-read-only t) - (fit-window-to-buffer)) - -(defun magit-key-mode-draw-header (header) - "Draw a header with the correct face." - (insert (propertize header 'face 'font-lock-keyword-face) "\n")) - -(defvar magit-key-mode-args-in-cols nil - "When true, draw arguments in columns as with switches and - options.") - -(defun magit-key-mode-draw-args (args) - "Draw the args part of the menu." - (magit-key-mode-draw-buttons - "Args" - args - (lambda (x) - (format "(%s) %s" - (nth 2 x) - (propertize (gethash (nth 2 x) magit-key-mode-current-args "") - 'face 'widget-field))) - (not magit-key-mode-args-in-cols))) - -(defun magit-key-mode-draw-switches (switches) - "Draw the switches part of the menu." - (magit-key-mode-draw-buttons - "Switches" - switches - (lambda (x) - (format "(%s)" (let ((s (nth 2 x))) - (if (member s magit-key-mode-current-options) - (propertize s 'face 'font-lock-warning-face) - s)))))) - -(defun magit-key-mode-draw-actions (actions) - "Draw the actions part of the menu." - (magit-key-mode-draw-buttons "Actions" actions nil)) - -(defun magit-key-mode-draw-buttons (section xs maker - &optional one-col-each) - (when xs - (magit-key-mode-draw-header section) - (magit-key-mode-draw-in-cols - (mapcar (lambda (x) - (let* ((head (propertize (car x) 'face 'font-lock-builtin-face)) - (desc (nth 1 x)) - (more (and maker (funcall maker x))) - (text (format " %s: %s%s%s" - head desc (if more " " "") (or more "")))) - (propertize text 'key-group-executor (car x)))) - xs) - one-col-each))) - -(defun magit-key-mode-draw-in-cols (strings one-col-each) - "Given a list of strings, print in columns (using `insert'). If -ONE-COL-EACH is true then don't columify, but rather, draw each -item on one line." - (let ((longest-act (apply 'max (mapcar 'length strings)))) - (while strings - (let ((str (car strings))) - (let ((padding (make-string (- (+ longest-act 3) (length str)) ? ))) - (insert str) - (if (or one-col-each - (and (> (+ (length padding) ; - (current-column) - longest-act) - (window-width)) - (cdr strings))) - (insert "\n") - (insert padding)))) - (setq strings (cdr strings)))) - (insert "\n")) - -(defun magit-key-mode-draw (for-group) - "Function used to draw actions, switches and parameters. - -Returns the point before the actions part, if any." - (let* ((options (magit-key-mode-options-for-group for-group)) - (switches (cdr (assoc 'switches options))) - (arguments (cdr (assoc 'arguments options))) - (actions (cdr (assoc 'actions options))) - (p nil)) - (magit-key-mode-draw-switches switches) - (magit-key-mode-draw-args arguments) - (when actions (setq p (point-marker))) - (magit-key-mode-draw-actions actions) - (insert "\n") - p)) - -(defun magit-key-mode-de-generate (group) - "Unbind the function for GROUP." - (fmakunbound - (intern (concat "magit-key-mode-popup-" (symbol-name group))))) - -(defun magit-key-mode-generate (group) - "Generate the key-group menu for GROUP" - (let ((opts (magit-key-mode-options-for-group group))) - (eval - `(defun ,(intern (concat "magit-key-mode-popup-" (symbol-name group))) nil - ,(concat "Key menu for " (symbol-name group)) - (interactive) - (magit-key-mode (quote ,group)))))) - -;; create the interactive functions for the key mode popups (which are -;; applied in the top-level key maps) -(mapc (lambda (g) - (magit-key-mode-generate (car g))) - magit-key-mode-groups) - -(provide 'magit-key-mode) diff --git a/elpa/magit-1.2.0/magit-pkg.el b/elpa/magit-1.2.0/magit-pkg.el deleted file mode 100644 index 11ad3243..00000000 --- a/elpa/magit-1.2.0/magit-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(define-package "magit" "1.2.0" "Control Git from Emacs.") diff --git a/elpa/magit-1.2.0/magit-stgit.el b/elpa/magit-1.2.0/magit-stgit.el deleted file mode 100644 index b105b71f..00000000 --- a/elpa/magit-1.2.0/magit-stgit.el +++ /dev/null @@ -1,288 +0,0 @@ -;;; magit-stgit.el --- StGit plug-in for Magit - -;; Copyright (C) 2011 Lluis Vilanova -;; -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see . - -;;; Commentary: - -;; This plug-in provides StGit functionality as a separate component of Magit. - -;; Available actions: -;; - visit: Shows the patch at point in the series (stg show) -;; - apply: Goes to the patch at point in the series (stg goto) -;; - discard: Deletes the marked/at point patch in the series (stg delete) - -;; Available commands: -;; - `magit-stgit-refresh': Refresh the marked/at point patch in the series -;; (stg refresh) -;; - `magit-stgit-repair': Repair the StGit metadata (stg repair) -;; - `magit-stgit-rebase': Rebase the whole series (stg rebase) - -;; TODO: -;; - Let the user select which files must be included in a refresh. -;; - Missing actions for `magit-show-item-or-scroll-up' and -;; `magit-show-item-or-scroll-down'. -;; - Marking a patch is slow and refreshes all buffers, which resets their -;; position (i.e., the buffer is shown from its first line). - -;;; Code: - -(require 'magit) -(eval-when-compile - (require 'cl)) - -;;; Customizables: - -(defcustom magit-stgit-executable "stg" - "The name of the StGit executable." - :group 'magit - :type 'string) - -(defface magit-stgit-applied - '((t :inherit magit-diff-add)) - "Face for an applied stgit patch." - :group 'magit-faces) - -(defface magit-stgit-current - '((t :inherit magit-item-highlight)) - "Face for the current stgit patch." - :group 'magit-faces) - -(defface magit-stgit-other - '((t :inherit magit-diff-del)) - "Face for a non-applied stgit patch." - :group 'magit-faces) - -(defface magit-stgit-marked - '((t :inherit magit-item-mark)) - "Face for a marked stgit patch." - :group 'magit-faces) - -(defface magit-stgit-empty - '((t :inherit magit-item-mark)) - "Face for an empty stgit patch." - :group 'magit-faces) - -;;; Common code: - -(defvar magit-stgit--enabled nil - "Whether this buffer has StGit support.") -(make-variable-buffer-local 'magit-stgit--enabled) - -(defvar magit-stgit-mode) - -(defun magit-stgit--enabled () - "Whether this buffer has StGit support enabled." - (if (assoc 'magit-stgit--enabled (buffer-local-variables)) - magit-stgit--enabled - (setq magit-stgit--enabled - (and magit-stgit-mode - (not (null - (member (concat (magit-get-current-branch) ".stgit") - (mapcar #'(lambda (line) - (string-match "^\\*?\s*\\([^\s]*\\)" - line) - (match-string 1 line)) - (magit-git-lines "branch"))))))))) - -(defun magit-stgit--enabled-reset () - "Reset the StGit enabled state." - (kill-local-variable 'magit-stgit--enabled)) - -(defvar magit-stgit--marked-patch nil - "The (per-buffer) currently marked patch in an StGit series.") -(make-variable-buffer-local 'magit-stgit--marked-patch) - -;;; Menu: - -(easy-menu-define magit-stgit-extension-menu - nil - "StGit extension menu" - '("StGit" - :active (magit-stgit--enabled) - - ["Refresh patch" magit-stgit-refresh - :help "Refresh the contents of a patch in an StGit series"] - ["Repair" magit-stgit-repair - :help "Repair StGit metadata if branch was modified with git commands"] - ["Rebase series" magit-stgit-rebase - :help "Rebase an StGit patch series"] - )) - -(easy-menu-add-item 'magit-mode-menu - '("Extensions") - magit-stgit-extension-menu) - -;;; Series section: - -(defun magit-stgit--wash-patch () - (if (search-forward-regexp "^\\(.\\)\\(.\\) \\([^\s]*\\)\\(\s*# ?\\)\\(.*\\)" - (line-end-position) t) - (let* ((empty-str "[empty] ") - (indent-str (make-string (string-bytes empty-str) ?\ )) - (empty (match-string 1)) - (state (match-string 2)) - (patch (match-string 3)) - (descr (match-string 5))) - (delete-region (line-beginning-position) (line-end-position)) - (insert - (cond ((string= empty "0") - (propertize (concat empty-str " " state " " descr) 'face 'magit-stgit-empty)) - ((string= magit-stgit--marked-patch patch) - (propertize (concat indent-str " " state " " descr) 'face 'magit-stgit-marked)) - ((string= state "+") - (concat indent-str " " (propertize state 'face 'magit-stgit-applied) " " descr)) - ((string= state ">") - (propertize (concat indent-str " " state " " descr) 'face 'magit-stgit-current)) - ((string= state "-") - (concat indent-str " " (propertize state 'face 'magit-stgit-other) " " descr)))) - (goto-char (line-beginning-position)) - (magit-with-section patch 'series - (magit-set-section-info patch) - (goto-char (line-end-position))) - (forward-line)) - (delete-region (line-beginning-position) (1+ (line-end-position)))) - t) - -(defun magit-stgit--wash-series () - (let ((magit-old-top-section nil)) - (magit-wash-sequence #'magit-stgit--wash-patch))) - -(magit-define-inserter series () - (when (executable-find magit-stgit-executable) - (magit-insert-section 'series - "Series:" 'magit-stgit--wash-series - magit-stgit-executable "series" "-a" "-d" "-e"))) - -;;; Actions: - -;; Copy of `magit-refresh-commit-buffer' (version 1.0.0) -(defun magit-stgit--refresh-patch-buffer (patch) - (magit-create-buffer-sections - (magit-insert-section nil nil - 'magit-wash-commit - magit-stgit-executable - "show" - patch))) - -;; Copy of `magit-show-commit' (version 1.0.0) -(defun magit-stgit--show-patch (patch &optional scroll) - (when (magit-section-p patch) - (setq patch (magit-section-info patch))) - (let ((dir default-directory) - (buf (get-buffer-create magit-commit-buffer-name))) - (cond ((and (equal magit-currently-shown-commit patch) - ;; if it's empty then the buffer was killed - (with-current-buffer buf - (> (length (buffer-string)) 1))) - (let ((win (get-buffer-window buf))) - (cond ((not win) - (display-buffer buf)) - (scroll - (with-selected-window win - (funcall scroll)))))) - (t - (setq magit-currently-shown-commit patch) - (display-buffer buf) - (with-current-buffer buf - (set-buffer buf) - (goto-char (point-min)) - (magit-mode-init dir 'magit-commit-mode - #'magit-stgit--refresh-patch-buffer patch)))))) - -(magit-add-action (item info "visit") - ((series) - (magit-stgit--show-patch info) - (pop-to-buffer magit-commit-buffer-name))) - -(magit-add-action (item info "apply") - ((series) - (magit-run magit-stgit-executable "goto" info))) - -(magit-add-action (item info "discard") - ((series) - (let ((patch (or magit-stgit--marked-patch info))) - (if (yes-or-no-p (format "Delete patch '%s' in series? " patch)) - (progn - (if (string= magit-stgit--marked-patch patch) - (setq magit-stgit--marked-patch nil)) - (magit-run magit-stgit-executable "delete" patch)))))) - -(defun magit-stgit--set-marked-patch (patch) - (setq magit-stgit--marked-patch - (if (string= magit-stgit--marked-patch patch) - nil - patch))) - -(magit-add-action (item info "mark") - ((series) - (magit-stgit--set-marked-patch info) - (magit-refresh-all))) - -;;; Commands: - -(defun magit-stgit-refresh () - "Refresh the contents of a patch in an StGit series. -If there is no marked patch in the series, refreshes the current -patch. -Otherwise, refreshes the marked patch." - (interactive) - (if magit-stgit--marked-patch - (magit-run magit-stgit-executable "refresh" "-p" magit-stgit--marked-patch) - (magit-run magit-stgit-executable "refresh"))) - -(defun magit-stgit-repair () - "Repair StGit metadata if branch was modified with git commands. -In the case of Git commits these will be imported as new patches -into the series." - (interactive) - (message "Repairing series...") - (magit-run magit-stgit-executable "repair") - (message "")) - -(defun magit-stgit-rebase () - "Rebase an StGit patch series." - (interactive) - (if (magit-get-current-remote) - (progn - (if (yes-or-no-p "Update remotes? ") - (progn - (message "Updating remotes...") - (magit-run-git-async "remote" "update"))) - (magit-run magit-stgit-executable "rebase" - (format "remotes/%s/%s" - (magit-get-current-remote) - (magit-get-current-branch)))))) - -;;;###autoload -(define-minor-mode magit-stgit-mode "StGit support for Magit" - :lighter " Stg" :require 'magit-stgit - (or (derived-mode-p 'magit-mode) - (error "This mode only makes sense with magit")) - (if magit-stgit-mode - (progn - (add-hook 'magit-after-insert-stashes-hook 'magit-insert-series nil t)) - (progn - (remove-hook 'magit-after-insert-stashes-hook 'magit-insert-series t))) - (when (called-interactively-p 'any) - (magit-refresh))) - -;;;###autoload -(defun turn-on-magit-stgit () - "Unconditionally turn on `magit-stgit-mode'." - (magit-stgit-mode 1)) - -(provide 'magit-stgit) -;;; magit-stgit.el ends here diff --git a/elpa/magit-1.2.0/magit-svn.el b/elpa/magit-1.2.0/magit-svn.el deleted file mode 100644 index d08c048d..00000000 --- a/elpa/magit-1.2.0/magit-svn.el +++ /dev/null @@ -1,240 +0,0 @@ -;;; magit-svn.el --- git-svn plug-in for Magit - -;; Copyright (C) 2008 Alex Ott -;; Copyright (C) 2009 Alexey Voinov -;; Copyright (C) 2009 John Wiegley -;; Copyright (C) 2008 Linh Dang -;; Copyright (C) 2008 Marcin Bachry -;; Copyright (C) 2008, 2009 Marius Vollmer -;; Copyright (C) 2010 Yann Hodique -;; -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see . - -;;; Commentary: - -;; This plug-in provides git-svn functionality as a separate component of Magit - -;;; Code: - -(require 'magit) -(eval-when-compile - (require 'cl)) - -;; git svn commands - -(defun magit-svn-find-rev (rev &optional branch) - (interactive - (list (read-string "SVN revision: ") - (if current-prefix-arg - (read-string "In branch: ")))) - (let* ((sha (apply 'magit-git-string - `("svn" - "find-rev" - ,(concat "r" rev) - ,@(when branch (list branch)))))) - (if sha - (magit-show-commit - (magit-with-section sha 'commit - (magit-set-section-info sha) - sha)) - (error "Revision %s could not be mapped to a commit" rev)))) - -(defun magit-svn-create-branch (name) - (interactive "sBranch name: ") - (magit-run-git "svn" "branch" name)) - -(defun magit-svn-rebase () - (interactive) - (magit-run-git-async "svn" "rebase")) - -(defun magit-svn-dcommit () - (interactive) - (magit-run-git-async "svn" "dcommit")) - -(defun magit-svn-enabled () - (not (null (magit-svn-get-ref-info t)))) - -(defun magit-svn-expand-braces-in-branches (branch) - (if (not (string-match "\\(.+\\){\\(.+,.+\\)}\\(.*\\):\\(.*\\)\\\*" branch)) - (list branch) - (let ((prefix (match-string 1 branch)) - (suffix (match-string 3 branch)) - (rhs (match-string 4 branch)) - (pieces (split-string (match-string 2 branch) ","))) - (mapcar (lambda (p) (concat prefix p suffix ":" rhs p)) pieces)))) - -(defun magit-svn-get-local-ref (url) - (let* ((branches (cons (magit-get "svn-remote" "svn" "fetch") - (magit-get-all "svn-remote" "svn" "branches"))) - (branches (apply 'nconc - (mapcar 'magit-svn-expand-braces-in-branches - branches))) - (base-url (magit-get "svn-remote" "svn" "url")) - (result nil)) - (while branches - (let* ((pats (split-string (pop branches) ":")) - (src (replace-regexp-in-string "\\*" "\\\\(.*\\\\)" (car pats))) - (dst (replace-regexp-in-string "\\*" "\\\\1" (cadr pats))) - (base-url (replace-regexp-in-string "\\+" "\\\\+" base-url)) - (base-url (replace-regexp-in-string "//.+@" "//" base-url)) - (pat1 (concat "^" src "$")) - (pat2 (cond ((equal src "") (concat "^" base-url "$")) - (t (concat "^" base-url "/" src "$"))))) - (cond ((string-match pat1 url) - (setq result (replace-match dst nil nil url)) - (setq branches nil)) - ((string-match pat2 url) - (setq result (replace-match dst nil nil url)) - (setq branches nil))))) - result)) - -(defvar magit-svn-get-ref-info-cache nil - "A cache for svn-ref-info. -As `magit-get-svn-ref-info' might be considered a quite -expensive operation a cache is taken so that `magit-status' -doesn't repeatedly call it.") - -(defun magit-svn-get-ref-info (&optional use-cache) - "Gather details about the current git-svn repository. -Return nil if there isn't one. Keys of the alist are ref-path, -trunk-ref-name and local-ref-name. -If USE-CACHE is non-nil then return the value of `magit-get-svn-ref-info-cache'." - (if (and use-cache magit-svn-get-ref-info-cache) - magit-svn-get-ref-info-cache - (let* ((fetch (magit-get "svn-remote" "svn" "fetch")) - (url) - (revision)) - (when fetch - (let* ((ref (cadr (split-string fetch ":"))) - (ref-path (file-name-directory ref)) - (trunk-ref-name (file-name-nondirectory ref))) - (set (make-local-variable - 'magit-svn-get-ref-info-cache) - (list - (cons 'ref-path ref-path) - (cons 'trunk-ref-name trunk-ref-name) - ;; get the local ref from the log. This is actually - ;; the way that git-svn does it. - (cons 'local-ref - (with-temp-buffer - (insert (or (magit-git-string "log" "--first-parent" - "--grep" "git-svn" "-1") - "")) - (goto-char (point-min)) - (cond ((re-search-forward "git-svn-id: \\(.+/.+?\\)@\\([0-9]+\\)" nil t) - (setq url (match-string 1) - revision (match-string 2)) - (magit-svn-get-local-ref url)) - (t - (setq url (magit-get "svn-remote" "svn" "url")) - nil)))) - (cons 'revision revision) - (cons 'url url)))))))) - -(defun magit-svn-get-ref (&optional use-cache) - "Get the best guess remote ref for the current git-svn based branch. -If USE-CACHE is non nil, use the cached information." - (let ((info (magit-svn-get-ref-info use-cache))) - (cdr (assoc 'local-ref info)))) - -(magit-define-inserter svn-unpulled (&optional use-cache) - (when (magit-svn-enabled) - (apply #'magit-git-section - 'svn-unpulled "Unpulled commits (SVN):" 'magit-wash-log "log" - (append magit-git-log-options - (list - (format "HEAD..%s" (magit-svn-get-ref use-cache))))))) - -(magit-define-inserter svn-unpushed (&optional use-cache) - (when (magit-svn-enabled) - (apply #'magit-git-section - 'svn-unpushed "Unpushed commits (SVN):" 'magit-wash-log "log" - (append magit-git-log-options - (list - (format "%s..HEAD" (magit-svn-get-ref use-cache))))))) - -(magit-define-section-jumper svn-unpushed "Unpushed commits (SVN)") - -(defun magit-svn-remote-string () - (let ((svn-info (magit-svn-get-ref-info))) - (when svn-info - (concat (cdr (assoc 'url svn-info)) - " @ " - (cdr (assoc 'revision svn-info)))))) - -(defun magit-svn-remote-update () - (interactive) - (when (magit-svn-enabled) - (magit-run-git-async "svn" "fetch"))) - -(easy-menu-define magit-svn-extension-menu - nil - "Git SVN extension menu" - '("Git SVN" - :visible magit-svn-mode - ["Create branch" magit-svn-create-branch (magit-svn-enabled)] - ["Rebase" magit-svn-rebase (magit-svn-enabled)] - ["Fetch" magit-svn-remote-update (magit-svn-enabled)] - ["Commit" magit-svn-dcommit (magit-svn-enabled)])) - -(easy-menu-add-item 'magit-mode-menu - '("Extensions") - magit-svn-extension-menu) - -;; add the group and its keys -(progn - ;; (re-)create the group - (magit-key-mode-add-group 'svn) - - (magit-key-mode-insert-action 'svn "r" "Rebase" 'magit-svn-rebase) - (magit-key-mode-insert-action 'svn "c" "DCommit" 'magit-svn-dcommit) - (magit-key-mode-insert-action 'svn "f" "Fetch" 'magit-svn-remote-update) - (magit-key-mode-insert-action 'svn "s" "Find rev" 'magit-svn-find-rev) - (magit-key-mode-insert-action 'svn "B" "Create branch" 'magit-svn-create-branch) - - ;; generate and bind the menu popup function - (magit-key-mode-generate 'svn)) - -(defvar magit-svn-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "N") 'magit-key-mode-popup-svn) - map)) - -;;;###autoload -(define-minor-mode magit-svn-mode "SVN support for Magit" - :lighter " SVN" :require 'magit-svn :keymap 'magit-svn-mode-map - (or (derived-mode-p 'magit-mode) - (error "This mode only makes sense with magit")) - (let ((unpulled-hook (lambda () (magit-insert-svn-unpulled t))) - (unpushed-hook (lambda () (magit-insert-svn-unpushed t))) - (remote-hook 'magit-svn-remote-string)) - (if magit-svn-mode - (progn - (add-hook 'magit-after-insert-unpulled-commits-hook unpulled-hook nil t) - (add-hook 'magit-after-insert-unpushed-commits-hook unpushed-hook nil t) - (add-hook 'magit-remote-string-hook remote-hook nil t)) - (progn - (remove-hook 'magit-after-insert-unpulled-commits-hook unpulled-hook t) - (remove-hook 'magit-after-insert-unpushed-commits-hook unpushed-hook t) - (remove-hook 'magit-remote-string-hook remote-hook t))) - (when (called-interactively-p 'any) - (magit-refresh)))) - -;;;###autoload -(defun turn-on-magit-svn () - "Unconditionally turn on `magit-svn-mode'." - (magit-svn-mode 1)) - -(provide 'magit-svn) -;;; magit-svn.el ends here diff --git a/elpa/magit-1.2.0/magit-topgit.el b/elpa/magit-1.2.0/magit-topgit.el deleted file mode 100644 index 6f0080cc..00000000 --- a/elpa/magit-1.2.0/magit-topgit.el +++ /dev/null @@ -1,191 +0,0 @@ -;;; magit-topgit.el --- topgit plug-in for Magit - -;; Copyright (C) 2010 Nathan Weizenbaum -;; Copyright (C) 2010 Yann Hodique -;; -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see . - -;;; Commentary: - -;; This plug-in provides topgit functionality as a separate component of Magit - -;;; Code: - -(require 'magit) -(eval-when-compile - (require 'cl)) - -(defcustom magit-topgit-executable "tg" - "The name of the TopGit executable." - :group 'magit - :type 'string) - -(defcustom magit-topgit-branch-prefix "t/" - "Convention prefix for topic branch creation." - :group 'magit - :type 'string) - -(defface magit-topgit-current - '((t :weight bold :inherit magit-branch)) - "Face for section titles." - :group 'magit-faces) - -;;; Topic branches (using topgit) - -(defun magit-topgit-in-topic-p () - (and (file-exists-p ".topdeps") - (executable-find magit-topgit-executable))) - -(defun magit-topgit-create-branch (branch parent) - (when (zerop (or (string-match magit-topgit-branch-prefix branch) -1)) - (magit-run* (list magit-topgit-executable "create" - branch (magit-rev-to-git parent)) - nil nil nil t) - t)) - -(defun magit-topgit-pull () - (when (magit-topgit-in-topic-p) - (magit-run* (list magit-topgit-executable "update") - nil nil nil t) - t)) - -(defun magit-topgit-push () - (when (magit-topgit-in-topic-p) - (let* ((branch (or (magit-get-current-branch) - (error "Don't push a detached head. That's gross"))) - (remote (magit-get "topgit" "remote")) - (push-remote (if (or current-prefix-arg (not remote)) - (magit-read-remote (format "Push %s to" branch)) - remote))) - (when (and (not remote) - (not current-prefix-arg)) - (magit-set push-remote "topgit" "remote")) - (magit-run magit-topgit-executable "push" "-r" push-remote)) - t)) - -(defun magit-topgit-remote-update (&optional remote) - (when (magit-topgit-in-topic-p) - (let* ((remote (magit-get "topgit" "remote")) - (remote-update (if (or current-prefix-arg (not remote)) - (magit-read-remote) - remote))) - (if (and (not remote) - (not current-prefix-arg)) - (progn - (magit-set remote-update "topgit" "remote") - (magit-run magit-topgit-executable "remote" - "--populate" remote-update))) - (magit-run magit-topgit-executable "remote" remote-update)) - ;; We return nil anyway, as we also want regular "git remote update" to - ;; happen - nil)) - -(defun magit-topgit-parse-flags (flags-string) - (let ((flags (string-to-list flags-string)) - (void-flag ?\ )) - (list :current (not (eq (nth 0 flags) void-flag)) - :empty (not (eq (nth 1 flags) void-flag))))) - -(defun magit-topgit-wash-topic () - (let ((fmt "^\\(.\\{7\\}\\)\\s-\\(\\S-+\\)\\s-+\\(.*\\)")) - (if (search-forward-regexp fmt (line-end-position) t) - (let ((flags (magit-topgit-parse-flags (match-string 1))) - (topic (match-string 2))) - (goto-char (line-beginning-position)) - (delete-char 8) - (insert "\t") - (goto-char (line-beginning-position)) - (magit-with-section topic 'topic - (magit-set-section-info topic) - (let ((beg (1+ (line-beginning-position))) - (end (line-end-position))) - (when (plist-get flags :current) - (put-text-property beg end 'face 'magit-topgit-current)) - (when (plist-get flags :empty) - (put-text-property beg end 'face `(:strike-through t :inherit ,(get-text-property beg 'face))))) - (forward-line))) - (delete-region (line-beginning-position) (1+ (line-end-position)))) - t)) - -(defun magit-topgit-wash-topics () - (let ((magit-old-top-section nil)) - (magit-wash-sequence #'magit-topgit-wash-topic))) - -(defun magit-topgit-section (section title washer &rest args) - (when (executable-find magit-topgit-executable) - (let ((magit-git-executable magit-topgit-executable) - (magit-git-standard-options nil)) - (apply 'magit-git-section section title washer args)))) - -(magit-define-inserter topics () - (magit-topgit-section 'topics - "Topics:" 'magit-topgit-wash-topics - "summary")) - -(magit-add-action (item info "discard") - ((topic) - (when (yes-or-no-p "Discard topic? ") - (magit-run* (list magit-topgit-executable "delete" "-f" info) - nil nil nil t)))) - -(magit-add-action (item info "visit") - ((topic) - (magit-checkout info))) - -(defun magit-topgit-get-top-bases-color (suffix) - (list nil nil)) - -(defun magit-topgit-get-remote-top-bases-color (suffix) - (when (string-match "^\\(?:[^/]+\\)/top-bases" suffix) - (list nil nil))) - -(defconst magit-topgit-ignored-namespace - '("top-bases" magit-topgit-get-top-bases-color)) - -;;;###autoload -(define-minor-mode magit-topgit-mode "Topgit support for Magit" - :lighter " Topgit" :require 'magit-topgit - (or (derived-mode-p 'magit-mode) - (error "This mode only makes sense with magit")) - (if magit-topgit-mode - (progn - (add-hook 'magit-after-insert-stashes-hook 'magit-insert-topics nil t) - (add-hook 'magit-create-branch-command-hook 'magit-topgit-create-branch nil t) - (add-hook 'magit-pull-command-hook 'magit-topgit-pull nil t) - (add-hook 'magit-remote-update-command-hook 'magit-topgit-remote-update nil t) - (add-hook 'magit-push-command-hook 'magit-topgit-push nil t) - ;; hide refs for top-bases namespace in any remote - (add-hook 'magit-log-remotes-color-hook - 'magit-topgit-get-remote-top-bases-color) - ;; hide refs in the top-bases namespace, as they're not meant for the user - (add-to-list 'magit-refs-namespaces magit-topgit-ignored-namespace)) - (progn - (remove-hook 'magit-after-insert-stashes-hook 'magit-insert-topics t) - (remove-hook 'magit-create-branch-command-hook 'magit-topgit-create-branch t) - (remove-hook 'magit-pull-command-hook 'magit-topgit-pull t) - (remove-hook 'magit-remote-update-command-hook 'magit-topgit-remote-update t) - (remove-hook 'magit-push-command-hook 'magit-topgit-push t) - (remove-hook 'magit-log-remotes-color-hook - 'magit-topgit-get-remote-top-bases-color) - (delete magit-topgit-ignored-namespace magit-refs-namespaces))) - (when (called-interactively-p 'any) - (magit-refresh))) - -;;;###autoload -(defun turn-on-magit-topgit () - "Unconditionally turn on `magit-topgit-mode'." - (magit-topgit-mode 1)) - -(provide 'magit-topgit) -;;; magit-topgit.el ends here diff --git a/elpa/magit-1.2.0/magit-wip.el b/elpa/magit-1.2.0/magit-wip.el deleted file mode 100644 index 5c198404..00000000 --- a/elpa/magit-1.2.0/magit-wip.el +++ /dev/null @@ -1,153 +0,0 @@ -;;; magit-wip.el --- git-wip plug-in for Magit - -;; Copyright (C) 2012 Jonas Bernoulli -;; Copyright (C) 2012 Ryan C. Thompson - -;; Maintainer: Jonas Bernoulli - -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see . - -;;; Commentary: - -;; This plug-in provides support for special work-in-progress refs. - -;; This requires the third-party git command "git wip" which is available -;; from https://github.com/bartman/git-wip. - -;; The global mode `magit-wip-mode' provides highlighting of wip refs in -;; Magit buffers while the local mode `magit-wip-save-mode' commits to -;; such a ref when saving a file-visiting buffer. - -;; To enable `magit-wip-save-mode' enable `global-magit-wip-save-mode' -;; and use the Magit extension mechanism to select the repositories in -;; which you want to use a work-in-progress ref. Usually you also want -;; to enable `magit-wip-mode'. -;; -;; (magit-wip-mode 1) -;; (global-magit-wip-save-mode 1) -;; -;; $ git config --add magit.extension wip-save # or -;; $ git config --global --add magit.extension wip-save - -;; Note that `global-magit-wip-save-mode' is the only mode that uses the -;; extension mechanism for file-visiting buffers all other global modes -;; making use of it to turn on local modes in Magit buffers. - -;;; Code: - -(require 'magit) -(require 'format-spec) - -;;; Magit Wip Mode. - -(defface magit-log-head-label-wip - '((((class color) (background light)) - :box t - :background "Grey95" - :foreground "LightSkyBlue3") - (((class color) (background dark)) - :box t - :background "Grey07" - :foreground "LightSkyBlue4")) - "Face for git-wip labels shown in log buffer." - :group 'magit-faces) - -(defun magit-log-get-wip-color (suffix) - (list (concat "(WIP) " suffix) - 'magit-log-head-label-wip)) - -(defconst magit-wip-refs-namespace - '("wip" magit-log-get-wip-color)) - -;;;###autoload -(define-minor-mode magit-wip-mode - "In Magit log buffers; give wip refs a special appearance." - :group 'magit - :global t - (if magit-wip-mode - (add-to-list 'magit-refs-namespaces magit-wip-refs-namespace 'append) - (setq magit-refs-namespaces - (delete magit-wip-refs-namespace magit-refs-namespaces)))) - -;;; Magit Wip Save Mode. - -(defcustom magit-wip-commit-message "WIP %r" - "Commit message for git-wip commits. - -The following `format'-like specs are supported: -%f the full name of the file being saved, and -%r the name of the file being saved, relative to the repository root -%g the root of the git repository." - :group 'magit - :type 'string) - -(defcustom magit-wip-echo-area-message "Wrote %f (wip)" - "Message shown in the echo area after creating a git-wip commit. - -The following `format'-like specs are supported: -%f the full name of the file being saved, and -%r the name of the file being saved, relative to the repository root. -%g the root of the git repository." - :group 'magit - :type '(choice (const :tag "No message" nil) string)) - -(defvar magit-wip-save-mode-lighter " Wip") - -;;;###autoload -(define-minor-mode magit-wip-save-mode - "Magit support for committing to a work-in-progress ref. - -When this minor mode is turned on and a file is saved inside a writable -git repository then it is also committed to a special work-in-progress -ref." - :lighter magit-wip-save-mode-lighter - (if magit-wip-save-mode - (add-hook 'after-save-hook 'magit-wip-save-safe t t) - (remove-hook 'after-save-hook 'magit-wip-save-safe t))) - -;;;###autoload -(define-globalized-minor-mode global-magit-wip-save-mode - magit-wip-save-mode turn-on-magit-wip-save - :group 'magit) - -(defun turn-on-magit-wip-save () - (when (and (buffer-file-name) - (magit-get-top-dir default-directory) - (member "wip-save" (magit-get-all "magit.extension"))) - (if (= (magit-git-exit-code "wip" "-h") 0) - (magit-wip-save-mode 1) - (message "Git command 'git wip' cannot be found")))) - -(defun magit-wip-save-safe () - (condition-case err - (magit-wip-save) - (error - (message "Magit WIP got an error: %S" err)))) - -(defun magit-wip-save () - (let* ((top-dir (magit-get-top-dir default-directory)) - (name (file-truename (buffer-file-name))) - (spec `((?r . ,(file-relative-name name top-dir)) - (?f . ,(buffer-file-name)) - (?g . ,top-dir)))) - (when (and top-dir (file-writable-p top-dir)) - (save-excursion ; kludge see https://github.com/magit/magit/issues/441 - (magit-run-git "wip" "save" - (format-spec magit-wip-commit-message spec) - "--editor" "--" name)) - (when magit-wip-echo-area-message - (message (format-spec magit-wip-echo-area-message spec)))))) - -(provide 'magit-wip) -;;; magit-wip.el ends here diff --git a/elpa/magit-1.2.0/magit.el b/elpa/magit-1.2.0/magit.el deleted file mode 100644 index 121ec9c7..00000000 --- a/elpa/magit-1.2.0/magit.el +++ /dev/null @@ -1,6001 +0,0 @@ -;;; magit.el --- control Git from Emacs - -;; Copyright (C) 2010 Aaron Culich. -;; Copyright (C) 2010 Alan Falloon. -;; Copyright (C) 2008, 2010 Alex Ott. -;; Copyright (C) 2008, 2009, 2010 Alexey Voinov. -;; Copyright (C) 2010 Ben Walton. -;; Copyright (C) 2010 Chris Bernard. -;; Copyright (C) 2010 Christian Kluge. -;; Copyright (C) 2008 Daniel Farina. -;; Copyright (C) 2010 David Abrahams. -;; Copyright (C) 2009 David Wallin. -;; Copyright (C) 2009, 2010 Hannu Koivisto. -;; Copyright (C) 2009 Ian Eure. -;; Copyright (C) 2009 Jesse Alama. -;; Copyright (C) 2009 John Wiegley. -;; Copyright (C) 2010 Leo. -;; Copyright (C) 2008, 2009 Marcin Bachry. -;; Copyright (C) 2008, 2009 Marius Vollmer. -;; Copyright (C) 2010 Mark Hepburn. -;; Copyright (C) 2010 Moritz Bunkus. -;; Copyright (C) 2010 Nathan Weizenbaum. -;; Copyright (C) 2010 Oscar Fuentes. -;; Copyright (C) 2009 Pavel Holejsovsky. -;; Copyright (C) 2011-2012 Peter J Weisberg -;; Copyright (C) 2009, 2010 Phil Jackson. -;; Copyright (C) 2010 Philip Weaver. -;; Copyright (C) 2010 Ramkumar Ramachandra. -;; Copyright (C) 2010 Remco van 't Veer. -;; Copyright (C) 2009 René Stadler. -;; Copyright (C) 2010 Robin Green. -;; Copyright (C) 2010 Roger Crew. -;; Copyright (C) 2009, 2010, 2011 Rémi Vanicat. -;; Copyright (C) 2010 Sean Bryant. -;; Copyright (C) 2009, 2011 Steve Purcell. -;; Copyright (C) 2010 Timo Juhani Lindfors. -;; Copyright (C) 2010, 2011 Yann Hodique. -;; Copyright (C) 2010 Ævar Arnfjörð Bjarmason. -;; Copyright (C) 2010 Óscar Fuentes. - -;; Original Author: Marius Vollmer -;; Former Maintainer: Phil Jackson -;; Maintenance Group: https://github.com/organizations/magit/teams/53130 -;; Currently composed of: -;; - Phil Jackson -;; - Peter J Weisberg -;; - Yann Hodique -;; - Rémi Vanicat -;; Version: 1.2.0 -;; Keywords: tools - -;; -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see . - -;;; Commentary: - -;; Invoking the magit-status function will show a buffer with the -;; status of the current git repository and its working tree. That -;; buffer offers key bindings for manipulating the status in simple -;; ways. -;; -;; The status buffer mainly shows the difference between the working -;; tree and the index, and the difference between the index and the -;; current HEAD. You can add individual hunks from the working tree -;; to the index, and you can commit the index. -;; -;; See the Magit User Manual for more information. - -;;; Code: - -(eval-when-compile (require 'cl)) -(require 'log-edit) -(require 'easymenu) -(require 'diff-mode) - -;; Silences byte-compiler warnings -(eval-and-compile - (unless (fboundp 'declare-function) (defmacro declare-function (&rest args)))) - -(eval-when-compile (require 'view)) -(declare-function view-mode 'view) -(eval-when-compile (require 'iswitchb)) -(eval-when-compile (require 'ido)) -(eval-when-compile (require 'ediff)) - -;; Dummy to be used by the defcustoms when first loading the file. -(eval-when (load eval) - (defalias 'magit-set-variable-and-refresh 'set-default)) - -;;; Code: -(defgroup magit nil - "Controlling Git from Emacs." - :prefix "magit-" - :group 'tools) - -(defcustom magit-git-executable "git" - "The name of the Git executable." - :group 'magit - :type 'string) - -(defcustom magit-gitk-executable (concat (file-name-directory magit-git-executable) - "gitk") - "The name of the Gitk executable." - :group 'magit - :type 'string) - -(defcustom magit-git-standard-options '("--no-pager") - "Standard options when running Git." - :group 'magit - :type '(repeat string)) - -(defcustom magit-repo-dirs nil - "Directories containing Git repositories. -Magit will look into these directories for Git repositories and -offer them as choices for `magit-status'." - :group 'magit - :type '(repeat string)) - -(defcustom magit-repo-dirs-depth 3 - "The maximum depth to look for Git repos. -When looking for a Git repository below the directories in `magit-repo-dirs', -Magit will only descend this many levels deep." - :group 'magit - :type 'integer) - -(defcustom magit-set-upstream-on-push nil - "Non-nil means that `magit-push' may use --set-upstream when pushing a branch. -This only applies if the branch does not have an upstream set yet. -Setting this to t will ask if --set-upstream should be used. -Setting it to 'dontask will always use --set-upstream. -Setting it to 'refuse will refuse to push unless a remote branch has already been set. - ---set-upstream is supported with git > 1.7.0" - :group 'magit - :type '(choice (const :tag "Never" nil) - (const :tag "Ask" t) - (const :tag "Refuse" refuse) - (const :tag "Always" dontask))) - -(defcustom magit-save-some-buffers t - "Non-nil means that \\[magit-status] will save modified buffers before running. -Setting this to t will ask which buffers to save, setting it to 'dontask will -save all modified buffers without asking." - :group 'magit - :type '(choice (const :tag "Never" nil) - (const :tag "Ask" t) - (const :tag "Save without asking" dontask))) - -(defcustom magit-save-some-buffers-predicate - 'magit-save-buffers-predicate-tree-only - "A predicate function to decide whether to save a buffer. - -Used by function `magit-save-some-buffers' when the variable of -the same name is non-nil." - - :group 'magit - :type '(radio (function-item magit-save-buffers-predicate-tree-only) - (function-item magit-save-buffers-predicate-all) - (function :tag "Other"))) - -(defcustom magit-default-tracking-name-function - 'magit-default-tracking-name-remote-plus-branch - "Specifies the function to use to generate default tracking branch names -when doing a \\[magit-checkout]. - -The default is magit-default-tracking-name-remote-plus-branch, -which generates a tracking name of the form 'REMOTE-BRANCHNAME'." - :group 'magit - :type '(radio (function-item magit-default-tracking-name-remote-plus-branch) - (function-item magit-default-tracking-name-branch-only) - (function :tag "Other"))) - -(defcustom magit-commit-all-when-nothing-staged 'ask - "Determines what \\[magit-log-edit] does when nothing is staged. -Setting this to nil will make it do nothing, setting it to t will -arrange things so that the actual commit command will use the \"--all\" option, -setting it to 'ask will first ask for confirmation whether to do this, -and setting it to 'ask-stage will cause all changes to be staged, -after a confirmation." - :group 'magit - :type '(choice (const :tag "No" nil) - (const :tag "Always" t) - (const :tag "Ask" ask) - (const :tag "Ask to stage everything" ask-stage))) - -(defcustom magit-commit-signoff nil - "Add the \"Signed-off-by:\" line when committing." - :group 'magit - :type 'boolean) - -(defcustom magit-sha1-abbrev-length 7 - "The number of digits to show when a sha1 is displayed in abbreviated form." - :group 'magit - :type 'integer) - -(defcustom magit-log-cutoff-length 100 - "The maximum number of commits to show in the log and whazzup buffers." - :group 'magit - :type 'integer) - -(defcustom magit-log-infinite-length 99999 - "Number of log used to show as maximum for `magit-log-cutoff-length'." - :group 'magit - :type 'integer) - -(defcustom magit-log-auto-more nil - "Insert more log entries automatically when moving past the last entry. - -Only considered when moving past the last entry with -`magit-goto-*-section' commands." - :group 'magit - :type 'boolean) - -(defcustom magit-process-popup-time -1 - "Popup the process buffer if a command takes longer than this many seconds." - :group 'magit - :type '(choice (const :tag "Never" -1) - (const :tag "Immediately" 0) - (integer :tag "After this many seconds"))) - -(defcustom magit-revert-item-confirm t - "Require acknowledgment before reverting an item." - :group 'magit - :type 'boolean) - -(defcustom magit-log-edit-confirm-cancellation nil - "Require acknowledgment before canceling the log edit buffer." - :group 'magit - :type 'boolean) - -(defcustom magit-remote-ref-format 'branch-then-remote - "What format to use for autocompleting refs, in pariticular for remotes. - -Autocompletion is used by functions like `magit-checkout', -`magit-interactive-rebase' and others which offer branch name -completion. - -The value 'name-then-remote means remotes will be of the -form \"name (remote)\", while the value 'remote-slash-name -means that they'll be of the form \"remote/name\". I.e. something that's -listed as \"remotes/upstream/next\" by \"git branch -l -a\" -will be \"upstream/next\"." - :group 'magit - :type '(choice (const :tag "name (remote)" branch-then-remote) - (const :tag "remote/name" remote-slash-branch))) - -(defcustom magit-process-connection-type (not (eq system-type 'cygwin)) - "Connection type used for the git process. - -If nil, use pipes: this is usually more efficient, and works on Cygwin. -If t, use ptys: this enables magit to prompt for passphrases when needed." - :group 'magit - :type '(choice (const :tag "pipe" nil) - (const :tag "pty" t))) - -(defcustom magit-completing-read-function 'magit-builtin-completing-read - "Function to be called when requesting input from the user." - :group 'magit - :type '(radio (function-item magit-iswitchb-completing-read) - (function-item magit-ido-completing-read) - (function-item magit-builtin-completing-read) - (function :tag "Other"))) - -(defcustom magit-create-branch-behaviour 'at-head - "Where magit will create a new branch if not supplied a branchname or ref. - -The value 'at-head means a new branch will be created at the tip -of your current branch, while the value 'at-point means magit -will try to find a valid reference at point..." - :group 'magit - :type '(choice (const :tag "at HEAD" at-head) - (const :tag "at point" at-point))) - -(defcustom magit-status-buffer-switch-function 'pop-to-buffer - "Function for `magit-status' to use for switching to the status buffer. - -The function is given one argument, the status buffer." - :group 'magit - :type '(radio (function-item switch-to-buffer) - (function-item pop-to-buffer) - (function :tag "Other"))) - -(defcustom magit-rewrite-inclusive t - "Whether magit includes the selected base commit in a rewrite operation. - -t means both the selected commit as well as any subsequent -commits will be rewritten. This is magit's default behaviour, -equivalent to 'git rebase -i ${REV}~1' - - A'---B'---C'---D' - ^ - -nil means the selected commit will be literally used as 'base', -so only subsequent commits will be rewritten. This is consistent -with git-rebase, equivalent to 'git rebase -i ${REV}', yet more -cumbersome to use from the status buffer. - - A---B'---C'---D' - ^" - :group 'magit - :type '(choice (const :tag "Always" t) - (const :tag "Never" nil) - (const :tag "Ask" ask))) - -(defcustom magit-highlight-whitespace t - "Specifies where to highlight whitespace errors. -See `magit-highlight-trailing-whitespace', -`magit-highlight-indentation'. The symbol t means in all diffs, -'status means only in the status buffer, and nil means nowhere." - :group 'magit - :type '(choice (const :tag "Always" t) - (const :tag "Never" nil) - (const :tag "In status buffer" status)) - :set 'magit-set-variable-and-refresh) - -(defcustom magit-highlight-trailing-whitespace t - "Highlight whitespace at the end of a line in diffs. -Used only when `magit-highlight-whitespace' is non-nil." - :group 'magit - :type 'boolean - :set 'magit-set-variable-and-refresh) - -(defcustom magit-highlight-indentation nil - "Highlight the \"wrong\" indentation style. -Used only when `magit-highlight-whitespace' is non-nil. - -The value is a list of cons cells. The car is a regular -expression, and the cdr is the value that applies to repositories -whose directory matches the regular expression. If more than one -item matches, then the *last* item in the list applies. So, the -default value should come first in the list. - -If the value is `tabs', highlight indentation with tabs. If the -value is an integer, highlight indentation with at least that -many spaces. Otherwise, highlight neither." - :group 'magit - :type `(repeat (cons (string :tag "Directory regexp") - (choice (const :tag "Tabs" tabs) - (integer :tag "Spaces" :value ,tab-width) - (const :tag "Neither" nil)))) - :set 'magit-set-variable-and-refresh) - -(defcustom magit-diff-refine-hunk nil - "Show fine (word-granularity) differences within diff hunks. - -There are three possible settings: - - nil means to never show fine differences - - t means to only show fine differences for the currently - selected diff hunk - - `all' means to always show fine differences for all displayed diff hunks" - :group 'magit - :type '(choice (const :tag "Never" nil) - (const :tag "Selected only" t) - (const :tag "All" all)) - :set 'magit-set-variable-and-refresh) - -(defvar magit-current-indentation nil - "Indentation highlight used in the current buffer. -This is calculated from `magit-highlight-indentation'.") -(make-variable-buffer-local 'magit-current-indentation) - -(defgroup magit-faces nil - "Customize the appearance of Magit." - :prefix "magit-" - :group 'faces - :group 'magit) - -(defface magit-header - '((t :inherit header-line)) - "Face for generic header lines. - -Many Magit faces inherit from this one by default." - :group 'magit-faces) - -(defface magit-section-title - '((t :inherit magit-header)) - "Face for section titles." - :group 'magit-faces) - -(defface magit-branch - '((t :inherit magit-header)) - "Face for the current branch." - :group 'magit-faces) - -(defface magit-diff-file-header - '((t :inherit diff-file-header)) - "Face for diff file header lines." - :group 'magit-faces) - -(defface magit-diff-hunk-header - '((t :inherit diff-hunk-header)) - "Face for diff hunk header lines." - :group 'magit-faces) - -(defface magit-diff-add - '((t :inherit diff-added)) - "Face for lines in a diff that have been added." - :group 'magit-faces) - -(defface magit-diff-none - '((t :inherit diff-context)) - "Face for lines in a diff that are unchanged." - :group 'magit-faces) - -(defface magit-diff-del - '((t :inherit diff-removed)) - "Face for lines in a diff that have been deleted." - :group 'magit-faces) - -(defface magit-log-graph - '((((class color) (background light)) - :foreground "grey11") - (((class color) (background dark)) - :foreground "grey80")) - "Face for the graph element of the log output." - :group 'magit-faces) - -(defface magit-log-sha1 - '((((class color) (background light)) - :foreground "firebrick") - (((class color) (background dark)) - :foreground "tomato")) - "Face for the sha1 element of the log output." - :group 'magit-faces) - -(defface magit-log-message - '((t)) - "Face for the message element of the log output." - :group 'magit-faces) - -(defface magit-item-highlight - '((t :inherit highlight)) - "Face for highlighting the current item." - :group 'magit-faces) - -(defface magit-item-mark - '((t :inherit secondary-selection)) - "Face for highlighting marked item." - :group 'magit-faces) - -(defface magit-log-head-label-bisect-good - '((((class color) (background light)) - :box t - :background "light green" - :foreground "dark olive green") - (((class color) (background dark)) - :box t - :background "light green" - :foreground "dark olive green")) - "Face for good bisect refs." - :group 'magit-faces) - -(defface magit-log-head-label-bisect-bad - '((((class color) (background light)) - :box t - :background "IndianRed1" - :foreground "IndianRed4") - (((class color) (background dark)) - :box t - :background "IndianRed1" - :foreground "IndianRed4")) - "Face for bad bisect refs." - :group 'magit-faces) - -(defface magit-log-head-label-remote - '((((class color) (background light)) - :box t - :background "Grey85" - :foreground "OliveDrab4") - (((class color) (background dark)) - :box t - :background "Grey11" - :foreground "DarkSeaGreen2")) - "Face for remote branch head labels shown in log buffer." - :group 'magit-faces) - -(defface magit-log-head-label-tags - '((((class color) (background light)) - :box t - :background "LemonChiffon1" - :foreground "goldenrod4") - (((class color) (background dark)) - :box t - :background "LemonChiffon1" - :foreground "goldenrod4")) - "Face for tag labels shown in log buffer." - :group 'magit-faces) - -(defface magit-log-head-label-patches - '((((class color) (background light)) - :box t - :background "IndianRed1" - :foreground "IndianRed4") - (((class color) (background dark)) - :box t - :background "IndianRed1" - :foreground "IndianRed4")) - "Face for Stacked Git patches." - :group 'magit-faces) - -(defface magit-whitespace-warning-face - '((t :inherit trailing-whitespace)) - "Face for highlighting whitespace errors in Magit diffs." - :group 'magit-faces) - -(defvar magit-custom-options '() - "List of custom options to pass to Git. -Do not customize this (used in the `magit-key-mode' implementation).") - -(defvar magit-read-rev-history nil - "The history of inputs to `magit-read-rev'.") - -(defvar magit-buffer-internal nil - "Track associated *magit* buffers. -Do not customize this (used in the `magit-log-edit-mode' implementation -to switch back to the *magit* buffer associated with a given commit -operation after commit).") - -(defvar magit-back-navigation-history nil - "History items that will be visited by successively going \"back\".") -(make-variable-buffer-local 'magit-back-navigation-history) -(put 'magit-back-navigation-history 'permanent-local t) - -(defvar magit-forward-navigation-history nil - "History items that will be visited by successively going \"forward\".") -(make-variable-buffer-local 'magit-forward-navigation-history) -(put 'magit-forward-navigation-history 'permanent-local t) - -(defvar magit-omit-untracked-dir-contents nil - "When non-nil magit will only list an untracked directory, not its contents.") - -(defvar magit-tmp-buffer-name " *magit-tmp*") - -(defface magit-log-head-label-local - '((((class color) (background light)) - :box t - :background "Grey85" - :foreground "LightSkyBlue4") - (((class color) (background dark)) - :box t - :background "Grey13" - :foreground "LightSkyBlue1")) - "Face for local branch head labels shown in log buffer." - :group 'magit-faces) - -(defface magit-log-head-label-default - '((((class color) (background light)) - :box t - :background "Grey50") - (((class color) (background dark)) - :box t - :background "Grey50")) - "Face for unknown ref labels shown in log buffer." - :group 'magit-faces) - -(defvar magit-mode-map - (let ((map (make-keymap))) - (suppress-keymap map t) - (define-key map (kbd "n") 'magit-goto-next-section) - (define-key map (kbd "p") 'magit-goto-previous-section) - (define-key map (kbd "^") 'magit-goto-parent-section) - (define-key map (kbd "M-n") 'magit-goto-next-sibling-section) - (define-key map (kbd "M-p") 'magit-goto-previous-sibling-section) - (define-key map (kbd "TAB") 'magit-toggle-section) - (define-key map (kbd "") 'magit-expand-collapse-section) - (define-key map (kbd "1") 'magit-show-level-1) - (define-key map (kbd "2") 'magit-show-level-2) - (define-key map (kbd "3") 'magit-show-level-3) - (define-key map (kbd "4") 'magit-show-level-4) - (define-key map (kbd "M-1") 'magit-show-level-1-all) - (define-key map (kbd "M-2") 'magit-show-level-2-all) - (define-key map (kbd "M-3") 'magit-show-level-3-all) - (define-key map (kbd "M-4") 'magit-show-level-4-all) - (define-key map (kbd "M-h") 'magit-show-only-files) - (define-key map (kbd "M-H") 'magit-show-only-files-all) - (define-key map (kbd "M-s") 'magit-show-level-4) - (define-key map (kbd "M-S") 'magit-show-level-4-all) - (define-key map (kbd "g") 'magit-refresh) - (define-key map (kbd "G") 'magit-refresh-all) - (define-key map (kbd "?") 'magit-describe-item) - (define-key map (kbd "!") 'magit-key-mode-popup-running) - (define-key map (kbd ":") 'magit-git-command) - (define-key map (kbd "C-x 4 a") 'magit-add-change-log-entry-other-window) - (define-key map (kbd "L") 'magit-add-change-log-entry-no-option) - (define-key map (kbd "RET") 'magit-visit-item) - (define-key map (kbd "SPC") 'magit-show-item-or-scroll-up) - (define-key map (kbd "DEL") 'magit-show-item-or-scroll-down) - (define-key map (kbd "C-w") 'magit-copy-item-as-kill) - (define-key map (kbd "R") 'magit-rebase-step) - (define-key map (kbd "t") 'magit-key-mode-popup-tagging) - (define-key map (kbd "r") 'magit-key-mode-popup-rewriting) - (define-key map (kbd "P") 'magit-key-mode-popup-pushing) - (define-key map (kbd "f") 'magit-key-mode-popup-fetching) - (define-key map (kbd "b") 'magit-key-mode-popup-branching) - (define-key map (kbd "M") 'magit-key-mode-popup-remoting) - (define-key map (kbd "B") 'magit-key-mode-popup-bisecting) - (define-key map (kbd "F") 'magit-key-mode-popup-pulling) - (define-key map (kbd "l") 'magit-key-mode-popup-logging) - (define-key map (kbd "$") 'magit-display-process) - (define-key map (kbd "c") 'magit-log-edit) - (define-key map (kbd "E") 'magit-interactive-rebase) - (define-key map (kbd "e") 'magit-ediff) - (define-key map (kbd "w") 'magit-wazzup) - (define-key map (kbd "q") 'magit-quit-window) - (define-key map (kbd "m") 'magit-key-mode-popup-merging) - (define-key map (kbd "x") 'magit-reset-head) - (define-key map (kbd "v") 'magit-revert-item) - (define-key map (kbd "a") 'magit-apply-item) - (define-key map (kbd "A") 'magit-cherry-pick-item) - (define-key map (kbd "d") 'magit-diff-working-tree) - (define-key map (kbd "D") 'magit-diff) - (define-key map (kbd "-") 'magit-diff-smaller-hunks) - (define-key map (kbd "+") 'magit-diff-larger-hunks) - (define-key map (kbd "0") 'magit-diff-default-hunks) - (define-key map (kbd "h") 'magit-toggle-diff-refine-hunk) - map)) - -(defvar magit-commit-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-b") 'magit-show-commit-backward) - (define-key map (kbd "C-c C-f") 'magit-show-commit-forward) - map)) - -(defvar magit-status-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "s") 'magit-stage-item) - (define-key map (kbd "S") 'magit-stage-all) - (define-key map (kbd "u") 'magit-unstage-item) - (define-key map (kbd "U") 'magit-unstage-all) - (define-key map (kbd "i") 'magit-ignore-item) - (define-key map (kbd "I") 'magit-ignore-item-locally) - (define-key map (kbd ".") 'magit-mark-item) - (define-key map (kbd "=") 'magit-diff-with-mark) - (define-key map (kbd "k") 'magit-discard-item) - (define-key map (kbd "C") 'magit-add-log) - (define-key map (kbd "X") 'magit-reset-working-tree) - (define-key map (kbd "z") 'magit-key-mode-popup-stashing) - map)) - -(eval-after-load 'dired-x - '(define-key magit-status-mode-map [remap dired-jump] 'magit-dired-jump)) - -(defvar magit-log-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd ".") 'magit-mark-item) - (define-key map (kbd "=") 'magit-diff-with-mark) - (define-key map (kbd "e") 'magit-log-show-more-entries) - map)) - -(defvar magit-wazzup-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd ".") 'magit-mark-item) - (define-key map (kbd "=") 'magit-diff-with-mark) - (define-key map (kbd "i") 'magit-ignore-item) - map)) - -(defvar magit-branch-manager-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "c") 'magit-create-branch) - (define-key map (kbd "a") 'magit-add-remote) - (define-key map (kbd "r") 'magit-move-item) - (define-key map (kbd "k") 'magit-discard-item) - (define-key map (kbd "T") 'magit-change-what-branch-tracks) - map)) - -(defvar magit-bug-report-url - "http://github.com/magit/magit/issues") - -(defconst magit-version "1.2.0" - "The version of Magit that you're using.") - -(defun magit-bug-report (str) - "Asks the user to submit a bug report about the error described in STR." -;; XXX - should propose more information to be included. - (message (concat - "Unknown error: %s\n" - "Please, with as much information as possible, file a bug at\n" - "%s\n" - "You are using Magit version %s.") - str magit-bug-report-url magit-version)) - -(defun magit-buffer-switch (buf) - (if (string-match "magit" (buffer-name)) - (switch-to-buffer buf) - (pop-to-buffer buf))) - -;;; Macros - -(defmacro magit-with-refresh (&rest body) - (declare (indent 0)) - `(magit-refresh-wrapper (lambda () ,@body))) - -;;; Git features - -(defvar magit-have-graph 'unset) -(defvar magit-have-decorate 'unset) -(defvar magit-have-abbrev 'unset) -(make-variable-buffer-local 'magit-have-graph) -(put 'magit-have-graph 'permanent-local t) -(make-variable-buffer-local 'magit-have-decorate) -(put 'magit-have-decorate 'permanent-local t) -(make-variable-buffer-local 'magit-have-abbrev) -(put 'magit-have-abbrev 'permanent-local t) - -(defun magit-configure-have-graph () - (if (eq magit-have-graph 'unset) - (let ((res (magit-git-exit-code "log" "--graph" "--max-count=0"))) - (setq magit-have-graph (eq res 0))))) - -(defun magit-configure-have-decorate () - (if (eq magit-have-decorate 'unset) - (let ((res (magit-git-exit-code "log" "--decorate=full" "--max-count=0"))) - (setq magit-have-decorate (eq res 0))))) - -(defun magit-configure-have-abbrev () - (if (eq magit-have-abbrev 'unset) - (let ((res (magit-git-exit-code "log" "--no-abbrev-commit" "--max-count=0"))) - (setq magit-have-abbrev (eq res 0))))) - -;;; Compatibilities - -(eval-and-compile - (defun magit-max-args-internal (function) - "Returns the maximum number of arguments accepted by FUNCTION." - (if (symbolp function) - (setq function (symbol-function function))) - (if (subrp function) - (let ((max (cdr (subr-arity function)))) - (if (eq 'many max) - most-positive-fixnum - max)) - (if (eq 'macro (car-safe function)) - (setq function (cdr function))) - (let ((arglist (if (byte-code-function-p function) - (aref function 0) - (second function)))) - (if (memq '&rest arglist) - most-positive-fixnum - (length (remq '&optional arglist)))))) - - (if (functionp 'start-file-process) - (defalias 'magit-start-process 'start-file-process) - (defalias 'magit-start-process 'start-process)) - - (unless (fboundp 'string-match-p) - (defun string-match-p (regexp string &optional start) - "Same as `string-match' except this function does not -change the match data." - (let ((inhibit-changing-match-data t)) - (string-match regexp string start)))) - - (if (fboundp 'with-silent-modifications) - (defalias 'magit-with-silent-modifications 'with-silent-modifications) - (defmacro magit-with-silent-modifications (&rest body) - "Execute body without changing `buffer-modified-p'. Also, do not -record undo information." - `(set-buffer-modified-p - (prog1 (buffer-modified-p) - (let ((buffer-undo-list t) - before-change-functions - after-change-functions) - ,@body))))) - - (if (>= (magit-max-args-internal 'delete-directory) 2) - (defalias 'magit-delete-directory 'delete-directory) - (defun magit-delete-directory (directory &optional recursive) - "Deletes a directory named DIRECTORY. If RECURSIVE is non-nil, -recursively delete all of DIRECTORY's contents as well. - -Does not follow symlinks." - (if (or (file-symlink-p directory) - (not (file-directory-p directory))) - (delete-file directory) - (if recursive - ;; `directory-files-no-dot-files-regex' borrowed from Emacs 23 - (dolist (file (directory-files directory 'full "\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) - (magit-delete-directory file recursive))) - (delete-directory directory))))) - -;;; Utilities - -(defun magit-set-variable-and-refresh (symbol value) - "Set SYMBOL to VALUE and call `magit-refresh-all'" - (set-default symbol value) - (magit-refresh-all)) - -(defun magit-iswitchb-completing-read (prompt choices &optional predicate require-match - initial-input hist def) - "iswitchb-based completing-read almost-replacement." - (require 'iswitchb) - (let ((iswitchb-make-buflist-hook - (lambda () - (setq iswitchb-temp-buflist (if (consp (first choices)) - (mapcar #'car choices) - choices))))) - (iswitchb-read-buffer prompt (or initial-input def) require-match))) - -(defun magit-ido-completing-read (prompt choices &optional predicate require-match initial-input hist def) - "ido-based completing-read almost-replacement." - (require 'ido) - (let ((selected (ido-completing-read prompt (if (consp (first choices)) - (mapcar #'car choices) - choices) - predicate require-match initial-input hist def))) - (if (consp (first choices)) - (or (cdr (assoc selected choices)) - selected) - selected))) - -(defun magit-builtin-completing-read (prompt choices &optional predicate require-match - initial-input hist def) - "Magit wrapper for standard `completing-read' function." - (completing-read (if (and def (> (length prompt) 2) - (string-equal ": " (substring prompt -2))) - (format "%s (default %s): " (substring prompt 0 -2) def) - prompt) - choices predicate require-match initial-input hist def)) - -(defun magit-completing-read (prompt choices &optional predicate require-match - initial-input hist def) - (funcall magit-completing-read-function prompt choices predicate require-match - initial-input hist def)) - -(defun magit-use-region-p () - (if (fboundp 'use-region-p) - (use-region-p) - (and transient-mark-mode mark-active))) - -(defun magit-goto-line (line) - "Like `goto-line' but doesn't set the mark." - (save-restriction - (widen) - (goto-char 1) - (forward-line (1- line)))) - -(defun magit-trim-line (str) - (if (string= str "") - nil - (if (equal (elt str (- (length str) 1)) ?\n) - (substring str 0 (- (length str) 1)) - str))) - -(defun magit-split-lines (str) - (if (string= str "") - nil - (let ((lines (nreverse (split-string str "\n")))) - (if (string= (car lines) "") - (setq lines (cdr lines))) - (nreverse lines)))) - -(defun magit-git-insert (args) - (insert (magit-git-output args))) - -(defun magit-git-output (args) - (magit-cmd-output magit-git-executable (append magit-git-standard-options args))) - -(defun magit-cmd-insert (cmd args) - (insert (magit-cmd-output cmd args))) - -(defun magit-cmd-output (cmd args) - (let ((cmd-output (with-output-to-string - (with-current-buffer standard-output - (apply #'process-file - cmd - nil (list t nil) nil - args))))) - (replace-regexp-in-string "\e\\[.*?m" "" cmd-output))) - -(defun magit-git-string (&rest args) - (magit-trim-line (magit-git-output args))) - -(defun magit-git-lines (&rest args) - (magit-split-lines (magit-git-output args))) - -(defun magit-git-exit-code (&rest args) - (apply #'process-file magit-git-executable nil nil nil - (append magit-git-standard-options args))) - -(defun magit-file-lines (file) - (when (file-exists-p file) - (with-temp-buffer - (insert-file-contents file) - (let ((rev (nreverse (split-string (buffer-string) "\n")))) - (nreverse (if (equal (car rev) "") - (cdr rev) - rev)))))) - -(defun magit-write-file-lines (file lines) - (with-temp-buffer - (dolist (l lines) - (insert l "\n")) - (write-file file))) - -(defun magit-get (&rest keys) - "Return the value of Git config entry specified by KEYS." - (magit-git-string "config" (mapconcat 'identity keys "."))) - -(defun magit-get-all (&rest keys) - "Return all values of the Git config entry specified by KEYS." - (magit-git-lines "config" "--get-all" (mapconcat 'identity keys "."))) - -(defun magit-get-boolean (&rest keys) - "Return the boolean value of Git config entry specified by KEYS." - (equal (magit-git-string "config" "--bool" (mapconcat 'identity keys ".")) - "true")) - -(defun magit-set (val &rest keys) - "Set Git config settings specified by KEYS to VAL." - (if val - (magit-git-string "config" (mapconcat 'identity keys ".") val) - (magit-git-string "config" "--unset" (mapconcat 'identity keys ".")))) - -(defun magit-remove-conflicts (alist) - (let ((dict (make-hash-table :test 'equal)) - (result nil)) - (dolist (a alist) - (puthash (car a) (cons (cdr a) (gethash (car a) dict)) - dict)) - (maphash (lambda (key value) - (if (= (length value) 1) - (push (cons key (car value)) result) - (let ((sub (magit-remove-conflicts - (mapcar (lambda (entry) - (let ((dir (directory-file-name - (substring entry 0 (- (length key)))))) - (cons (concat (file-name-nondirectory dir) "/" key) - entry))) - value)))) - (setq result (append result sub))))) - dict) - result)) - -(defun magit-git-repo-p (dir) - (file-exists-p (expand-file-name ".git" dir))) - -(defun magit-git-dir () - "Returns the .git directory for the current repository." - (concat (expand-file-name (magit-git-string "rev-parse" "--git-dir")) "/")) - -(defun magit-no-commit-p () - "Return non-nil if there is no commit in the current git repository." - (not (magit-git-string - "rev-list" "HEAD" "--max-count=1"))) - -(defun magit-list-repos* (dir level) - (if (magit-git-repo-p dir) - (list dir) - (apply #'append - (mapcar (lambda (entry) - (unless (or (string= (substring entry -3) "/..") - (string= (substring entry -2) "/.")) - (magit-list-repos* entry (+ level 1)))) - (and (file-directory-p dir) - (< level magit-repo-dirs-depth) - (directory-files dir t nil t)))))) - -(defun magit-list-repos (dirs) - (magit-remove-conflicts - (apply #'append - (mapcar (lambda (dir) - (mapcar #'(lambda (repo) - (cons (file-name-nondirectory repo) - repo)) - (magit-list-repos* dir 0))) - dirs)))) - -(defun magit-get-top-dir (cwd) - (let ((cwd (expand-file-name (file-truename cwd)))) - (when (file-directory-p cwd) - (let* ((default-directory (file-name-as-directory cwd)) - (cdup (magit-git-string "rev-parse" "--show-cdup"))) - (when cdup - (file-name-as-directory (expand-file-name cdup cwd))))))) - -(defun magit-get-ref (ref) - (magit-git-string "symbolic-ref" "-q" ref)) - -(defun magit-get-current-branch () - (let* ((head (magit-get-ref "HEAD")) - (pos (and head (string-match "^refs/heads/" head)))) - (if pos - (substring head 11) - nil))) - -(defun magit-get-remote (branch) - "Return the name of the remote for BRANCH. -If branch is nil or it has no remote, but a remote named -\"origin\" exists, return that. Otherwise, return nil." - (let ((remote (or (and branch (magit-get "branch" branch "remote")) - (and (magit-get "remote" "origin" "url") "origin")))) - (if (string= remote "") nil remote))) - -(defun magit-get-current-remote () - "Return the name of the remote for the current branch. -If there is no current branch, or no remote for that branch, -but a remote named \"origin\" is configured, return that. -Otherwise, return nil." - (magit-get-remote (magit-get-current-branch))) - -(defun magit-ref-exists-p (ref) - (= (magit-git-exit-code "show-ref" "--verify" ref) 0)) - -(defun magit-read-top-dir (dir) - "Ask the user for a Git repository. The choices offered by -auto-completion will be the repositories under `magit-repo-dirs'. -If `magit-repo-dirs' is nil or DIR is non-nill, then -autocompletion will offer directory names." - (if (and (not dir) magit-repo-dirs) - (let* ((repos (magit-list-repos magit-repo-dirs)) - (reply (magit-completing-read "Git repository: " repos))) - (file-name-as-directory - (or (cdr (assoc reply repos)) - (if (file-directory-p reply) - (expand-file-name reply) - (error "Not a repository or a directory: %s" reply))))) - (file-name-as-directory - (read-directory-name "Git repository: " - (or (magit-get-top-dir default-directory) - default-directory))))) - -(defun magit-rev-parse (ref) - "Return the SHA hash for REF." - (magit-git-string "rev-parse" ref)) - -(defun magit-ref-ambiguous-p (ref) - "Return whether or not REF is ambiguous." - ;; If REF is ambiguous, rev-parse just prints errors, - ;; so magit-git-string returns nil. - (not (magit-git-string "rev-parse" "--abbrev-ref" ref))) - -(defun magit-name-rev (rev &optional no-trim) - "Return a human-readable name for REV. -Unlike git name-rev, this will remove tags/ and remotes/ prefixes -if that can be done unambiguously (unless optional arg NO-TRIM is -non-nil). In addition, it will filter out revs involving HEAD." - (when rev - (let ((name (magit-git-string "name-rev" "--no-undefined" "--name-only" rev))) - ;; There doesn't seem to be a way of filtering HEAD out from name-rev, - ;; so we have to do it manually. - ;; HEAD-based names are too transient to allow. - (when (and (stringp name) - (string-match "^\\(.*\\" name)) - (setq name (magit-rev-parse rev))))) - (setq rev (or name rev)) - (when (string-match "^\\(?:tags\\|remotes\\)/\\(.*\\)" rev) - (let ((plain-name (match-string 1 rev))) - (unless (or no-trim (magit-ref-ambiguous-p plain-name)) - (setq rev plain-name)))) - rev))) - -(defun magit-highlight-line-whitespace () - (when (and magit-highlight-whitespace - (or (derived-mode-p 'magit-status-mode) - (not (eq magit-highlight-whitespace 'status)))) - (if (and magit-highlight-trailing-whitespace - (looking-at "^[-+].*?\\([ \t]+\\)$")) - (overlay-put (make-overlay (match-beginning 1) (match-end 1)) - 'face 'magit-whitespace-warning-face)) - (if (or (and (eq magit-current-indentation 'tabs) - (looking-at "^[-+]\\( *\t[ \t]*\\)")) - (and (integerp magit-current-indentation) - (looking-at (format "^[-+]\\([ \t]* \\{%s,\\}[ \t]*\\)" - magit-current-indentation)))) - (overlay-put (make-overlay (match-beginning 1) (match-end 1)) - 'face 'magit-whitespace-warning-face)))) - -(defun magit-put-line-property (prop val) - (put-text-property (line-beginning-position) (line-beginning-position 2) - prop val)) - -(defun magit-format-commit (commit format) - (magit-git-string "log" "--max-count=1" - (concat "--pretty=format:" format) - commit)) - -(defun magit-current-line () - (buffer-substring-no-properties (line-beginning-position) - (line-end-position))) - -(defun magit-insert-region (beg end buf) - (let ((text (buffer-substring-no-properties beg end))) - (with-current-buffer buf - (insert text)))) - -(defun magit-insert-current-line (buf) - (let ((text (buffer-substring-no-properties - (line-beginning-position) (line-beginning-position 2)))) - (with-current-buffer buf - (insert text)))) - -(defun magit-file-uptodate-p (file) - (eq (magit-git-exit-code "diff" "--quiet" "--" file) 0)) - -(defun magit-anything-staged-p () - (not (eq (magit-git-exit-code "diff" "--quiet" "--cached") 0))) - -(defun magit-everything-clean-p () - (and (not (magit-anything-staged-p)) - (eq (magit-git-exit-code "diff" "--quiet") 0))) - -(defun magit-commit-parents (commit) - (cdr (split-string (magit-git-string "rev-list" "-1" "--parents" commit)))) - -;; XXX - let the user choose the parent - -(defun magit-choose-parent-id (commit op) - (let* ((parents (magit-commit-parents commit))) - (if (> (length parents) 1) - (error "Can't %s merge commits" op) - nil))) - -;;; Revisions and ranges - -(defvar magit-current-range nil - "The range described by the current buffer. -This is only non-nil in diff and log buffers. - -This has three possible (non-nil) forms. If it's a string REF or -a singleton list (REF), then the range is from REF to the current -working directory state (or HEAD in a log buffer). If it's a -pair (START . END), then the range is START..END.") -(make-variable-buffer-local 'magit-current-range) - -(defun magit-list-interesting-refs (&optional uninteresting) - "Return interesting references as given by `git show-ref'. -Removes references matching UNINTERESTING from the -results. UNINTERESTING can be either a function taking a single -argument or a list of strings used as regexps." - (let ((refs ())) - (dolist (line (magit-git-lines "show-ref")) - (if (string-match "[^ ]+ +\\(.*\\)" line) - (let ((ref (match-string 1 line))) - (cond ((and (functionp uninteresting) - (funcall uninteresting ref))) - ((and (not (functionp uninteresting)) - (loop for i in uninteresting thereis (string-match i ref)))) - (t - (let ((fmt-ref (magit-format-ref ref))) - (when fmt-ref - (push (cons fmt-ref - (replace-regexp-in-string "^refs/heads/" - "" ref)) - refs)))))))) - (nreverse refs))) - -(defun magit-format-ref (ref) - "Convert fully-specified ref REF into its displayable form -according to `magit-remote-ref-format'" - (cond - ((null ref) - nil) - ((string-match "refs/heads/\\(.*\\)" ref) - (match-string 1 ref)) - ((string-match "refs/tags/\\(.*\\)" ref) - (format (if (eq magit-remote-ref-format 'branch-then-remote) - "%s (tag)" - "%s") - (match-string 1 ref))) - ((string-match "refs/remotes/\\([^/]+\\)/\\(.+\\)" ref) - (if (eq magit-remote-ref-format 'branch-then-remote) - (format "%s (%s)" - (match-string 2 ref) - (match-string 1 ref)) - (format "%s/%s" - (match-string 1 ref) - (match-string 2 ref)))))) - -(defun magit-tree-contents (treeish) - "Returns a list of all files under TREEISH. TREEISH can be a tree, -a commit, or any reference to one of those." - (let ((return-value nil)) - (with-temp-buffer - (magit-git-insert (list "ls-tree" "-r" treeish)) - (if (eql 0 (buffer-size)) - (error "%s is not a commit or tree." treeish)) - (goto-char (point-min)) - (while (search-forward-regexp "\t\\(.*\\)" nil 'noerror) - (push (match-string 1) return-value))) - return-value)) - -(defvar magit-uninteresting-refs '("refs/remotes/\\([^/]+\\)/HEAD$" "refs/stash")) - -(defun magit-read-file-from-rev (revision) - (magit-completing-read (format "Retrieve file from %s: " revision) - (magit-tree-contents revision) - nil - 'require-match - nil - 'magit-read-file-hist - (if buffer-file-name - (let ((topdir-length (length (magit-get-top-dir default-directory)))) - (substring (buffer-file-name) topdir-length))))) - -(defun magit-read-rev (prompt &optional default uninteresting) - (let* ((interesting-refs (magit-list-interesting-refs - (or uninteresting magit-uninteresting-refs))) - (reply (magit-completing-read (concat prompt ": ") interesting-refs - nil nil nil 'magit-read-rev-history default)) - (rev (or (cdr (assoc reply interesting-refs)) reply))) - (if (string= rev "") - nil - rev))) - -(defun magit-read-rev-range (op &optional def-beg def-end) - (let ((beg (magit-read-rev (format "%s start" op) - def-beg))) - (if (not beg) - nil - (save-match-data - (if (string-match "^\\(.+\\)\\.\\.\\(.+\\)$" beg) - (cons (match-string 1 beg) (match-string 2 beg)) - (let ((end (magit-read-rev (format "%s end" op) def-end))) - (cons beg end))))))) - -(defun magit-rev-to-git (rev) - (or rev - (error "No revision specified")) - (if (string= rev ".") - (magit-marked-commit) - rev)) - -(defun magit-rev-range-to-git (range) - (or range - (error "No revision range specified")) - (if (stringp range) - range - (if (cdr range) - (format "%s..%s" - (magit-rev-to-git (car range)) - (magit-rev-to-git (cdr range))) - (format "%s" (magit-rev-to-git (car range)))))) - -(defun magit-rev-describe (rev) - (or rev - (error "No revision specified")) - (if (string= rev ".") - "mark" - (magit-name-rev rev))) - -(defun magit-rev-range-describe (range things) - (or range - (error "No revision range specified")) - (if (stringp range) - (format "%s in %s" things range) - (if (cdr range) - (format "%s from %s to %s" things - (magit-rev-describe (car range)) - (magit-rev-describe (cdr range))) - (format "%s at %s" things (magit-rev-describe (car range)))))) - -(defun magit-default-rev (&optional no-trim) - (or (magit-name-rev (magit-commit-at-point t) no-trim) - (let ((branch (magit-guess-branch))) - (if branch - (if (string-match "^refs/\\(.*\\)" branch) - (match-string 1 branch) - branch))))) - -(defun magit-read-remote (&optional prompt def) - "Read the name of a remote. -PROMPT is used as the prompt, and defaults to \"Remote\". -DEF is the default value." - (let* ((prompt (or prompt "Remote")) - (def (or def (magit-guess-remote))) - (remotes (magit-git-lines "remote")) - - (reply (magit-completing-read (concat prompt ": ") remotes - nil nil nil nil def))) - (if (string= reply "") nil reply))) - -(defun magit-read-remote-branch (remote &optional prompt default) - (let* ((prompt (or prompt (format "Remote branch (in %s)" remote))) - (branches (delete nil - (mapcar - (lambda (b) - (and (not (string-match " -> " b)) - (string-match (format "^ *%s/\\(.*\\)$" - (regexp-quote remote)) b) - (match-string 1 b))) - (magit-git-lines "branch" "-r")))) - (reply (magit-completing-read (concat prompt ": ") branches - nil nil nil nil default))) - (if (string= reply "") nil reply))) - -;;; Sections - -;; A buffer in magit-mode is organized into hierarchical sections. -;; These sections are used for navigation and for hiding parts of the -;; buffer. -;; -;; Most sections also represent the objects that Magit works with, -;; such as files, diffs, hunks, commits, etc. The 'type' of a section -;; identifies what kind of object it represents (if any), and the -;; parent and grand-parent, etc provide the context. - -(defstruct magit-section - parent title beginning end children hidden type info - needs-refresh-on-show) - -(defvar magit-top-section nil - "The top section of the current buffer.") -(make-variable-buffer-local 'magit-top-section) -(put 'magit-top-section 'permanent-local t) - -(defvar magit-old-top-section nil) - -(defvar magit-section-hidden-default nil) - -(defun magit-new-section (title type) - "Create a new section with title TITLE and type TYPE in current buffer. - -If not `magit-top-section' exist, the new section will be the new top-section -otherwise, the new-section will be a child of the current top-section. - -If TYPE is nil, the section won't be highlighted." - (let* ((s (make-magit-section :parent magit-top-section - :title title - :type type - :hidden magit-section-hidden-default)) - (old (and magit-old-top-section - (magit-find-section (magit-section-path s) - magit-old-top-section)))) - (if magit-top-section - (push s (magit-section-children magit-top-section)) - (setq magit-top-section s)) - (if old - (setf (magit-section-hidden s) (magit-section-hidden old))) - s)) - -(defun magit-cancel-section (section) - "Delete the section SECTION." - (delete-region (magit-section-beginning section) - (magit-section-end section)) - (let ((parent (magit-section-parent section))) - (if parent - (setf (magit-section-children parent) - (delq section (magit-section-children parent))) - (setq magit-top-section nil)))) - -(defmacro magit-with-section (title type &rest body) - "Create a new section of title TITLE and type TYPE and evaluate BODY there. - -Sections created inside BODY will become children of the new -section. BODY must leave point at the end of the created section. - -If TYPE is nil, the section won't be highlighted." - (declare (indent 2)) - (let ((s (make-symbol "*section*"))) - `(let* ((,s (magit-new-section ,title ,type)) - (magit-top-section ,s)) - (setf (magit-section-beginning ,s) (point)) - ,@body - (setf (magit-section-end ,s) (point)) - (setf (magit-section-children ,s) - (nreverse (magit-section-children ,s))) - ,s))) - -(defun magit-set-section (title type start end) - "Create a new section of title TITLE and type TYPE with specified start and -end positions." - (let ((section (magit-new-section title type))) - (setf (magit-section-beginning section) start) - (setf (magit-section-end section) end) - section)) - -(defun magit-set-section-info (info &optional section) - (setf (magit-section-info (or section magit-top-section)) info)) - -(defun magit-set-section-needs-refresh-on-show (flag &optional section) - (setf (magit-section-needs-refresh-on-show - (or section magit-top-section)) - flag)) - -(defmacro magit-create-buffer-sections (&rest body) - "Empty current buffer of text and Magit's sections, and then evaluate BODY." - (declare (indent 0)) - `(let ((inhibit-read-only t)) - (erase-buffer) - (let ((magit-old-top-section magit-top-section)) - (setq magit-top-section nil) - ,@body - (when (null magit-top-section) - (magit-with-section 'top nil - (insert "(empty)\n"))) - (magit-propertize-section magit-top-section) - (magit-section-set-hidden magit-top-section - (magit-section-hidden magit-top-section))))) - -(defun magit-propertize-section (section) - "Add text-property needed for SECTION." - (put-text-property (magit-section-beginning section) - (magit-section-end section) - 'magit-section section) - (dolist (s (magit-section-children section)) - (magit-propertize-section s))) - -(defun magit-find-section (path top) - "Find the section at the path PATH in subsection of section TOP." - (if (null path) - top - (let ((secs (magit-section-children top))) - (while (and secs (not (equal (car path) - (magit-section-title (car secs))))) - (setq secs (cdr secs))) - (and (car secs) - (magit-find-section (cdr path) (car secs)))))) - -(defun magit-section-path (section) - "Return the path of SECTION." - (if (not (magit-section-parent section)) - '() - (append (magit-section-path (magit-section-parent section)) - (list (magit-section-title section))))) - -(defun magit-find-section-after (pos) - "Find the first section that begins after POS." - (magit-find-section-after* pos (list magit-top-section))) - -(defun magit-find-section-after* (pos secs) - "Find the first section that begins after POS in the list SECS -\(including children of sections in SECS)." - (while (and secs - (<= (magit-section-beginning (car secs)) pos)) - (setq secs (if (magit-section-hidden (car secs)) - (cdr secs) - (append (magit-section-children (car secs)) - (cdr secs))))) - (car secs)) - -(defun magit-find-section-before (pos) - "Return the last section that begins before POS." - (let ((section (magit-find-section-at pos))) - (do* ((current (or (magit-section-parent section) - section) - next) - (next (if (not (magit-section-hidden current)) - (magit-find-section-before* pos (magit-section-children current))) - (if (not (magit-section-hidden current)) - (magit-find-section-before* pos (magit-section-children current))))) - ((null next) current)))) - -(defun magit-find-section-before* (pos secs) - "Find the last section that begins before POS in the list SECS." - (let ((prev nil)) - (while (and secs - (< (magit-section-beginning (car secs)) pos)) - (setq prev (car secs)) - (setq secs (cdr secs))) - prev)) - -(defun magit-current-section () - "Return the Magit section at point." - (magit-find-section-at (point))) - -(defun magit-find-section-at (pos) - "Return the Magit section at POS." - (or (get-text-property pos 'magit-section) - magit-top-section)) - -(defun magit-insert-section (section-title-and-type - buffer-title washer cmd &rest args) - "Run CMD and put its result in a new section. - -SECTION-TITLE-AND-TYPE is either a string that is the title of the section -or (TITLE . TYPE) where TITLE is the title of the section and TYPE is its type. - -If there is no type, or if type is nil, the section won't be highlighted. - -BUFFER-TITLE is the inserted title of the section - -WASHER is a function that will be run after CMD. -The buffer will be narrowed to the inserted text. -It should add sectioning as needed for Magit interaction. - -CMD is an external command that will be run with ARGS as arguments." - (let* ((body-beg nil) - (section-title (if (consp section-title-and-type) - (car section-title-and-type) - section-title-and-type)) - (section-type (if (consp section-title-and-type) - (cdr section-title-and-type) - nil)) - (section - (magit-with-section section-title section-type - (if buffer-title - (insert (propertize buffer-title 'face 'magit-section-title) - "\n")) - (setq body-beg (point)) - (magit-cmd-insert cmd args) - (if (not (eq (char-before) ?\n)) - (insert "\n")) - (if washer - (save-restriction - (narrow-to-region body-beg (point)) - (goto-char (point-min)) - (funcall washer) - (goto-char (point-max))))))) - (if (= body-beg (point)) - (magit-cancel-section section) - (insert "\n")) - section)) - -(defun magit-git-section (section-title-and-type - buffer-title washer &rest args) - "Run git and put its result in a new section. - -see `magit-insert-section' for meaning of the arguments" - (apply #'magit-insert-section - section-title-and-type - buffer-title - washer - magit-git-executable - (append magit-git-standard-options args))) - -(defun magit-goto-next-section () - "Go to the next section." - (interactive) - (let ((next (magit-find-section-after (point)))) - (if next - (magit-goto-section next) - (message "No next section")))) - -(defun magit-goto-previous-section () - "Go to the previous section." - (interactive) - (if (eq (point) 1) - (message "No previous section") - (magit-goto-section (magit-find-section-before (point))))) - -(defun magit-goto-parent-section () - "Go to the parent section." - (interactive) - (let ((parent (magit-section-parent (magit-current-section)))) - (when parent - (goto-char (magit-section-beginning parent))))) - -(defun magit-goto-next-sibling-section () - "Go to the next sibling section." - (interactive) - (let* ((initial (point)) - (section (magit-current-section)) - (end (- (magit-section-end section) 1)) - (parent (magit-section-parent section)) - (siblings (magit-section-children parent)) - (next-sibling (magit-find-section-after* end siblings))) - (if next-sibling - (magit-goto-section next-sibling) - (magit-goto-next-section)))) - -(defun magit-goto-previous-sibling-section () - "Go to the previous sibling section." - (interactive) - (let* ((section (magit-current-section)) - (beginning (magit-section-beginning section)) - (parent (magit-section-parent section)) - (siblings (magit-section-children parent)) - (previous-sibling (magit-find-section-before* beginning siblings))) - (if previous-sibling - (magit-goto-section previous-sibling) - (magit-goto-parent-section)))) - -(defun magit-goto-section (section) - (goto-char (magit-section-beginning section)) - (cond - ((and magit-log-auto-more - (eq (magit-section-type section) 'longer)) - (magit-log-show-more-entries) - (forward-line -1) - (magit-goto-next-section)) - ((and (eq (magit-section-type section) 'commit) - (derived-mode-p 'magit-log-mode)) - (magit-show-commit section)))) - -(defun magit-goto-section-at-path (path) - "Go to the section described by PATH." - (let ((sec (magit-find-section path magit-top-section))) - (if sec - (goto-char (magit-section-beginning sec)) - (message "No such section")))) - -(defun magit-for-all-sections (func &optional top) - "Run FUNC on TOP and recursively on all its children. - -Default value for TOP is `magit-top-section'" - (let ((section (or top magit-top-section))) - (when section - (funcall func section) - (dolist (c (magit-section-children section)) - (magit-for-all-sections func c))))) - -(defun magit-section-set-hidden (section hidden) - "Hide SECTION if HIDDEN is not nil, show it otherwise." - (setf (magit-section-hidden section) hidden) - (if (and (not hidden) - (magit-section-needs-refresh-on-show section)) - (magit-refresh) - (let ((inhibit-read-only t) - (beg (save-excursion - (goto-char (magit-section-beginning section)) - (forward-line) - (point))) - (end (magit-section-end section))) - (if (< beg end) - (put-text-property beg end 'invisible hidden))) - (if (not hidden) - (dolist (c (magit-section-children section)) - (magit-section-set-hidden c (magit-section-hidden c)))))) - -(defun magit-section-any-hidden (section) - "Return true if SECTION or any of its children is hidden." - (or (magit-section-hidden section) - (let ((kids (magit-section-children section))) - (while (and kids (not (magit-section-any-hidden (car kids)))) - (setq kids (cdr kids))) - kids))) - -(defun magit-section-collapse (section) - "Show SECTION and hide all its children." - (dolist (c (magit-section-children section)) - (setf (magit-section-hidden c) t)) - (magit-section-set-hidden section nil)) - -(defun magit-section-expand (section) - "Show SECTION and all its children." - (dolist (c (magit-section-children section)) - (setf (magit-section-hidden c) nil)) - (magit-section-set-hidden section nil)) - -(defun magit-section-expand-all-aux (section) - "Show recursively all SECTION's children." - (dolist (c (magit-section-children section)) - (setf (magit-section-hidden c) nil) - (magit-section-expand-all-aux c))) - -(defun magit-section-expand-all (section) - "Show SECTION and all its children." - (magit-section-expand-all-aux section) - (magit-section-set-hidden section nil)) - -(defun magit-section-hideshow (flag-or-func) - "Show or hide current section depending on FLAG-OR-FUNC. - -If FLAG-OR-FUNC is a function, it will be ran on current section -IF FLAG-OR-FUNC is a Boolean value, the section will be hidden if its true, shown otherwise" - (let ((section (magit-current-section))) - (when (magit-section-parent section) - (goto-char (magit-section-beginning section)) - (if (functionp flag-or-func) - (funcall flag-or-func section) - (magit-section-set-hidden section flag-or-func))))) - -(defun magit-show-section () - "Show current section." - (interactive) - (magit-section-hideshow nil)) - -(defun magit-hide-section () - "Hide current section." - (interactive) - (magit-section-hideshow t)) - -(defun magit-collapse-section () - "Hide all subsection of current section." - (interactive) - (magit-section-hideshow #'magit-section-collapse)) - -(defun magit-expand-section () - "Show all subsection of current section." - (interactive) - (magit-section-hideshow #'magit-section-expand)) - -(defun magit-toggle-file-section () - "Like `magit-toggle-section' but toggle at file granularity." - (interactive) - (when (eq 'hunk (first (magit-section-context-type (magit-current-section)))) - (magit-goto-parent-section)) - (magit-toggle-section)) - -(defun magit-toggle-section () - "Toggle hidden status of current section." - (interactive) - (magit-section-hideshow - (lambda (s) - (magit-section-set-hidden s (not (magit-section-hidden s)))))) - -(defun magit-expand-collapse-section () - "Toggle hidden status of subsections of current section." - (interactive) - (magit-section-hideshow - (lambda (s) - (cond ((magit-section-any-hidden s) - (magit-section-expand-all s)) - (t - (magit-section-collapse s)))))) - -(defun magit-cycle-section () - "Cycle between expanded, hidden and collapsed state for current section. - -Hidden: only the first line of the section is shown -Collapsed: only the first line of the subsection is shown -Expanded: everything is shown." - (interactive) - (magit-section-hideshow - (lambda (s) - (cond ((magit-section-hidden s) - (magit-section-collapse s)) - ((notany #'magit-section-hidden (magit-section-children s)) - (magit-section-set-hidden s t)) - (t - (magit-section-expand s)))))) - -(defun magit-section-lineage (s) - "Return list of parent, grand-parents... for section S." - (when s - (cons s (magit-section-lineage (magit-section-parent s))))) - -(defun magit-section-show-level (section level threshold path) - (magit-section-set-hidden section (>= level threshold)) - (when (and (< level threshold) - (not (magit-no-commit-p))) - (if path - (magit-section-show-level (car path) (1+ level) threshold (cdr path)) - (dolist (c (magit-section-children section)) - (magit-section-show-level c (1+ level) threshold nil))))) - -(defun magit-show-level (level all) - "Show section whose level is less than LEVEL, hide the others. -If ALL is non nil, do this in all sections, -otherwise do it only on ancestors and descendants of current section." - (magit-with-refresh - (if all - (magit-section-show-level magit-top-section 0 level nil) - (let ((path (reverse (magit-section-lineage (magit-current-section))))) - (magit-section-show-level (car path) 0 level (cdr path)))))) - -(defun magit-show-only-files () - "Show section that are files, but not there subsection. - -Do this in on ancestors and descendants of current section." - (interactive) - (if (derived-mode-p 'magit-status-mode) - (call-interactively 'magit-show-level-2) - (call-interactively 'magit-show-level-1))) - -(defun magit-show-only-files-all () - "Show section that are files, but not there subsection. - -Do this for all sections" - (interactive) - (if (derived-mode-p 'magit-status-mode) - (call-interactively 'magit-show-level-2-all) - (call-interactively 'magit-show-level-1-all))) - -(defmacro magit-define-level-shower-1 (level all) - "Define an interactive function to show function of level LEVEL. - -If ALL is non nil, this function will affect all section, -otherwise it will affect only ancestors and descendants of current section." - (let ((fun (intern (format "magit-show-level-%s%s" - level (if all "-all" "")))) - (doc (format "Show sections on level %s." level))) - `(defun ,fun () - ,doc - (interactive) - (magit-show-level ,level ,all)))) - -(defmacro magit-define-level-shower (level) - "Define two interactive function to show function of level LEVEL. -one for all, one for current lineage." - `(progn - (magit-define-level-shower-1 ,level nil) - (magit-define-level-shower-1 ,level t))) - -(defmacro magit-define-section-jumper (sym title) - "Define an interactive function to go to section SYM. - -TITLE is the displayed title of the section." - (let ((fun (intern (format "magit-jump-to-%s" sym))) - (doc (format "Jump to section `%s'." title))) - `(progn - (defun ,fun () - ,doc - (interactive) - (magit-goto-section-at-path '(,sym))) - (put ',fun 'definition-name ',sym)))) - -(defmacro magit-define-inserter (sym arglist &rest body) - (declare (indent defun)) - (let ((fun (intern (format "magit-insert-%s" sym))) - (before (intern (format "magit-before-insert-%s-hook" sym))) - (after (intern (format "magit-after-insert-%s-hook" sym))) - (doc (format "Insert items for `%s'." sym))) - `(progn - (defvar ,before nil) - (defvar ,after nil) - (defun ,fun ,arglist - ,doc - (run-hooks ',before) - ,@body - (run-hooks ',after)) - (put ',before 'definition-name ',sym) - (put ',after 'definition-name ',sym) - (put ',fun 'definition-name ',sym)))) - -(defvar magit-highlighted-section nil) - -(defun magit-refine-section (section) - "Apply temporary refinements to the display of SECTION. -Refinements can be undone with `magit-unrefine-section'." - (let ((type (and section (magit-section-type section)))) - (cond ((and (eq type 'hunk) - magit-diff-refine-hunk - (not (eq magit-diff-refine-hunk 'all))) - ;; Refine the current hunk to show fine details, using - ;; diff-mode machinery. - (save-excursion - (goto-char (magit-section-beginning magit-highlighted-section)) - (diff-refine-hunk)))))) - -(defun magit-unrefine-section (section) - "Remove refinements to the display of SECTION done by `magit-refine-section'." - (let ((type (and section (magit-section-type section)))) - (cond ((and (eq type 'hunk) - magit-diff-refine-hunk - (not (eq magit-diff-refine-hunk 'all))) - ;; XXX this should be in some diff-mode function, like - ;; `diff-unrefine-hunk' - (remove-overlays (magit-section-beginning section) - (magit-section-end section) - 'diff-mode 'fine))))) - -(defvar magit-highlight-overlay nil) - -(defun magit-highlight-section () - "Highlight current section if it has a type." - (let ((section (magit-current-section))) - (when (not (eq section magit-highlighted-section)) - (when magit-highlighted-section - ;; remove any refinement from previous hunk - (magit-unrefine-section magit-highlighted-section)) - (setq magit-highlighted-section section) - (if (not magit-highlight-overlay) - (let ((ov (make-overlay 1 1))) - (overlay-put ov 'face 'magit-item-highlight) - (setq magit-highlight-overlay ov))) - (if (and section (magit-section-type section)) - (progn - (magit-refine-section section) - (move-overlay magit-highlight-overlay - (magit-section-beginning section) - (magit-section-end section) - (current-buffer))) - (delete-overlay magit-highlight-overlay))))) - -(defun magit-section-context-type (section) - (if (null section) - '() - (let ((c (or (magit-section-type section) - (if (symbolp (magit-section-title section)) - (magit-section-title section))))) - (if c - (cons c (magit-section-context-type - (magit-section-parent section))) - '())))) - -(defun magit-prefix-p (prefix list) - "Returns non-nil if PREFIX is a prefix of LIST. PREFIX and LIST should both be -lists. - -If the car of PREFIX is the symbol '*, then return non-nil if the cdr of PREFIX -is a sublist of LIST (as if '* matched zero or more arbitrary elements of LIST)" - ;;; Very schemish... - (or (null prefix) - (if (eq (car prefix) '*) - (or (magit-prefix-p (cdr prefix) list) - (and (not (null list)) - (magit-prefix-p prefix (cdr list)))) - (and (not (null list)) - (equal (car prefix) (car list)) - (magit-prefix-p (cdr prefix) (cdr list)))))) - -(defmacro magit-section-case (head &rest clauses) - "Make different action depending of current section. - -HEAD is (SECTION INFO &optional OPNAME), - SECTION will be bind to the current section, - INFO will be bind to the info's of the current section, - OPNAME is a string that will be used to describe current action, - -CLAUSES is a list of CLAUSE, each clause is (SECTION-TYPE &BODY) -where SECTION-TYPE describe section where BODY will be run. - -This returns non-nil if some section matches. If the -corresponding body return a non-nil value, it is returned, -otherwise it returns t. - -If no section matches, this returns nil if no OPNAME was given -and throws an error otherwise." - (declare (indent 1)) - (let ((section (car head)) - (info (cadr head)) - (type (make-symbol "*type*")) - (context (make-symbol "*context*")) - (opname (caddr head))) - `(let* ((,section (magit-current-section)) - (,info (and ,section (magit-section-info ,section))) - (,type (and ,section (magit-section-type ,section))) - (,context (magit-section-context-type ,section))) - (cond ,@(mapcar (lambda (clause) - (if (eq (car clause) t) - `(t (or (progn ,@(cdr clause)) - t)) - (let ((prefix (reverse (car clause))) - (body (cdr clause))) - `((magit-prefix-p ',prefix ,context) - (or (progn ,@body) - t))))) - clauses) - ,@(when opname - `(((run-hook-with-args-until-success - ',(intern (format "magit-%s-action-hook" opname)))) - ((not ,type) - (error "Nothing to %s here" ,opname)) - (t - (error "Can't %s a %s" - ,opname - (or (get ,type 'magit-description) - ,type))))))))) - -(defmacro magit-section-action (head &rest clauses) - (declare (indent 1)) - `(magit-with-refresh - (magit-section-case ,head ,@clauses))) - -(defmacro magit-add-action (head &rest clauses) - "Add additional actions to a pre-existing operator. -The syntax is identical to `magit-section-case', except that -OPNAME is mandatory and specifies the operation to which to add -the actions." - (declare (indent 1)) - (let ((section (car head)) - (info (cadr head)) - (type (caddr head))) - `(add-hook ',(intern (format "magit-%s-action-hook" type)) - (lambda () - ,(macroexpand - ;; Don't pass in the opname so we don't recursively - ;; run the hook again, and so we don't throw an - ;; error if no action matches. - `(magit-section-case (,section ,info) - ,@clauses)))))) - -(defun magit-wash-sequence (func) - "Run FUNC until end of buffer is reached. - -FUNC should leave point at the end of the modified region" - (while (and (not (eobp)) - (funcall func)))) - -(defmacro magit-define-command (sym arglist &rest body) - "Macro to define a magit command. -It will define the magit-SYM function having ARGLIST as argument. -It will also define the magit-SYM-command-hook variable. - -The defined function will call the function in the hook in -order until one return non nil. If they all return nil then body will be called. - -It is used to define hookable magit command: command defined by this -function can be enriched by magit extension like magit-topgit and magit-svn" - (declare (indent defun) - (debug (&define name lambda-list - [&optional stringp] ; Match the doc string, if present. - [&optional ("interactive" interactive)] - def-body))) - (let ((fun (intern (format "magit-%s" sym))) - (hook (intern (format "magit-%s-command-hook" sym))) - (doc (format "Command for `%s'." sym)) - (inter nil) - (instr body)) - (when (stringp (car body)) - (setq doc (car body) - instr (cdr body))) - (let ((form (car instr))) - (when (eq (car form) 'interactive) - (setq inter form - instr (cdr instr)))) - `(progn - (defvar ,hook nil) - (defun ,fun ,arglist - ,doc - ,inter - (or (run-hook-with-args-until-success - ',hook ,@(remq '&optional (remq '&rest arglist))) - ,@instr)) - (put ',fun 'definition-name ',sym) - (put ',hook 'definition-name ',sym)))) - -;;; Running commands - -(defun magit-set-mode-line-process (str) - (let ((pr (if str (concat " " str) ""))) - (save-excursion - (magit-for-all-buffers (lambda () - (setq mode-line-process pr)))))) - -(defun magit-process-indicator-from-command (comps) - (if (magit-prefix-p (cons magit-git-executable magit-git-standard-options) - comps) - (setq comps (nthcdr (+ (length magit-git-standard-options) 1) comps))) - (cond ((or (null (cdr comps)) - (not (member (car comps) '("remote")))) - (car comps)) - (t - (concat (car comps) " " (cadr comps))))) - -(defvar magit-process nil) -(defvar magit-process-client-buffer nil) -(defvar magit-process-buffer-name "*magit-process*" - "Buffer name for running git commands.") - -(defun magit-run* (cmd-and-args - &optional logline noerase noerror nowait input) - (if (and magit-process - (get-buffer magit-process-buffer-name)) - (error "Git is already running")) - (let ((cmd (car cmd-and-args)) - (args (cdr cmd-and-args)) - (dir default-directory) - (buf (get-buffer-create magit-process-buffer-name)) - (successp nil)) - (magit-set-mode-line-process - (magit-process-indicator-from-command cmd-and-args)) - (setq magit-process-client-buffer (current-buffer)) - (with-current-buffer buf - (view-mode 1) - (set (make-local-variable 'view-no-disable-on-exit) t) - (setq view-exit-action - (lambda (buffer) - (with-current-buffer buffer - (bury-buffer)))) - (setq buffer-read-only t) - (let ((inhibit-read-only t)) - (setq default-directory dir) - (if noerase - (goto-char (point-max)) - (erase-buffer)) - (insert "$ " (or logline - (mapconcat 'identity cmd-and-args " ")) - "\n") - (cond (nowait - (setq magit-process - (let ((process-connection-type magit-process-connection-type)) - (apply 'magit-start-process cmd buf cmd args))) - (set-process-sentinel magit-process 'magit-process-sentinel) - (set-process-filter magit-process 'magit-process-filter) - (when input - (with-current-buffer input - (process-send-region magit-process - (point-min) (point-max))) - (process-send-eof magit-process) - (sit-for 0.1 t)) - (cond ((= magit-process-popup-time 0) - (pop-to-buffer (process-buffer magit-process))) - ((> magit-process-popup-time 0) - (run-with-timer - magit-process-popup-time nil - (function - (lambda (buf) - (with-current-buffer buf - (when magit-process - (display-buffer (process-buffer magit-process)) - (goto-char (point-max)))))) - (current-buffer)))) - (setq successp t)) - (input - (with-current-buffer input - (setq default-directory dir) - (setq magit-process - ;; Don't use a pty, because it would set icrnl - ;; which would modify the input (issue #20). - (let ((process-connection-type nil)) - (apply 'magit-start-process cmd buf cmd args))) - (set-process-filter magit-process 'magit-process-filter) - (process-send-region magit-process - (point-min) (point-max)) - (process-send-eof magit-process) - (while (equal (process-status magit-process) 'run) - (sit-for 0.1 t)) - (setq successp - (equal (process-exit-status magit-process) 0)) - (setq magit-process nil)) - (magit-set-mode-line-process nil) - (magit-need-refresh magit-process-client-buffer)) - (t - (setq successp - (equal (apply 'process-file cmd nil buf nil args) 0)) - (magit-set-mode-line-process nil) - (magit-need-refresh magit-process-client-buffer)))) - (or successp - noerror - (error - "%s ... [Hit %s or see buffer %s for details]" - (or (with-current-buffer (get-buffer magit-process-buffer-name) - (when (re-search-backward - (concat "^error: \\(.*\\)" paragraph-separate) nil t) - (match-string 1))) - "Git failed") - (with-current-buffer magit-process-client-buffer - (key-description (car (where-is-internal - 'magit-display-process)))) - magit-process-buffer-name)) - successp))) - -(autoload 'dired-uncache "dired") -(defun magit-process-sentinel (process event) - (let ((msg (format "%s %s." (process-name process) (substring event 0 -1))) - (successp (string-match "^finished" event)) - (key (with-current-buffer magit-process-client-buffer - (key-description (car (where-is-internal - 'magit-display-process)))))) - (with-current-buffer (process-buffer process) - (let ((inhibit-read-only t)) - (goto-char (point-max)) - (insert msg "\n") - (message (if successp msg - (format "%s Hit %s or see buffer %s for details." - msg key (current-buffer))))) - (unless (memq (process-status process) '(run open)) - (dired-uncache default-directory))) - (setq magit-process nil) - (magit-set-mode-line-process nil) - (magit-refresh-buffer magit-process-client-buffer))) - -(defun magit-password (proc string) - "Checks if git/ssh asks for a password and ask the user for it." - (let (ask) - (cond ((or (string-match "^Enter passphrase for key '\\\(.*\\\)': $" string) - (string-match "^\\\(.*\\\)'s password:" string) - (string-match "^Password for '\\\(.*\\\)':" string)) - (setq ask (format "Password for '%s': " (match-string 1 string)))) - ((string-match "^[pP]assword:" string) - (setq ask "Password:"))) - (when ask - (process-send-string proc (concat (read-passwd ask nil) "\n"))))) - -(defun magit-username (proc string) - "Checks if git asks for a username and ask the user for it." - (when (string-match "^Username for '\\\(.*\\\)':" string) - (process-send-string proc - (concat - (read-string (format "Username for '%s': " - (match-string 1 string)) - nil nil (user-login-name)) - "\n")))) - -(defun magit-process-filter (proc string) - (save-current-buffer - (set-buffer (process-buffer proc)) - (let ((inhibit-read-only t)) - (magit-username proc string) - (magit-password proc string) - (goto-char (process-mark proc)) - ;; Find last ^M in string. If one was found, ignore everything - ;; before it and delete the current line. - (let ((ret-pos (length string))) - (while (and (>= (setq ret-pos (1- ret-pos)) 0) - (/= ?\r (aref string ret-pos)))) - (cond ((>= ret-pos 0) - (goto-char (line-beginning-position)) - (delete-region (point) (line-end-position)) - (insert (substring string (+ ret-pos 1)))) - (t - (insert string)))) - (set-marker (process-mark proc) (point))))) - -(defun magit-run (cmd &rest args) - (magit-with-refresh - (magit-run* (cons cmd args)))) - -(defun magit-run-git (&rest args) - (magit-with-refresh - (magit-run* (append (cons magit-git-executable - magit-git-standard-options) - args)))) - -(defun magit-run-git-with-input (input &rest args) - (magit-with-refresh - (magit-run* (append (cons magit-git-executable - magit-git-standard-options) - args) - nil nil nil nil input))) - -(defun magit-run-git-async (&rest args) - (message "Running %s %s" magit-git-executable (mapconcat 'identity args " ")) - (magit-run* (append (cons magit-git-executable - magit-git-standard-options) - args) - nil nil nil t)) - -(defun magit-run-async-with-input (input cmd &rest args) - (magit-run* (cons cmd args) nil nil nil t input)) - -(defun magit-display-process () - "Display output from most recent git command." - (interactive) - (unless (get-buffer magit-process-buffer-name) - (error "No Git commands have run")) - (display-buffer magit-process-buffer-name)) - -;;; Mode - -;; We define individual functions (instead of using lambda etc) so -;; that the online help can show something meaningful. - -(magit-define-section-jumper untracked "Untracked files") -(magit-define-section-jumper unstaged "Unstaged changes") -(magit-define-section-jumper staged "Staged changes") -(magit-define-section-jumper unpushed "Unpushed commits") - -(magit-define-level-shower 1) -(magit-define-level-shower 2) -(magit-define-level-shower 3) -(magit-define-level-shower 4) - -(easy-menu-define magit-mode-menu magit-mode-map - "Magit menu" - '("Magit" - ["Refresh" magit-refresh t] - ["Refresh all" magit-refresh-all t] - "---" - ["Stage" magit-stage-item t] - ["Stage all" magit-stage-all t] - ["Unstage" magit-unstage-item t] - ["Unstage all" magit-unstage-all t] - ["Commit" magit-log-edit t] - ["Add log entry" magit-add-log t] - ["Tag" magit-tag t] - ["Annotated tag" magit-annotated-tag t] - "---" - ["Diff working tree" magit-diff-working-tree t] - ["Diff" magit-diff t] - ("Log" - ["Short Log" magit-log t] - ["Long Log" magit-log-long t] - ["Reflog" magit-reflog t] - ["Extended..." magit-key-mode-popup-logging t]) - "---" - ["Cherry pick" magit-cherry-pick-item t] - ["Apply" magit-apply-item t] - ["Revert" magit-revert-item t] - "---" - ["Ignore" magit-ignore-item t] - ["Ignore locally" magit-ignore-item-locally t] - ["Discard" magit-discard-item t] - ["Reset head" magit-reset-head t] - ["Reset working tree" magit-reset-working-tree t] - ["Stash" magit-stash t] - ["Snapshot" magit-stash-snapshot t] - "---" - ["Branch..." magit-checkout t] - ["Merge" magit-manual-merge t] - ["Interactive resolve" magit-interactive-resolve-item t] - ["Rebase" magit-rebase-step t] - ("Rewrite" - ["Start" magit-rewrite-start t] - ["Stop" magit-rewrite-stop t] - ["Finish" magit-rewrite-finish t] - ["Abort" magit-rewrite-abort t] - ["Set used" magit-rewrite-set-used t] - ["Set unused" magit-rewrite-set-unused t]) - "---" - ["Push" magit-push t] - ["Pull" magit-pull t] - ["Remote update" magit-remote-update t] - ("Submodule" - ["Submodule update" magit-submodule-update t] - ["Submodule update and init" magit-submodule-update-init t] - ["Submodule init" magit-submodule-init t] - ["Submodule sync" magit-submodule-sync t]) - "---" - ("Extensions") - "---" - ["Display Git output" magit-display-process t] - ["Quit Magit" magit-quit-window t])) - -(defvar magit-mode-hook nil "Hook run by `magit-mode'.") - -(put 'magit-mode 'mode-class 'special) - -(defvar magit-refresh-function nil) -(make-variable-buffer-local 'magit-refresh-function) -(put 'magit-refresh-function 'permanent-local t) - -(defvar magit-refresh-args nil) -(make-variable-buffer-local 'magit-refresh-args) -(put 'magit-refresh-args 'permanent-local t) - -(defvar last-point) - -(defun magit-remember-point () - (setq last-point (point))) - -(defun magit-invisible-region-end (pos) - (while (and (not (= pos (point-max))) (invisible-p pos)) - (setq pos (next-char-property-change pos))) - pos) - -(defun magit-invisible-region-start (pos) - (while (and (not (= pos (point-min))) (invisible-p pos)) - (setq pos (1- (previous-char-property-change pos)))) - pos) - -(defun magit-correct-point-after-command () - "Move point outside of invisible regions. - -Emacs often leaves point in invisible regions, it seems. To fix -this, we move point ourselves and never let Emacs do its own -adjustments. - -When point has to be moved out of an invisible region, it can be -moved to its end or its beginning. We usually move it to its -end, except when that would move point back to where it was -before the last command." - (if (invisible-p (point)) - (let ((end (magit-invisible-region-end (point)))) - (goto-char (if (= end last-point) - (magit-invisible-region-start (point)) - end)))) - (setq disable-point-adjustment t)) - -(defun magit-post-command-hook () - (magit-correct-point-after-command) - (magit-highlight-section)) - -(defun magit-mode () - "Review the status of a git repository and act on it. - -Please see the manual for a complete description of Magit. - -\\{magit-mode-map}" - (kill-all-local-variables) - (buffer-disable-undo) - (setq buffer-read-only t - truncate-lines t - major-mode 'magit-mode - mode-name "Magit" - mode-line-process "") - (add-hook 'pre-command-hook #'magit-remember-point nil t) - (add-hook 'post-command-hook #'magit-post-command-hook t t) - (use-local-map magit-mode-map) - (setq magit-current-indentation (magit-indentation-for default-directory)) - ;; Emacs' normal method of showing trailing whitespace gives weird - ;; results when `magit-whitespace-warning-face' is different from - ;; `trailing-whitespace'. - (if (and magit-highlight-whitespace magit-highlight-trailing-whitespace) - (setq show-trailing-whitespace nil)) - (run-mode-hooks 'magit-mode-hook)) - -(defun magit-mode-init (dir submode refresh-func &rest refresh-args) - (setq default-directory dir - magit-refresh-function refresh-func - magit-refresh-args refresh-args) - (funcall submode) - (magit-refresh-buffer)) - -(defun magit-indentation-for (dir) - (let (result) - (dolist (pair magit-highlight-indentation) - (if (string-match-p (car pair) dir) - (setq result (cdr pair)))) - result)) - -(defun magit-find-buffer (submode &optional dir) - (let ((topdir (magit-get-top-dir (or dir default-directory)))) - (dolist (buf (buffer-list)) - (if (with-current-buffer buf - (and (eq major-mode submode) - default-directory - (equal (expand-file-name default-directory) topdir))) - (return buf))))) - -(defun magit-find-status-buffer (&optional dir) - (magit-find-buffer 'magit-status-mode dir)) - -(defun magit-for-all-buffers (func &optional dir) - (dolist (buf (buffer-list)) - (with-current-buffer buf - (if (and (derived-mode-p 'magit-mode) - (or (null dir) - (equal default-directory dir))) - (funcall func))))) - -(defun magit-refresh-buffer (&optional buffer) - (with-current-buffer (or buffer (current-buffer)) - (let* ((old-line (line-number-at-pos)) - (old-point (point)) - (old-section (magit-current-section)) - (old-path (and old-section - (magit-section-path (magit-current-section))))) - (beginning-of-line) - (let ((section-line (and old-section - (count-lines - (magit-section-beginning old-section) - (point)))) - (line-char (- old-point (point)))) - (if magit-refresh-function - (apply magit-refresh-function - magit-refresh-args)) - (magit-refresh-marked-commits-in-buffer) - (let ((s (and old-path (magit-find-section old-path magit-top-section)))) - (cond (s - (goto-char (magit-section-beginning s)) - (forward-line section-line) - (forward-char line-char)) - (t - (magit-goto-line old-line))) - (dolist (w (get-buffer-window-list (current-buffer))) - (set-window-point w (point))) - (magit-highlight-section)))))) - -(defun magit-string-has-prefix-p (string prefix) - (eq (compare-strings string nil (length prefix) prefix nil nil) t)) - -(defun magit-revert-buffers (dir &optional ignore-modtime) - (dolist (buffer (buffer-list)) - (when (and buffer - (buffer-file-name buffer) - ;; don't revert indirect buffers, as the parent will be reverted - (not (buffer-base-buffer buffer)) - (magit-string-has-prefix-p (buffer-file-name buffer) dir) - (file-readable-p (buffer-file-name buffer)) - (or ignore-modtime (not (verify-visited-file-modtime buffer))) - (not (buffer-modified-p buffer))) - (with-current-buffer buffer - (condition-case var - (revert-buffer t t nil) - (error (let ((signal-data (cadr var))) - (cond (t (magit-bug-report signal-data)))))))))) - -(defun magit-update-vc-modeline (dir) - "Update the modeline for buffers representable by magit." - (dolist (buffer (buffer-list)) - (when (and buffer - (buffer-file-name buffer) - (magit-string-has-prefix-p (buffer-file-name buffer) dir)) - (with-current-buffer buffer - (condition-case var - (vc-find-file-hook) - (error (let ((signal-data (cadr var))) - (cond (t (magit-bug-report signal-data)))))))))) - -(defvar magit-refresh-needing-buffers nil) -(defvar magit-refresh-pending nil) - -(defun magit-refresh-wrapper (func) - (if magit-refresh-pending - (funcall func) - (let* ((dir default-directory) - (status-buffer (magit-find-status-buffer dir)) - (magit-refresh-needing-buffers nil) - (magit-refresh-pending t)) - (unwind-protect - (funcall func) - (when magit-refresh-needing-buffers - (magit-revert-buffers dir) - (dolist (b (adjoin status-buffer - magit-refresh-needing-buffers)) - (magit-refresh-buffer b))))))) - -(defun magit-need-refresh (&optional buffer) - "Mark BUFFER as needing to be refreshed. If BUFFER is nil, use the -current buffer." - (pushnew (or buffer (current-buffer)) magit-refresh-needing-buffers :test 'eq)) - -(defun magit-refresh () - "Refresh current buffer to match repository state. -Also revert every unmodified buffer visiting files -in the corresponding directory." - (interactive) - (magit-with-refresh - (magit-need-refresh))) - -(defun magit-refresh-all () - "Refresh all magit buffers to match respective repository states. -Also revert every unmodified buffer visiting files -in the corresponding directories." - (interactive) - (magit-for-all-buffers #'magit-refresh-buffer default-directory)) - -;;; Untracked files - -(defun magit-wash-untracked-file () - (if (looking-at "^? \\(.*\\)$") - (let ((file (match-string-no-properties 1))) - (delete-region (point) (+ (line-end-position) 1)) - (magit-with-section file 'file - (magit-set-section-info file) - (insert "\t" file "\n")) - t) - nil)) - -(defun magit-wash-untracked-files () - ;; Setting magit-old-top-section to nil speeds up washing: no time - ;; is wasted looking up the old visibility, which doesn't matter for - ;; untracked files. - ;; - ;; XXX - speed this up in a more general way. - ;; - (let ((magit-old-top-section nil)) - (magit-wash-sequence #'magit-wash-untracked-file))) - -(defun magit-insert-untracked-files () - (unless (string= (magit-get "status" "showUntrackedFiles") "no") - (apply 'magit-git-section - `(untracked - "Untracked files:" - magit-wash-untracked-files - "ls-files" "--others" "-t" "--exclude-standard" - ,@(when magit-omit-untracked-dir-contents - '("--directory")))))) - -;;; Diffs and Hunks - -(defvar magit-diff-context-lines 3) - -(defun magit-diff-U-arg () - (format "-U%d" magit-diff-context-lines)) - -(defun magit-diff-smaller-hunks (&optional count) - "Decrease the context for diff hunks by COUNT." - (interactive "p") - (setq magit-diff-context-lines (max 0 (- magit-diff-context-lines count))) - (magit-refresh)) - -(defun magit-diff-larger-hunks (&optional count) - "Increase the context for diff hunks by COUNT." - (interactive "p") - (setq magit-diff-context-lines (+ magit-diff-context-lines count)) - (magit-refresh)) - -(defun magit-diff-default-hunks () - "Reset context for diff hunks to the default size." - (interactive "") - (setq magit-diff-context-lines 3) - (magit-refresh)) - -(defun magit-toggle-diff-refine-hunk (&optional other) - (interactive "P") - "Turn diff-hunk refining on or off. - -If hunk refining is currently on, then hunk refining is turned off. -If hunk refining is off, then hunk refining is turned on, in -`selected' mode (only the currently selected hunk is refined). - -With a prefix argument, the \"third choice\" is used instead: -If hunk refining is currently on, then refining is kept on, but -the refining mode (`selected' or `all') is switched. -If hunk refining is off, then hunk refining is turned on, in -`all' mode (all hunks refined). - -Customize `magit-diff-refine-hunk' to change the default mode." - (let* ((old magit-diff-refine-hunk) - (new - (if other - (if (eq old 'all) t 'all) - (not old)))) - - ;; remove any old refining in currently highlighted section - (when (and magit-highlighted-section old (not (eq old 'all))) - (magit-unrefine-section magit-highlighted-section)) - - ;; set variable to new value locally - (set (make-local-variable 'magit-diff-refine-hunk) new) - - ;; if now highlighting in "selected only" mode, turn refining back - ;; on in the current section - (when (and magit-highlighted-section new (not (eq new 'all))) - (magit-refine-section magit-highlighted-section)) - - ;; `all' mode being turned on or off needs a complete refresh - (when (or (eq old 'all) (eq new 'all)) - (magit-refresh)))) - -(defun magit-diff-line-file () - (cond ((looking-at "^diff --git ./\\(.*\\) ./\\(.*\\)$") - (match-string-no-properties 2)) - ((looking-at "^diff --cc +\\(.*\\)$") - (match-string-no-properties 1)) - (t - nil))) - -(defun magit-wash-diffs () - (magit-wash-sequence #'magit-wash-diff-or-other-file)) - -(defun magit-wash-diff-or-other-file () - (or (magit-wash-diff) - (magit-wash-other-file))) - -(defun magit-wash-other-file () - (if (looking-at "^? \\(.*\\)$") - (let ((file (match-string-no-properties 1))) - (delete-region (point) (+ (line-end-position) 1)) - (magit-with-section file 'file - (magit-set-section-info file) - (insert "\tNew " file "\n")) - t) - nil)) - -(defvar magit-hide-diffs nil) - -(defvar magit-indentation-level 1) - -(defun magit-insert-diff-title (status file file2) - (let ((status-text (case status - ((unmerged) - (format "Unmerged %s" file)) - ((new) - (format "New %s" file)) - ((deleted) - (format "Deleted %s" file)) - ((renamed) - (format "Renamed %s (from %s)" - file file2)) - ((modified) - (format "Modified %s" file)) - ((typechange) - (format "Typechange %s" file)) - (t - (format "? %s" file))))) - (insert (make-string magit-indentation-level ?\t) status-text "\n"))) - -(defvar magit-current-diff-range nil - "Used internally when setting up magit diff sections.") - -(defun magit-wash-typechange-section (file) - (magit-set-section-info (list 'typechange file)) - (let ((first-start (point-marker)) - (second-start (progn (forward-line 1) - (search-forward-regexp "^diff") - (beginning-of-line) - (point-marker)))) - (let ((magit-indentation-level (+ magit-indentation-level 1))) - (save-restriction - (narrow-to-region first-start second-start) - (goto-char (point-min)) - (magit-with-section file 'diff - (magit-wash-diff-section))) - (save-restriction - (narrow-to-region second-start (point-max)) - (goto-char (point-min)) - (magit-with-section file 'diff - (magit-wash-diff-section)))))) - -(defun magit-wash-diff-section () - (cond ((looking-at "^\\* Unmerged path \\(.*\\)") - (let ((file (match-string-no-properties 1))) - (delete-region (point) (line-end-position)) - (insert "\tUnmerged " file "\n") - (magit-set-section-info (list 'unmerged file nil)) - t)) - ((looking-at "^diff") - (let ((file (magit-diff-line-file)) - (end (save-excursion - (forward-line) ;; skip over "diff" line - (if (search-forward-regexp "^diff\\|^@@" nil t) - (goto-char (match-beginning 0)) - (goto-char (point-max))) - (point-marker)))) - (let* ((status (cond - ((looking-at "^diff --cc") - 'unmerged) - ((save-excursion - (search-forward-regexp "^new file" end t)) - 'new) - ((save-excursion - (search-forward-regexp "^deleted" end t)) - 'deleted) - ((save-excursion - (search-forward-regexp "^rename" end t)) - 'renamed) - (t - 'modified))) - (file2 (cond - ((save-excursion - (search-forward-regexp "^rename from \\(.*\\)" - end t)) - (match-string-no-properties 1))))) - (magit-set-section-info (list status - file - (or file2 file) - magit-current-diff-range)) - (magit-insert-diff-title status file file2) - (when (search-forward-regexp "\\(--- \\(.*\\)\n\\+\\+\\+ \\(.*\\)\n\\)" () t) - (when (match-string 1) - (add-text-properties (match-beginning 1) (match-end 1) - '(face magit-diff-hunk-header)) - (add-text-properties (match-beginning 2) (match-end 2) - '(face magit-diff-file-header)) - (add-text-properties (match-beginning 3) (match-end 3) - '(face magit-diff-file-header)))) - (goto-char end) - (let ((magit-section-hidden-default nil)) - (magit-wash-sequence #'magit-wash-hunk)))) - t) - (t - nil))) - -(defun magit-wash-diff () - (let ((magit-section-hidden-default magit-hide-diffs)) - (magit-with-section (magit-current-line) 'diff - (magit-wash-diff-section)))) - -(defun magit-diff-item-kind (diff) - (car (magit-section-info diff))) - -(defun magit-diff-item-file (diff) - (cadr (magit-section-info diff))) - -(defun magit-diff-item-file2 (diff) - (caddr (magit-section-info diff))) - -(defun magit-diff-item-range (diff) - (nth 3 (magit-section-info diff))) - -(defun magit-wash-hunk () - (cond ((looking-at "\\(^@+\\)[^@]*@+.*") - (let ((n-columns (1- (length (match-string 1)))) - (head (match-string 0)) - (hunk-start-pos (point))) - (magit-with-section head 'hunk - (add-text-properties (match-beginning 0) (match-end 0) - '(face magit-diff-hunk-header)) - (forward-line) - (while (not (or (eobp) - (looking-at "^diff\\|^@@"))) - (magit-highlight-line-whitespace) - (let ((prefix (buffer-substring-no-properties - (point) (min (+ (point) n-columns) (point-max))))) - (cond ((string-match "\\+" prefix) - (magit-put-line-property 'face 'magit-diff-add)) - ((string-match "-" prefix) - (magit-put-line-property 'face 'magit-diff-del)) - (t - (magit-put-line-property 'face 'magit-diff-none)))) - (forward-line))) - - (when (eq magit-diff-refine-hunk 'all) - (save-excursion - (goto-char hunk-start-pos) - (diff-refine-hunk)))) - t) - (t - nil))) - -(defvar magit-diff-options nil) - -(defun magit-insert-diff (file status) - (let ((cmd magit-git-executable) - (args (append (list "diff") - (list (magit-diff-U-arg)) - magit-diff-options - (list "--" file)))) - (let ((p (point))) - (magit-git-insert args) - (if (not (eq (char-before) ?\n)) - (insert "\n")) - (save-restriction - (narrow-to-region p (point)) - (goto-char p) - (cond - ((eq status 'typechange) - (magit-insert-diff-title status file file) - (magit-wash-typechange-section file)) - (t - (magit-wash-diff-section))) - (goto-char (point-max)))))) - -(defvar magit-last-raw-diff nil) -(defvar magit-ignore-unmerged-raw-diffs nil) - -(defun magit-wash-raw-diffs () - (let ((magit-last-raw-diff nil)) - (magit-wash-sequence #'magit-wash-raw-diff))) - -(defun magit-wash-raw-diff () - (if (looking-at - ":\\([0-7]+\\) \\([0-7]+\\) [0-9a-f]+ [0-9a-f]+ \\(.\\)[0-9]*\t\\([^\t\n]+\\)$") - (let ((old-perm (match-string-no-properties 1)) - (new-perm (match-string-no-properties 2)) - (status (case (string-to-char (match-string-no-properties 3)) - (?A 'new) - (?D 'deleted) - (?M 'modified) - (?U 'unmerged) - (?T 'typechange) - (t nil))) - (file (match-string-no-properties 4))) - ;; If this is for the same file as the last diff, ignore it. - ;; Unmerged files seem to get two entries. - ;; We also ignore unmerged files when told so. - (if (or (equal file magit-last-raw-diff) - (and magit-ignore-unmerged-raw-diffs (eq status 'unmerged))) - (delete-region (point) (+ (line-end-position) 1)) - (setq magit-last-raw-diff file) - ;; The 'diff' section that is created here will not work with - ;; magit-insert-diff-item-patch etc when we leave it empty. - ;; Luckily, raw diffs are only produced for staged and - ;; unstaged changes, and we never call - ;; magit-insert-diff-item-patch on them. This is a bit - ;; brittle, of course. - (let ((magit-section-hidden-default magit-hide-diffs)) - (magit-with-section file 'diff - (delete-region (point) (+ (line-end-position) 1)) - (if (not (magit-section-hidden magit-top-section)) - (magit-insert-diff file status) - (magit-set-section-info (list status file nil)) - (magit-set-section-needs-refresh-on-show t) - (magit-insert-diff-title status file nil))))) - t) - nil)) - -(defun magit-hunk-item-diff (hunk) - (let ((diff (magit-section-parent hunk))) - (or (eq (magit-section-type diff) 'diff) - (error "Huh? Parent of hunk not a diff")) - diff)) - -(defun magit-diff-item-insert-header (diff buf) - (let ((beg (save-excursion - (goto-char (magit-section-beginning diff)) - (forward-line) - (point))) - (end (if (magit-section-children diff) - (magit-section-beginning (car (magit-section-children diff))) - (magit-section-end diff)))) - (magit-insert-region beg end buf))) - -(defun magit-insert-diff-item-patch (diff buf) - (let ((beg (save-excursion - (goto-char (magit-section-beginning diff)) - (forward-line) - (point))) - (end (magit-section-end diff))) - (magit-insert-region beg end buf))) - -(defun magit-insert-hunk-item-patch (hunk buf) - (magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf) - (magit-insert-region (magit-section-beginning hunk) (magit-section-end hunk) - buf)) - -(defun magit-insert-hunk-item-region-patch (hunk reverse beg end buf) - (magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf) - (save-excursion - (goto-char (magit-section-beginning hunk)) - (magit-insert-current-line buf) - (forward-line) - (let ((copy-op (if reverse "+" "-"))) - (while (< (point) (magit-section-end hunk)) - (if (and (<= beg (point)) (< (point) end)) - (magit-insert-current-line buf) - (cond ((looking-at " ") - (magit-insert-current-line buf)) - ((looking-at copy-op) - (let ((text (buffer-substring-no-properties - (+ (point) 1) (line-beginning-position 2)))) - (with-current-buffer buf - (insert " " text)))))) - (forward-line)))) - (with-current-buffer buf - (diff-fixup-modifs (point-min) (point-max)))) - -(defun magit-hunk-item-is-conflict-p (hunk) - ;;; XXX - Using the title is a bit too clever... - (string-match "^diff --cc" - (magit-section-title (magit-hunk-item-diff hunk)))) - -(defun magit-hunk-item-target-line (hunk) - (save-excursion - (beginning-of-line) - (let ((line (line-number-at-pos))) - (goto-char (magit-section-beginning hunk)) - (if (not (looking-at "@@+ .* \\+\\([0-9]+\\)\\(,[0-9]+\\)? @@+")) - (error "Hunk header not found")) - (let ((target (string-to-number (match-string 1)))) - (forward-line) - (while (< (line-number-at-pos) line) - ;; XXX - deal with combined diffs - (if (not (looking-at "-")) - (setq target (+ target 1))) - (forward-line)) - target)))) - -(defun magit-show (commit filename &optional select prefix) - "Returns a buffer containing the contents of the file FILENAME, as stored in -COMMIT. COMMIT may be one of the following: - -- A string with the name of a commit, such as \"head\" or \"dae86e\". See 'git - help revisions' for syntax. -- The symbol 'index, indicating that you want the version in Git's index or - staging area. -- The symbol 'working, indicating that you want the version in the working - directory. In this case you'll get a buffer visiting the file. If there's - already a buffer visiting that file, you'll get that one. - -When called interactively or when SELECT is non-nil, make the buffer active, -either in another window or (with a prefix argument) in the current window." - (interactive (let* ((revision (magit-read-rev "Retrieve file from revision")) - (filename (magit-read-file-from-rev revision))) - (list revision filename t current-prefix-arg))) - (if (eq commit 'working) - (find-file-noselect filename) - (let ((buffer (create-file-buffer (format "%s.%s" filename (replace-regexp-in-string ".*/" "" (prin1-to-string commit t)))))) - (cond - ((eq commit 'index) - (let ((checkout-string (magit-git-string "checkout-index" - "--temp" - filename))) - (string-match "^\\(.*\\)\t" checkout-string) - (with-current-buffer buffer - (let ((tmpname (match-string 1 checkout-string))) - (magit-with-silent-modifications - (insert-file-contents tmpname nil nil nil t)) - (delete-file tmpname))))) - (t - (with-current-buffer buffer - (magit-with-silent-modifications - (magit-git-insert (list "cat-file" "-p" - (concat commit ":" filename))))))) - (with-current-buffer buffer - (let ((buffer-file-name filename)) - (normal-mode)) - (goto-char (point-min))) - (if select - (if prefix - (switch-to-buffer buffer) - (switch-to-buffer-other-window buffer)) - buffer)))) - -(defmacro with-magit-tmp-buffer (var &rest body) - (declare (indent 1) - (debug (symbolp &rest form))) - `(let ((,var (generate-new-buffer magit-tmp-buffer-name))) - (unwind-protect - (progn ,@body) - (kill-buffer ,var)))) - -(defun magit-apply-diff-item (diff &rest args) - (when (zerop magit-diff-context-lines) - (setq args (cons "--unidiff-zero" args))) - (with-magit-tmp-buffer tmp - (magit-insert-diff-item-patch diff tmp) - (apply #'magit-run-git-with-input tmp - "apply" (append args (list "-"))))) - -(defun magit-apply-hunk-item* (hunk reverse &rest args) - "Apply single hunk or part of a hunk to the index or working file. - -This function is the core of magit's stage, unstage, apply, and -revert operations. HUNK (or the portion of it selected by the -region) will be applied to either the index, if \"--cached\" is a -member of ARGS, or to the working file otherwise." - (let ((zero-context (zerop magit-diff-context-lines)) - (use-region (magit-use-region-p))) - (when zero-context - (setq args (cons "--unidiff-zero" args))) - (when reverse - (setq args (cons "--reverse" args))) - (when (and use-region zero-context) - (error (concat "Not enough context to partially apply hunk. " - "Use `+' to increase context."))) - (with-magit-tmp-buffer tmp - (if use-region - (magit-insert-hunk-item-region-patch - hunk reverse (region-beginning) (region-end) tmp) - (magit-insert-hunk-item-patch hunk tmp)) - (apply #'magit-run-git-with-input tmp - "apply" (append args (list "-")))))) - -(defun magit-apply-hunk-item (hunk &rest args) - (apply #'magit-apply-hunk-item* hunk nil args)) - -(defun magit-apply-hunk-item-reverse (hunk &rest args) - (apply #'magit-apply-hunk-item* hunk t args)) - -(magit-define-inserter unstaged-changes (title) - (let ((magit-hide-diffs t) - (magit-current-diff-range (cons 'index 'working))) - (let ((magit-diff-options (append '() magit-diff-options))) - (magit-git-section 'unstaged title 'magit-wash-raw-diffs - "diff-files")))) - -(magit-define-inserter staged-changes (staged no-commit) - (let ((magit-current-diff-range (cons "HEAD" 'index))) - (when staged - (let ((magit-hide-diffs t) - (base (if no-commit - (magit-git-string "mktree") - "HEAD"))) - (let ((magit-diff-options (append '("--cached") magit-diff-options)) - (magit-ignore-unmerged-raw-diffs t)) - (magit-git-section 'staged "Staged changes:" 'magit-wash-raw-diffs - "diff-index" "--cached" - base)))))) - -;;; Logs and Commits - - ; Note: making this a plain defcustom would probably let users break - ; the parser too easily -(defvar magit-git-log-options - (list - "--pretty=format:* %h %s" - (format "--abbrev=%s" magit-sha1-abbrev-length))) - ; --decorate=full otherwise some ref prefixes are stripped - ; '("--pretty=format:* %H%d %s" "--decorate=full")) - -;; -;; Regexps for parsing ref names -;; -;; see the `git-check-ref-format' manpage for details - -(defconst magit-ref-nonchars "\000-\037\177 ~^:?*[\\" - "Characters specifically disallowed from appearing in Git symbolic refs. - -Evaluate (man \"git-check-ref-format\") for details") - -(defconst magit-ref-nonslash-re - (concat "\\(?:" - ;; "no slash-separated component can begin with a dot ." (rule 1) - "[^" magit-ref-nonchars "./]" - ;; "cannot have two consecutive dots .. anywhere." (rule 3) - "\\.?" - "\\)*") - "Regexp that matches the non-slash parts of a ref name. - -Evaluate (man \"git-check-ref-format\") for details") - -(defconst magit-refname-re - (concat - "\\(?:HEAD\\|" - - "\\(?:tag: \\)?" - - ;; optional non-slash sequence at the beginning - magit-ref-nonslash-re - - ;; any number of slash-prefixed sequences - "\\(?:" - "/" - magit-ref-nonslash-re - "\\)*" - - "/" ;; "must contain at least one /." (rule 2) - magit-ref-nonslash-re - - ;; "cannot end with a slash / nor a dot .." (rule 5) - "[^" magit-ref-nonchars "./]" - - "\\)" - ) - "Regexp that matches a git symbolic reference name. - -Evaluate (man \"git-check-ref-format\") for details") - -(defconst magit-log-oneline-re - (concat - "^\\([_\\*|/ -.]+\\)?" ; graph (1) - "\\(?:" - "\\([0-9a-fA-F]+\\)" ; sha1 (2) - "\\(?:" ; refs (3) - " " - "\\(" - "(" - magit-refname-re "\\(?:, " magit-refname-re "\\)*" - ")" - "\\)" - "\\)?" - "\\)?" - " ?\\(.*\\)$" ; msg (4) - )) - -(defconst magit-log-longline-re - (concat - ;; use \0 delimiter (from -z option) to identify commits. this prevents - ;; commit messages containing lines like "commit 00000" from polluting the - ;; display - "\\(?:\\(?:\\`\\|\0\\)" - "\\([_\\*|/ -.]+\\)?" ; graph (1) - "commit " - "\\([0-9a-fA-F]+\\)" ; sha1 (2) - "\\(?:" ; refs (3) - " " - "\\(" - "(" - magit-refname-re "\\(?:, " magit-refname-re "\\)*" - ")" - "\\)" - "\\)?" - "$\\)?" - " ?\\(.*\\)$" ; msg (4) - )) - -(defvar magit-present-log-line-function 'magit-present-log-line - "The function to use when generating a log line. -It takes four args: CHART, SHA1, REFS and MESSAGE. The function -must return a string which will represent the log line.") - -(defun magit-log-get-bisect-state-color (suffix) - (if (string= suffix "bad") - (list suffix 'magit-log-head-label-bisect-bad) - (list suffix 'magit-log-head-label-bisect-good))) - -(defun magit-log-get-patches-color (suffix) - (list (and (string-match ".+/\\(.+\\)" suffix) - (match-string 1 suffix)) - 'magit-log-head-label-patches)) - -(defvar magit-log-remotes-color-hook nil) - -(defun magit-log-get-remotes-color (suffix) - (or - (run-hook-with-args-until-success - 'magit-log-remotes-color-hook suffix) - (list suffix 'magit-log-head-label-remote))) - -(defvar magit-refs-namespaces - '(("tags" . magit-log-head-label-tags) - ("remotes" magit-log-get-remotes-color) - ("heads" . magit-log-head-label-local) - ("patches" magit-log-get-patches-color) - ("bisect" magit-log-get-bisect-state-color))) - -(defun magit-ref-get-label-color (r) - (let ((uninteresting (loop for re in magit-uninteresting-refs - thereis (string-match re r)))) - (if uninteresting (list nil nil) - (let* ((ref-re "\\(?:tag: \\)?refs/\\(?:\\([^/]+\\)/\\)?\\(.+\\)") - (label (and (string-match ref-re r) - (match-string 2 r))) - (res (let ((colorizer - (cdr (assoc (match-string 1 r) - magit-refs-namespaces)))) - (cond ((null colorizer) - (list r 'magit-log-head-label-default)) - ((symbolp colorizer) - (list label colorizer)) - ((listp colorizer) - (funcall (car colorizer) - (match-string 2 r))) - (t - (list r 'magit-log-head-label-default)))))) - res)))) - -(defun magit-present-log-line (graph sha1 refs message) - "The default log line generator." - (let ((string-refs - (when refs - (let ((colored-labels - (delete nil - (mapcar (lambda (r) - (destructuring-bind (label face) - (magit-ref-get-label-color r) - (and label - (propertize label 'face face)))) - refs)))) - (concat - (mapconcat 'identity colored-labels " ") - " "))))) - - (concat - (if sha1 - (propertize sha1 'face 'magit-log-sha1) - (insert-char ? magit-sha1-abbrev-length)) - " " - (when graph - (propertize graph 'face 'magit-log-graph)) - string-refs - (when message - (propertize message 'face 'magit-log-message))))) - -(defvar magit-log-count () - "Internal var used to count the number of logs actually added in a buffer.") - -(defmacro magit-create-log-buffer-sections (&rest body) - "Empty current buffer of text and magit's section, and then evaluate BODY. - -if the number of logs inserted in the buffer is `magit-log-cutoff-length' -insert a line to tell how to insert more of them" - (declare (indent 0)) - `(let ((magit-log-count 0) (inhibit-read-only t)) - (magit-create-buffer-sections - (magit-with-section 'log nil - ,@body - (if (= magit-log-count magit-log-cutoff-length) - (magit-with-section "longer" 'longer - (insert "type \"e\" to show more logs\n"))))))) - -(defun magit-wash-log-line (style) - (beginning-of-line) - (let ((line-re (cond ((eq style 'long) magit-log-longline-re) - (t magit-log-oneline-re)))) - (cond - ((looking-at line-re) - (let ((chart (match-string 1)) - (sha1 (match-string 2)) - (msg (match-string 4)) - (refs (when (match-string 3) - (delq nil - (mapcar - (lambda (s) - (and (not - (or (string= s "tag:") - (string= s "HEAD"))) ; as of 1.6.6 - s)) - (split-string (match-string 3) "[(), ]" t)))))) - (delete-region (point-at-bol) (point-at-eol)) - (insert (funcall magit-present-log-line-function chart sha1 refs msg)) - (goto-char (point-at-bol)) - (if sha1 - (magit-with-section sha1 'commit - (when magit-log-count (setq magit-log-count (1+ magit-log-count))) - (magit-set-section-info sha1) - (forward-line)) - (forward-line)))) - (t - (forward-line))) - t)) - -(defun magit-wash-log (&optional style) - (let ((magit-old-top-section nil)) - (magit-wash-sequence (apply-partially 'magit-wash-log-line style)))) - -(defvar magit-currently-shown-commit nil) - -(defun magit-wash-commit () - (let ((magit-current-diff-range)) - (when (looking-at "^commit \\([0-9a-fA-F]\\{40\\}\\)") - (setq magit-current-diff-range (match-string 1)) - (add-text-properties (match-beginning 1) (match-end 1) - '(face magit-log-sha1))) - (cond - ((search-forward-regexp "^Merge: \\([0-9a-fA-F]+\\) \\([0-9a-fA-F]+\\)$" nil t) - (setq magit-current-diff-range (cons (cons (match-string 1) - (match-string 2)) - magit-current-diff-range)) - (let ((first (magit-set-section nil 'commit (match-beginning 1) (match-end 1))) - (second (magit-set-section nil 'commit (match-beginning 2) (match-end 2)))) - (magit-set-section-info (match-string 1) first) - (magit-set-section-info (match-string 2) second)) - (make-commit-button (match-beginning 1) (match-end 1)) - (make-commit-button (match-beginning 2) (match-end 2))) - (t - (setq magit-current-diff-range (cons (concat magit-current-diff-range "^") - magit-current-diff-range)))) - (search-forward-regexp "^$") - (while (and - (search-forward-regexp "\\(\\b[0-9a-fA-F]\\{4,40\\}\\b\\)\\|\\(^diff\\)" nil 'noerror) - (not (match-string 2))) - (let ((sha1 (match-string 1)) - (start (match-beginning 1)) - (end (match-end 1))) - (when (string-equal "commit" (magit-git-string "cat-file" "-t" sha1)) - (make-commit-button start end) - (let ((section (magit-set-section sha1 'commit start end))) - (magit-set-section-info sha1 section))))) - (beginning-of-line) - (when (looking-at "^diff") - (magit-wash-diffs)) - (goto-char (point-max)) - (insert "\n") - (if magit-back-navigation-history - (magit-with-section "[back]" 'button - (insert-text-button "[back]" - 'help-echo "Previous commit" - 'action 'magit-show-commit-backward - 'follow-link t - 'mouse-face 'magit-item-highlight))) - (insert " ") - (if magit-forward-navigation-history - (magit-with-section "[forward]" 'button - (insert-text-button "[forward]" - 'help-echo "Next commit" - 'action 'magit-show-commit-forward - 'follow-link t - 'mouse-face 'magit-item-highlight))))) - -(defun make-commit-button (start end) - (make-text-button start end - 'help-echo "Visit commit" - 'action (lambda (button) - (save-excursion - (goto-char button) - (magit-visit-item))) - 'follow-link t - 'mouse-face 'magit-item-highlight - 'face 'magit-log-sha1)) - -(defun magit-refresh-commit-buffer (commit) - (magit-configure-have-abbrev) - (magit-configure-have-decorate) - (magit-create-buffer-sections - (apply #'magit-git-section nil nil - 'magit-wash-commit - "log" - "--max-count=1" - "--pretty=medium" - `(,@(if magit-have-abbrev (list "--no-abbrev-commit")) - ,@(if magit-have-decorate (list "--decorate=full")) - "--cc" - "-p" ,commit)))) - -(define-derived-mode magit-commit-mode magit-mode "Magit" - "Mode to view a git commit. - -\\{magit-commit-mode-map}" - :group 'magit) - -(defvar magit-commit-buffer-name "*magit-commit*" - "Buffer name for displaying commit log messages.") - -(defun magit-show-commit (commit &optional scroll inhibit-history select) - "Show information about a commit in the buffer named by -`magit-commit-buffer-name'. COMMIT can be any valid name for a commit -in the current Git repository. - -When called interactively or when SELECT is non-nil, switch to -the commit buffer using `pop-to-buffer'. - -Unless INHIBIT-HISTORY is non-nil, the commit currently shown -will be pushed onto `magit-back-navigation-history' and -`magit-forward-navigation-history' will be cleared. - -Noninteractively, if the commit is already displayed and SCROLL -is provided, call SCROLL's function definition in the commit -window. (`scroll-up' and `scroll-down' are typically passed in -for this argument.)" - (interactive (list (magit-read-rev "Show commit (hash or ref)") - nil nil t)) - (when (magit-section-p commit) - (setq commit (magit-section-info commit))) - (unless (eql 0 (magit-git-exit-code "cat-file" "commit" commit)) - (error "%s is not a commit" commit)) - (let ((dir default-directory) - (buf (get-buffer-create magit-commit-buffer-name))) - (cond - ((and (equal magit-currently-shown-commit commit) - ;; if it's empty then the buffer was killed - (with-current-buffer buf - (> (length (buffer-string)) 1))) - (let ((win (get-buffer-window buf))) - (cond ((not win) - (display-buffer buf)) - (scroll - (with-selected-window win - (funcall scroll)))))) - (commit - (display-buffer buf) - (with-current-buffer buf - (unless inhibit-history - (push (cons default-directory magit-currently-shown-commit) - magit-back-navigation-history) - (setq magit-forward-navigation-history nil)) - (setq magit-currently-shown-commit commit) - (goto-char (point-min)) - (magit-mode-init dir 'magit-commit-mode - #'magit-refresh-commit-buffer commit)))) - (if select - (pop-to-buffer buf)))) - -(defun magit-show-commit-backward (&optional ignored) - ;; Ignore argument passed by push-button - "Show the commit at the head of `magit-back-navigation-history in -`magit-commit-buffer-name`." - (interactive) - (with-current-buffer magit-commit-buffer-name - (unless magit-back-navigation-history - (error "No previous commit.")) - (let ((histitem (pop magit-back-navigation-history))) - (push (cons default-directory magit-currently-shown-commit) - magit-forward-navigation-history) - (setq default-directory (car histitem)) - (magit-show-commit (cdr histitem) nil 'inhibit-history)))) - -(defun magit-show-commit-forward (&optional ignored) - ;; Ignore argument passed by push-button - "Show the commit at the head of `magit-forward-navigation-history in -`magit-commit-buffer-name`." - (interactive) - (with-current-buffer magit-commit-buffer-name - (unless magit-forward-navigation-history - (error "No next commit.")) - (let ((histitem (pop magit-forward-navigation-history))) - (push (cons default-directory magit-currently-shown-commit) - magit-back-navigation-history) - (setq default-directory (car histitem)) - (magit-show-commit (cdr histitem) nil 'inhibit-history)))) - -(defvar magit-marked-commit nil) - -(defvar magit-mark-overlay nil) -(make-variable-buffer-local 'magit-mark-overlay) -(put 'magit-mark-overlay 'permanent-local t) - -(defun magit-refresh-marked-commits () - (magit-for-all-buffers #'magit-refresh-marked-commits-in-buffer)) - -(defun magit-refresh-marked-commits-in-buffer () - (if (not magit-mark-overlay) - (let ((ov (make-overlay 1 1))) - (overlay-put ov 'face 'magit-item-mark) - (setq magit-mark-overlay ov))) - (delete-overlay magit-mark-overlay) - (magit-for-all-sections - (lambda (section) - (when (and (eq (magit-section-type section) 'commit) - (equal (magit-section-info section) - magit-marked-commit)) - (move-overlay magit-mark-overlay - (magit-section-beginning section) - (magit-section-end section) - (current-buffer)))))) - -(defun magit-set-marked-commit (commit) - (setq magit-marked-commit commit) - (magit-refresh-marked-commits)) - -(defun magit-marked-commit () - (or magit-marked-commit - (error "No commit marked"))) - -(defun magit-remote-branch-name (remote branch) - "Get the name of the branch BRANCH on remote REMOTE" - (if (string= remote ".") - branch - (concat remote "/" branch))) - -(magit-define-inserter unpulled-commits (remote branch) - (when remote - (apply #'magit-git-section - 'unpulled "Unpulled commits:" 'magit-wash-log "log" - (append magit-git-log-options - (list - (format "HEAD..%s" (magit-remote-branch-name remote branch))))))) - -(magit-define-inserter unpushed-commits (remote branch) - (when remote - (apply #'magit-git-section - 'unpushed "Unpushed commits:" 'magit-wash-log "log" - (append magit-git-log-options - (list - (format "%s..HEAD" (magit-remote-branch-name remote branch))))))) - -(defun magit-remote-branch-for (local-branch &optional fully-qualified-name) - "Guess the remote branch name that LOCAL-BRANCH is tracking. -Gives a fully qualified name (e.g., refs/remotes/origin/master) if -FULLY-QUALIFIED-NAME is non-nil." - (let ((merge (magit-get "branch" local-branch "merge"))) - (save-match-data - (if (and merge (string-match "^refs/heads/\\(.+\\)" merge)) - (concat (if fully-qualified-name - (let ((remote-name (magit-get "branch" local-branch "remote"))) - (if (string= "." remote-name) - "refs/heads/" - (concat "refs/remotes/" remote-name "/")))) - (match-string 1 merge)))))) - -;;; Status - -(defvar magit-remote-string-hook nil) - -(defun magit-remote-string (remote remote-branch remote-rebase) - (cond - ((string= "." remote) - (concat - (when remote-rebase "onto ") - "branch " - (propertize remote-branch 'face 'magit-branch))) - (remote - (concat - (when remote-rebase "onto ") - (propertize remote-branch 'face 'magit-branch) - " @ " - remote - " (" - (magit-get "remote" remote "url") - ")")) - (t - (run-hook-with-args-until-success 'magit-remote-string-hook)))) - -(declare-function magit--bisect-info-for-status "magit-bisect" (branch)) - -(defun magit-refresh-status () - (magit-create-buffer-sections - (magit-with-section 'status nil - (let* ((branch (magit-get-current-branch)) - (remote (and branch (magit-get "branch" branch "remote"))) - (remote-rebase (and branch (magit-get-boolean "branch" branch "rebase"))) - (remote-branch (or (and branch (magit-remote-branch-for branch)) branch)) - (remote-string (magit-remote-string remote remote-branch remote-rebase)) - (head (magit-git-string - "log" - "--max-count=1" - "--abbrev-commit" - (format "--abbrev=%s" magit-sha1-abbrev-length) - "--pretty=oneline")) - (no-commit (not head))) - (when remote-string - (insert "Remote: " remote-string "\n")) - (insert (format "Local: %s %s\n" - (propertize (magit--bisect-info-for-status branch) - 'face 'magit-branch) - (abbreviate-file-name default-directory))) - (insert (format "Head: %s\n" - (if no-commit "nothing commited (yet)" head))) - (let ((merge-heads (magit-file-lines (concat (magit-git-dir) - "MERGE_HEAD")))) - (if merge-heads - (insert (format "Merging: %s\n" - (mapconcat 'identity - (mapcar 'magit-name-rev merge-heads) - ", "))))) - (let ((rebase (magit-rebase-info))) - (if rebase - (insert (apply 'format "Rebasing: onto %s (%s of %s); Press \"R\" to Abort, Skip, or Continue\n" rebase)))) - (insert "\n") - (magit-git-exit-code "update-index" "--refresh") - (magit-insert-stashes) - (magit-insert-untracked-files) - (magit-insert-pending-changes) - (magit-insert-pending-commits) - (magit-insert-unpulled-commits remote remote-branch) - (let ((staged (or no-commit (magit-anything-staged-p)))) - (magit-insert-unstaged-changes - (if staged "Unstaged changes:" "Changes:")) - (magit-insert-staged-changes staged no-commit)) - (magit-insert-unpushed-commits remote remote-branch) - (run-hooks 'magit-refresh-status-hook))))) - -(defun magit-init (dir) - "Initialize git repository in the DIR directory." - (interactive (list (read-directory-name "Directory for Git repository: "))) - (let* ((dir (file-name-as-directory (expand-file-name dir))) - (topdir (magit-get-top-dir dir))) - (when (or (not topdir) - (yes-or-no-p - (format - (if (string-equal topdir dir) - "There is already a Git repository in %s. Reinitialize? " - "There is a Git repository in %s. Create another in %s? ") - topdir dir))) - (unless (file-directory-p dir) - (and (y-or-n-p (format "Directory %s does not exists. Create it? " dir)) - (make-directory dir))) - (let ((default-directory dir)) - (magit-run* (list magit-git-executable "init")))))) - -(define-derived-mode magit-status-mode magit-mode "Magit" - "Mode for looking at git status. - -\\{magit-status-mode-map}" - :group 'magit) - -(defvar magit-default-directory nil) - -(defun magit-save-some-buffers (&optional msg pred) - "Save some buffers if variable `magit-save-some-buffers' is non-nil. -If variable `magit-save-some-buffers' is set to 'dontask then -don't ask the user before saving the buffers, just go ahead and -do it. - -Optional argument MSG is displayed in the minibuffer if variable -`magit-save-some-buffers' is nil. - -Optional second argument PRED determines which buffers are considered: -If PRED is nil, all the file-visiting buffers are considered. -If PRED is t, then certain non-file buffers will also be considered. -If PRED is a zero-argument function, it indicates for each buffer whether -to consider it or not when called with that buffer current." - (interactive) - (let ((predicate-function (or pred magit-save-some-buffers-predicate)) - (magit-default-directory default-directory)) - (if magit-save-some-buffers - (save-some-buffers - (eq magit-save-some-buffers 'dontask) - predicate-function) - (when msg - (message msg))))) - -(defun magit-save-buffers-predicate-all () - "Prompt to save all buffers with unsaved changes" - t) - -(defun magit-save-buffers-predicate-tree-only () - "Only prompt to save buffers which are within the current git project (as - determined by the dir passed to `magit-status'." - (and buffer-file-name - (string= (magit-get-top-dir magit-default-directory) - (magit-get-top-dir (file-name-directory buffer-file-name))))) - -;;;###autoload -(defun magit-status (dir) - "Open a Magit status buffer for the Git repository containing -DIR. If DIR is not within a Git repository, offer to create a -Git repository in DIR. - -Interactively, a prefix argument means to ask the user which Git -repository to use even if `default-directory' is under Git control. -Two prefix arguments means to ignore `magit-repo-dirs' when asking for -user input." - (interactive (list (if current-prefix-arg - (magit-read-top-dir - (> (prefix-numeric-value current-prefix-arg) - 4)) - (or (magit-get-top-dir default-directory) - (magit-read-top-dir nil))))) - (magit-save-some-buffers) - (let ((topdir (magit-get-top-dir dir))) - (unless topdir - (when (y-or-n-p (format "There is no Git repository in %S. Create one? " - dir)) - (magit-init dir) - (setq topdir (magit-get-top-dir dir)))) - (when topdir - (let ((buf (or (magit-find-status-buffer topdir) - (generate-new-buffer - (concat "*magit: " - (file-name-nondirectory - (directory-file-name topdir)) "*"))))) - (funcall magit-status-buffer-switch-function buf) - (magit-mode-init topdir 'magit-status-mode #'magit-refresh-status))))) - -(magit-define-command automatic-merge (revision) - "Merge REVISION into the current 'HEAD'; commit unless merge fails. -\('git merge REVISION')." - (interactive (list (magit-read-rev "Merge" (magit-guess-branch)))) - (if revision - (magit-run-git "merge" (magit-rev-to-git revision)))) - -(magit-define-command manual-merge (revision) - "Merge REVISION into the current 'HEAD'; commit unless merge fails. -\('git merge REVISION')." - (interactive (list (magit-read-rev "Merge" (magit-guess-branch)))) - (when revision - (apply 'magit-run-git - "merge" "--no-commit" - (magit-rev-to-git revision) - magit-custom-options) - (when (file-exists-p ".git/MERGE_MSG") - (magit-log-edit)))) - -;;; Staging and Unstaging - -(defun magit-stage-item (&optional ask) - "Add the item at point to the staging area. -If ASK is set, ask for the file name rather than picking the one -at point." - (interactive "P") - (if ask - (magit-run-git "add" (read-file-name "File to stage: ")) - (magit-section-action (item info "stage") - ((untracked file) - (magit-run-git "add" info)) - ((untracked) - (apply #'magit-run-git "add" "--" - (magit-git-lines "ls-files" "--other" "--exclude-standard"))) - ((unstaged diff hunk) - (if (magit-hunk-item-is-conflict-p item) - (error (concat "Can't stage individual resolution hunks. " - "Please stage the whole file."))) - (magit-apply-hunk-item item "--cached")) - ((unstaged diff) - (magit-run-git "add" "-u" (magit-diff-item-file item))) - ((staged *) - (error "Already staged")) - ((diff diff) - (save-excursion - (magit-goto-parent-section) - (magit-stage-item))) - ((diff diff hunk) - (save-excursion - (magit-goto-parent-section) - (magit-goto-parent-section) - (magit-stage-item))) - ((hunk) - (error "Can't stage this hunk")) - ((diff) - (error "Can't stage this diff"))))) - -(defun magit-unstage-item () - "Remove the item at point from the staging area." - (interactive) - (magit-section-action (item info "unstage") - ((staged diff hunk) - (magit-apply-hunk-item-reverse item "--cached")) - ((staged diff) - (if (eq (car info) 'unmerged) - (error "Can't unstage an unmerged file. Resolve it first")) - (if (magit-no-commit-p) - (magit-run-git "rm" "--cached" "--" (magit-diff-item-file item)) - (magit-run-git "reset" "-q" "HEAD" "--" (magit-diff-item-file item)))) - ((unstaged *) - (error "Already unstaged")) - ((diff diff) - (save-excursion - (magit-goto-parent-section) - (magit-unstage-item))) - ((diff diff hunk) - (save-excursion - (magit-goto-parent-section) - (magit-goto-parent-section) - (magit-unstage-item))) - ((hunk) - (error "Can't unstage this hunk")) - ((diff) - (error "Can't unstage this diff")))) - -(defun magit-stage-all (&optional also-untracked-p) - "Add all remaining changes in tracked files to staging area. -With prefix argument, add remaining untracked files as well. -\('git add -u .' or 'git add .', respectively)." - (interactive "P") - (if also-untracked-p - (magit-run-git "add" ".") - (magit-run-git "add" "-u" "."))) - -(defun magit-unstage-all () - "Remove all changes from staging area. -\('git reset --mixed HEAD')." - (interactive) - (magit-run-git "reset" "HEAD")) - -;;; Branches - -(defun escape-branch-name (branch) - "Escapes branch names to remove problematic characters." - (replace-regexp-in-string "[/]" "-" branch)) - -(defun magit-default-tracking-name-remote-plus-branch - (remote branch) - "Use the remote name plus a hyphen plus the escaped branch name for tracking branches." - (concat remote "-" (escape-branch-name branch))) - -(defun magit-default-tracking-name-branch-only - (remote branch) - "Use just the escaped branch name for tracking branches." - (escape-branch-name branch)) - -(defun magit-get-tracking-name (remote branch) - "Given a REMOTE and a BRANCH name, ask the user for a local -tracking brach name suggesting a sensible default." - (when (yes-or-no-p - (format "Create local tracking branch for %s? " branch)) - (let* ((default-name - (funcall magit-default-tracking-name-function remote branch)) - (chosen-name (read-string (format "Call local branch (%s): " default-name) - nil - nil - default-name))) - (when (magit-ref-exists-p (concat "refs/heads/" chosen-name)) - (error "'%s' already exists." chosen-name)) - chosen-name))) - -(defun magit-maybe-create-local-tracking-branch (rev) - "Depending on the users wishes, create a tracking branch for -rev... maybe." - (if (string-match "^\\(?:refs/\\)?remotes/\\([^/]+\\)/\\(.+\\)" rev) - (let* ((remote (match-string 1 rev)) - (branch (match-string 2 rev)) - (tracker-name (magit-get-tracking-name remote branch))) - (when tracker-name - (magit-run-git "checkout" "-b" tracker-name rev) - t)) - nil)) - -(magit-define-command checkout (revision) - "Switch 'HEAD' to REVISION and update working tree. -Fails if working tree or staging area contain uncommitted changes. -If REVISION is a remote branch, offer to create a local tracking branch. -\('git checkout [-b] REVISION')." - (interactive - (list (let ((current-branch (magit-get-current-branch)) - (default (magit-default-rev))) - (magit-read-rev "Switch to" - (unless (string= current-branch default) - default) - (if current-branch - (cons (concat "refs/heads/" current-branch "$") - magit-uninteresting-refs) - magit-uninteresting-refs))))) - (if revision - (when (not (magit-maybe-create-local-tracking-branch revision)) - (magit-save-some-buffers) - (magit-run-git "checkout" (magit-rev-to-git revision)) - (magit-update-vc-modeline default-directory)))) - -(defun magit-read-create-branch-args () - (let* ((cur-branch (magit-get-current-branch)) - (cur-point (magit-default-rev)) - (branch (read-string "Create branch: ")) - (parent (magit-read-rev "Parent" - (cond - ((eq magit-create-branch-behaviour 'at-point) cur-point) - ((eq magit-create-branch-behaviour 'at-head) cur-branch) - (t cur-branch))))) - (list branch parent))) - -(magit-define-command create-branch (branch parent) - "Switch 'HEAD' to new BRANCH at revision PARENT and update working tree. -Fails if working tree or staging area contain uncommitted changes. -\('git checkout -b BRANCH REVISION')." - (interactive (magit-read-create-branch-args)) - (when (and branch (not (string= branch "")) - parent) - (magit-save-some-buffers) - (magit-run-git "checkout" "-b" - branch - (append - magit-custom-options - (magit-rev-to-git parent))) - (magit-update-vc-modeline default-directory))) - -(defun magit-delete-branch (branch &optional force) - "Deletes a branch. -If the branch is the current one, offers to switch to `master' first. -With prefix, forces the removal even if it hasn't been merged. -Works with local or remote branches. -\('git branch [-d|-D] BRANCH' or 'git push :refs/heads/BRANCH')." - (interactive (list (magit-read-rev "Branch to delete" (magit-default-rev 'notrim)) - current-prefix-arg)) - (let* ((remote (magit-remote-part-of-branch branch)) - (is-current (string= branch (magit-get-current-branch))) - (args (list "branch" - (if force "-D" "-d") - branch))) - (cond - (remote - (magit-run-git "push" remote (concat ":refs/heads/" (magit-branch-no-remote branch)))) - (is-current - (when (y-or-n-p "Cannot delete current branch. Switch to master first? ") - (progn - (magit-checkout "master") - (apply 'magit-run-git args)) - (message "The current branch was not deleted."))) - (t - (apply 'magit-run-git args))))) - -(defun magit-move-branch (old new &optional force) - "Renames or moves a branch. -With prefix, forces the move even if NEW already exists. -\('git branch [-m|-M] OLD NEW')." - (interactive (list (magit-read-rev "Old name" (magit-default-rev)) - (read-string "New name: ") - current-prefix-arg)) - (magit-run-git "branch" (if force - "-M" - "-m") - (magit-rev-to-git old) new)) - -(defun magit-guess-branch () - (magit-section-case (item info) - ((branch) - (magit-section-info (magit-current-section))) - ((wazzup commit) - (magit-section-info (magit-section-parent item))) - ((commit) (magit-name-rev (substring info 0 magit-sha1-abbrev-length))) - ((wazzup) info))) - -;;; Remotes - -(defun magit-add-remote (remote url) - "Adds a remote and fetches it. -\('git remote add REMOTE URL')." - (interactive (list (read-string "Add remote: ") - (read-string "URL: "))) - (magit-run-git "remote" "add" "-f" remote url)) - -(defun magit-remove-remote (remote) - "Deletes a remote. -\('git remote rm REMOTE')." - (interactive (list (magit-read-remote "Remote to delete"))) - (magit-run-git "remote" "rm" remote)) - -(defun magit-rename-remote (old new) - "Renames a remote. -\('git remote rename OLD NEW')." - (interactive (list (magit-read-remote "Old name") - (read-string "New name: "))) - (magit-run-git "remote" "rename" old new)) - -(defun magit-guess-remote () - (magit-section-case (item info) - ((branch) - (magit-section-info (magit-section-parent item))) - ((remote) - info) - (t - (if (string= info ".") - info - (magit-get-current-remote))))) - -;;; Merging - -(defun magit-merge (revision) - "Merge REVISION into the current 'HEAD'; leave changes uncommitted. -With a prefix-arg, the merge will be squashed. -\('git merge --no-commit [--squash|--no-ff] REVISION')." - (interactive - (list (magit-read-rev "Merge" (magit-default-rev)))) - (if revision - (apply 'magit-run-git - "merge" - (magit-rev-to-git revision) - magit-custom-options))) - -;;; Rebasing - -(defun magit-rebase-info () - "Returns a list indicating the state of an in-progress rebase, -if any." - (let ((git-dir (magit-git-dir))) - (cond ((file-exists-p (concat git-dir "rebase-merge")) - (list - ;; The commit we're rebasing onto, i.e. git rebase -i - (magit-name-rev (car (magit-file-lines (concat git-dir "rebase-merge/onto")))) - - ;; How many commits we've gone through - (length (magit-file-lines (concat git-dir "rebase-merge/done"))) - - ;; How many commits we have in total, without the comments - ;; at the end of git-rebase-todo.backup - (let ((todo-lines-with-comments (magit-file-lines (concat git-dir "rebase-merge/git-rebase-todo.backup")))) - (loop for i in todo-lines-with-comments - until (string= "" i) - count i)))) - ((and (file-exists-p (concat git-dir "rebase-apply")) - (file-exists-p (concat git-dir "rebase-apply/onto"))) - ;; we might be here because a non-interactive rebase failed: the - ;; patches didn't apply cleanly - (list - ;; The commit we're rebasing onto, i.e. git rebase -i - (magit-name-rev (car (magit-file-lines (concat git-dir "rebase-apply/onto")))) - - ;; How many commits we've gone through - (- (string-to-number (car (magit-file-lines (concat git-dir "rebase-apply/next")))) 1) - - ;; How many commits we have in total - (string-to-number (car (magit-file-lines (concat git-dir "rebase-apply/last")))) - )) - (t nil)))) - -(defun magit-rebase-step () - (interactive) - (let ((info (magit-rebase-info))) - (if (not info) - (let* ((current-branch (magit-get-current-branch)) - (rev (magit-read-rev "Rebase to" - (magit-format-ref (magit-remote-branch-for current-branch t)) - (if current-branch - (cons (concat "refs/heads/" current-branch) - magit-uninteresting-refs) - magit-uninteresting-refs)))) - (if rev - (magit-run-git "rebase" (magit-rev-to-git rev)))) - (let ((cursor-in-echo-area t) - (message-log-max nil)) - (message "Rebase in progress. [A]bort, [S]kip, or [C]ontinue? ") - (let ((reply (read-event))) - (case reply - ((?A ?a) - (magit-run-git-async "rebase" "--abort")) - ((?S ?s) - (magit-run-git-async "rebase" "--skip")) - ((?C ?c) - (magit-run-git-async "rebase" "--continue")))))))) - -;;; Resetting - -(magit-define-command reset-head (revision &optional hard) - "Switch 'HEAD' to REVISION, keeping prior working tree and staging area. -Any differences from REVISION become new changes to be committed. -With prefix argument, all uncommitted changes in working tree -and staging area are lost. -\('git reset [--soft|--hard] REVISION')." - (interactive (list (magit-read-rev (format "%s head to" - (if current-prefix-arg - "Hard reset" - "Reset")) - (or (magit-default-rev) - "HEAD^")) - current-prefix-arg)) - (when revision - (magit-run-git "reset" (if hard "--hard" "--soft") - (magit-rev-to-git revision)) - (magit-update-vc-modeline default-directory))) - -(magit-define-command reset-head-hard (revision) - "Switch 'HEAD' to REVISION, losing all changes. -Uncomitted changes in both working tree and staging area are lost. -\('git reset --hard REVISION')." - (interactive (list (magit-read-rev (format "Hard reset head to") - (or (magit-default-rev) - "HEAD")))) - (magit-reset-head revision t)) - -(magit-define-command reset-working-tree (&optional arg) - "Revert working tree and clear changes from staging area. -\('git reset --hard HEAD'). - -With a prefix arg, also remove untracked files. With two prefix args, remove ignored files as well." - (interactive "p") - (let ((include-untracked (>= arg 4)) - (include-ignored (>= arg 16))) - (when (yes-or-no-p (format "Discard all uncommitted changes%s%s? " - (if include-untracked - ", untracked files" - "") - (if include-ignored - ", ignored files" - ""))) - (magit-reset-head-hard "HEAD") - (if include-untracked - (magit-run-git "clean" "-fd" (if include-ignored - "-x" - "")))))) - -;;; Rewriting - -(defun magit-read-rewrite-info () - (when (file-exists-p (concat (magit-git-dir) "magit-rewrite-info")) - (with-temp-buffer - (insert-file-contents (concat (magit-git-dir) "magit-rewrite-info")) - (goto-char (point-min)) - (read (current-buffer))))) - -(defun magit-write-rewrite-info (info) - (with-temp-file (concat (magit-git-dir) "magit-rewrite-info") - (prin1 info (current-buffer)) - (princ "\n" (current-buffer)))) - -(magit-define-inserter pending-commits () - (let* ((info (magit-read-rewrite-info)) - (pending (cdr (assq 'pending info)))) - (when pending - (magit-with-section 'pending nil - (insert (propertize "Pending commits:\n" - 'face 'magit-section-title)) - (dolist (p pending) - (let* ((commit (car p)) - (properties (cdr p)) - (used (plist-get properties 'used))) - (magit-with-section commit 'commit - (magit-set-section-info commit) - (insert (magit-git-string - "log" "--max-count=1" - (if used - "--pretty=format:. %s" - "--pretty=format:* %s") - commit "--") - "\n"))))) - (insert "\n")))) - -(defun magit-rewrite-set-commit-property (commit prop value) - (let* ((info (magit-read-rewrite-info)) - (pending (cdr (assq 'pending info))) - (p (assoc commit pending))) - (when p - (setf (cdr p) (plist-put (cdr p) prop value)) - (magit-write-rewrite-info info) - (magit-need-refresh)))) - -(defun magit-rewrite-set-used () - (interactive) - (magit-section-action (item info) - ((pending commit) - (magit-rewrite-set-commit-property info 'used t)))) - -(defun magit-rewrite-set-unused () - (interactive) - (magit-section-action (item info) - ((pending commit) - (magit-rewrite-set-commit-property info 'used nil)))) - -(magit-define-inserter pending-changes () - (let* ((info (magit-read-rewrite-info)) - (orig (cadr (assq 'orig info)))) - (when orig - (let ((magit-hide-diffs t)) - (magit-git-section 'pending-changes - "Pending changes" - 'magit-wash-diffs - "diff" (magit-diff-U-arg) "-R" orig))))) - -(defun magit-rewrite-start (from &optional onto) - (interactive (list (magit-read-rev "Rewrite from" (magit-default-rev)))) - (or (magit-everything-clean-p) - (error "You have uncommitted changes")) - (or (not (magit-read-rewrite-info)) - (error "Rewrite in progress")) - (let* ((orig (magit-rev-parse "HEAD")) - (base - (if - (or - (eq magit-rewrite-inclusive t) - (and - (eq magit-rewrite-inclusive 'ask) - (y-or-n-p "Include selected revision in rewrite? "))) - (or - (car (magit-commit-parents from)) - (error "Can't rewrite a parentless commit.")) - from)) - (pending (magit-git-lines "rev-list" (concat base "..")))) - (magit-write-rewrite-info `((orig ,orig) - (pending ,@(mapcar #'list pending)))) - (magit-run-git "reset" "--hard" base))) - -(defun magit-rewrite-stop (&optional noconfirm) - (interactive) - (let* ((info (magit-read-rewrite-info))) - (or info - (error "No rewrite in progress")) - (when (or noconfirm - (yes-or-no-p "Stop rewrite? ")) - (magit-write-rewrite-info nil) - (magit-refresh)))) - -(defun magit-rewrite-abort () - (interactive) - (let* ((info (magit-read-rewrite-info)) - (orig (cadr (assq 'orig info)))) - (or info - (error "No rewrite in progress")) - (or (magit-everything-clean-p) - (error "You have uncommitted changes")) - (when (yes-or-no-p "Abort rewrite? ") - (magit-write-rewrite-info nil) - (magit-run-git "reset" "--hard" orig)))) - -(defun magit-rewrite-finish () - (interactive) - (magit-with-refresh - (magit-rewrite-finish-step t))) - -(defun magit-rewrite-finish-step (first-p) - (let ((info (magit-read-rewrite-info))) - (or info - (error "No rewrite in progress")) - (let* ((pending (cdr (assq 'pending info))) - (first-unused - (let ((rpend (reverse pending))) - (while (and rpend (plist-get (cdr (car rpend)) 'used)) - (setq rpend (cdr rpend))) - (car rpend))) - (commit (car first-unused))) - (cond ((not first-unused) - (magit-rewrite-stop t)) - ((magit-apply-commit commit t (not first-p)) - (magit-rewrite-set-commit-property commit 'used t) - (magit-rewrite-finish-step nil)))))) - -;;; Updating, pull, and push - -(magit-define-command fetch (remote) - "Fetch from REMOTE." - (interactive (list (magit-read-remote))) - (apply 'magit-run-git-async "fetch" remote magit-custom-options)) - -(magit-define-command fetch-current () - "Run fetch for default remote. - -If there is no default remote, ask for one." - (interactive) - (magit-fetch (or (magit-get-current-remote) - (magit-read-remote)))) - -(magit-define-command remote-update () - "Update all remotes." - (interactive) - (apply 'magit-run-git-async "remote" "update" magit-custom-options)) - -(magit-define-command pull () - "Run git pull against the current remote." - (interactive) - (let* ((branch (magit-get-current-branch)) - (branch-remote (magit-get-remote branch)) - (config-branch (and branch (magit-get "branch" branch "merge"))) - (merge-branch (or (and config-branch (not current-prefix-arg)) - (magit-read-remote-branch - branch-remote (format "Pull from: "))))) - (when (and branch (not config-branch)) - (magit-set branch-remote "branch" branch "remote") - (magit-set (format "refs/heads/%s" merge-branch) - "branch" branch "merge")) - (apply 'magit-run-git-async "pull" "-v" magit-custom-options))) - -(eval-when-compile (require 'eshell)) - -(defun magit-parse-arguments (command) - (require 'eshell) - (with-temp-buffer - (insert command) - (mapcar 'eval (eshell-parse-arguments (point-min) (point-max))))) - -(defun magit-shell-command (command) - "Perform arbitrary shell COMMAND." - (interactive "sCommand: ") - (let ((args (magit-parse-arguments command)) - (magit-process-popup-time 0)) - (magit-run* args nil nil nil t))) - -(defvar magit-git-command-history nil) - -(defun magit-git-command (command) - "Perform arbitrary Git COMMAND. - -Similar to `magit-shell-command', but involves slightly less -typing and automatically refreshes the status buffer." - (interactive - (list (read-string "Run git like this: " nil 'magit-git-command-history))) - (require 'pcomplete) - (let ((args (magit-parse-arguments command)) - (magit-process-popup-time 0)) - (magit-with-refresh - (magit-run* (append (cons magit-git-executable - magit-git-standard-options) - args) - nil nil nil t)))) - -(magit-define-command push-tags () - "Push tags." - (interactive) - (magit-run-git-async "push" "--tags")) - -(magit-define-command push () - "Push the current branch to a remote repository. - -With no prefix argument, ask `magit-get-remote' what remote to -use for this branch. - -With a prefix arg \(e.g., \\[universal-argument] \\[magit-push]), \ -ask user instead. - -With \\[universal-argument] \\[universal-argument] as prefix, \ -also prompt user for the remote branch; -otherwise, try to use the branch..merge git-config(1) -option, falling back to something hairy if that is unset." - (interactive) - (let* ((branch (or (magit-get-current-branch) - (error "Don't push a detached head. That's gross"))) - (branch-remote (magit-get-remote branch)) - (push-remote (if (or current-prefix-arg - (not branch-remote)) - (magit-read-remote (format "Push %s to remote" - branch) - branch-remote) - branch-remote)) - (ref-branch (or (and (>= (prefix-numeric-value current-prefix-arg) 16) - (magit-read-remote-branch - push-remote (format "Push %s as branch" branch))) - (magit-get "branch" branch "merge")))) - (if (and (not ref-branch) - (eq magit-set-upstream-on-push 'refuse)) - (error "Not pushing since no upstream has been set.") - (let ((set-upstream-on-push (and (not ref-branch) - (or (eq magit-set-upstream-on-push 'dontask) - (and (eq magit-set-upstream-on-push t) - (yes-or-no-p "Set upstream while pushing? ")))))) - (if (and (not branch-remote) - (not current-prefix-arg)) - (magit-set push-remote "branch" branch "remote")) - (apply 'magit-run-git-async "push" "-v" push-remote - (if ref-branch - (format "%s:%s" branch ref-branch) - branch) - (if set-upstream-on-push - (cons "--set-upstream" magit-custom-options) - magit-custom-options)) - ;; Although git will automatically set up the remote, - ;; it doesn't set up the branch to merge (at least as of Git 1.6.6.1), - ;; so we have to do that manually. - (unless ref-branch - (magit-set (concat "refs/heads/" branch) "branch" branch "merge")))))) - -;;; Log edit mode - -(defvar magit-log-edit-buffer-name "*magit-edit-log*" - "Buffer name for composing commit messages.") - -(defvar magit-log-edit-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-c") 'magit-log-edit-commit) - (define-key map (kbd "C-x #") 'magit-log-edit-commit) - (define-key map (kbd "C-c C-a") 'magit-log-edit-toggle-amending) - (define-key map (kbd "C-c C-s") 'magit-log-edit-toggle-signoff) - (define-key map (kbd "C-c C-t") 'magit-log-edit-toggle-author) - (define-key map (kbd "C-c C-e") 'magit-log-edit-toggle-allow-empty) - (define-key map (kbd "M-p") 'log-edit-previous-comment) - (define-key map (kbd "M-n") 'log-edit-next-comment) - (define-key map (kbd "C-c C-k") 'magit-log-edit-cancel-log-message) - (define-key map (kbd "C-c C-]") 'magit-log-edit-cancel-log-message) - (define-key map (kbd "C-x C-s") (lambda () - (interactive) - (message "Not saved. Use C-c C-c to finalize this commit message."))) - map)) - -(defvar magit-pre-log-edit-window-configuration nil) - -(define-derived-mode magit-log-edit-mode text-mode "Magit Log Edit" - ;; Recognize changelog-style paragraphs - (set (make-local-variable 'paragraph-start) - (concat paragraph-start "\\|*\\|("))) - -(defun magit-log-edit-cleanup () - (save-excursion - (goto-char (point-min)) - (goto-char (point-min)) - (if (re-search-forward "[ \t\n]*\\'" nil t) - (replace-match "\n" nil nil)))) - -(defun magit-log-edit-append (str) - (with-current-buffer (get-buffer-create magit-log-edit-buffer-name) - (goto-char (point-max)) - (insert str "\n"))) - -(defconst magit-log-header-end "-- End of Magit header --\n") - -(defun magit-log-edit-get-fields () - (let ((buf (get-buffer magit-log-edit-buffer-name)) - (result nil)) - (if buf - (with-current-buffer buf - (goto-char (point-min)) - (while (looking-at "^\\([A-Za-z0-9-_]+\\): *\\(.+\\)?$") - (setq result (acons (intern (downcase (match-string 1))) - (read (or (match-string 2) "nil")) - result)) - (forward-line)) - (if (not (looking-at (regexp-quote magit-log-header-end))) - (setq result nil)))) - (nreverse result))) - -(defun magit-log-edit-set-fields (fields) - (let ((buf (get-buffer-create magit-log-edit-buffer-name))) - (with-current-buffer buf - (goto-char (point-min)) - (if (search-forward-regexp (format "^\\([A-Za-z0-9-_]+:.*\n\\)*%s" - (regexp-quote magit-log-header-end)) - nil t) - (delete-region (match-beginning 0) (match-end 0))) - (goto-char (point-min)) - (when fields - (while fields - (insert (capitalize (symbol-name (caar fields))) ": " - (prin1-to-string (cdar fields)) "\n") - (setq fields (cdr fields))) - (insert magit-log-header-end))))) - -(defun magit-log-edit-set-field (name value) - (let* ((fields (magit-log-edit-get-fields)) - (cell (assq name fields))) - (cond (cell - (if value - (rplacd cell value) - (setq fields (delq cell fields)))) - (t - (if value - (setq fields (append fields (list (cons name value))))))) - (magit-log-edit-set-fields fields))) - -(defun magit-log-edit-get-field (name) - (cdr (assq name (magit-log-edit-get-fields)))) - -(defun magit-log-edit-toggle-field (name default) - "Toggle the log-edit field named NAME. -If it's currently unset, set it to DEFAULT (t or nil). - -Return nil if the field is toggled off, and non-nil if it's -toggled on. When it's toggled on for the first time, return -'first." - (let* ((fields (magit-log-edit-get-fields)) - (cell (assq name fields)) yesp) - (if cell - (progn - (setq yesp (equal (cdr cell) "yes")) - (rplacd cell (if yesp "no" "yes"))) - (setq fields (acons name (if default "yes" "no") fields)) - (setq yesp (if default 'first))) - (magit-log-edit-set-fields fields) - yesp)) - -(defun magit-log-edit-toggle-input (name default) - "Toggle the log-edit input named NAME. -If it's currently unset, set it to DEFAULT (a string). If it is -set remove it. - -Return nil if the input is toggled off, and its valud if it's -toggled on." - (let* ((fields (magit-log-edit-get-fields)) - (cell (assq name fields)) - result) - (if cell - (progn - (setq fields (assq-delete-all name fields) - result (cdr cell))) - (setq fields (acons name default fields))) - (magit-log-edit-set-fields fields) - result)) - -(defun magit-log-edit-setup-author-env (author) - "Set GIT_AUTHOR_* variables from AUTHOR spec. -If AUTHOR is nil, honor default values from -environment (potentially empty)." - (when author - ;; XXX - this is a bit strict, probably. - (or (string-match "\\(.*\\) <\\(.*\\)>\\(?:,\\s-*\\(.+\\)\\)?" author) - (error "Can't parse author string")) - ;; Shucks, setenv destroys the match data. - (let ((name (match-string 1 author)) - (email (match-string 2 author)) - (date (match-string 3 author))) - (make-local-variable 'process-environment) - (setenv "GIT_AUTHOR_NAME" name) - (setenv "GIT_AUTHOR_EMAIL" email) - (if date - (setenv "GIT_AUTHOR_DATE" date))))) - -(defun magit-log-edit-push-to-comment-ring (comment) - (when (or (ring-empty-p log-edit-comment-ring) - (not (equal comment (ring-ref log-edit-comment-ring 0)))) - (ring-insert log-edit-comment-ring comment))) - -(defun magit-log-edit-commit () - "Finish edits and create new commit object. -\('git commit ...')" - (interactive) - (let* ((fields (magit-log-edit-get-fields)) - (amend (equal (cdr (assq 'amend fields)) "yes")) - (allow-empty (equal (cdr (assq 'allow-empty fields)) "yes")) - (commit-all (equal (cdr (assq 'commit-all fields)) "yes")) - (sign-off-field (assq 'sign-off fields)) - (sign-off (if sign-off-field - (equal (cdr sign-off-field) "yes") - magit-commit-signoff)) - (tag-rev (cdr (assq 'tag-rev fields))) - (tag-name (cdr (assq 'tag-name fields))) - (author (cdr (assq 'author fields))) - (tag-options (cdr (assq 'tag-options fields)))) - - (unless (or (magit-anything-staged-p) - allow-empty - amend - tag-name - (file-exists-p (concat (magit-git-dir) "MERGE_HEAD")) - (and commit-all - (not (magit-everything-clean-p)))) - (error "Refusing to create empty commit. Maybe you want to amend (%s) or allow-empty (%s)?" - (key-description (car (where-is-internal - 'magit-log-edit-toggle-amending))) - (key-description (car (where-is-internal - 'magit-log-edit-toggle-allow-empty))))) - - (magit-log-edit-push-to-comment-ring (buffer-string)) - (magit-log-edit-setup-author-env author) - (magit-log-edit-set-fields nil) - (magit-log-edit-cleanup) - (if (= (buffer-size) 0) - (insert "(Empty description)\n")) - (let ((env process-environment) - (commit-buf (current-buffer))) - (with-current-buffer (magit-find-status-buffer default-directory) - (let ((process-environment env)) - (cond (tag-name - (apply #'magit-run-git-with-input commit-buf - "tag" (append tag-options (list tag-name "-a" "-F" "-" tag-rev)))) - (t - (apply #'magit-run-async-with-input commit-buf - magit-git-executable - (append magit-git-standard-options - '("commit") - magit-custom-options - '("-F" "-") - (if (and commit-all (not allow-empty)) '("--all") '()) - (if amend '("--amend") '()) - (if allow-empty '("--allow-empty")) - (if sign-off '("--signoff") '())))))))) - ;; shouldn't we kill that buffer altogether? - (erase-buffer) - (let ((magit-buf magit-buffer-internal)) - (bury-buffer) - (set-buffer magit-buf)) - (when (file-exists-p (concat (magit-git-dir) "MERGE_MSG")) - (delete-file (concat (magit-git-dir) "MERGE_MSG"))) - ;; potentially the local environment has been altered with settings that - ;; were specific to this commit. Let's revert it - (kill-local-variable 'process-environment) - (magit-update-vc-modeline default-directory) - (when magit-pre-log-edit-window-configuration - (set-window-configuration magit-pre-log-edit-window-configuration) - (setq magit-pre-log-edit-window-configuration nil)))) - -(defun magit-log-edit-cancel-log-message () - "Abort edits and erase commit message being composed." - (interactive) - (when (or (not magit-log-edit-confirm-cancellation) - (yes-or-no-p - "Really cancel editing the log (any changes will be lost)?")) - (erase-buffer) - (bury-buffer) - (when magit-pre-log-edit-window-configuration - (set-window-configuration magit-pre-log-edit-window-configuration) - (setq magit-pre-log-edit-window-configuration nil)))) - -(defun magit-log-edit-toggle-amending () - "Toggle whether this will be an amendment to the previous commit. -\(i.e., whether eventual commit does 'git commit --amend')" - (interactive) - (when (eq (magit-log-edit-toggle-field 'amend t) 'first) - (magit-log-edit-append - (magit-trim-line (magit-format-commit "HEAD" "%s%n%n%b"))))) - -(defun magit-log-edit-toggle-signoff () - "Toggle whether this commit will include a signoff. -\(i.e., whether eventual commit does 'git commit --signoff')" - (interactive) - (magit-log-edit-toggle-field 'sign-off (not magit-commit-signoff))) - -(defun magit-log-edit-toggle-author () - "Toggle whether this commit will include an author. -\(i.e., whether eventual commit is run with GIT_AUTHOR_NAME and -GIT_AUTHOR_EMAIL set)" - (interactive) - (magit-log-edit-toggle-input 'author (format "%s <%s>" - (or (magit-get "user" "name") "Author Name") - (or (magit-get "user" "email") "author@email")))) - -(defun magit-log-edit-toggle-allow-empty () - "Toggle whether this commit is allowed to be empty. -This means that the eventual commit does 'git commit --allow-empty'." - (interactive) - (magit-log-edit-toggle-field 'allow-empty t)) - -(defun magit-pop-to-log-edit (operation) - (let ((dir default-directory) - (magit-buf (current-buffer)) - (buf (get-buffer-create magit-log-edit-buffer-name))) - (setq magit-pre-log-edit-window-configuration - (current-window-configuration)) - (pop-to-buffer buf) - (setq default-directory dir) - (when (file-exists-p (concat (magit-git-dir) "MERGE_MSG")) - (insert-file-contents (concat (magit-git-dir) "MERGE_MSG"))) - (magit-log-edit-mode) - (make-local-variable 'magit-buffer-internal) - (setq magit-buffer-internal magit-buf) - (message "Type C-c C-c to %s (C-c C-k to cancel)." operation))) - -(defun magit-log-edit (&optional arg) - "Brings up a buffer to allow editing of commit messages. - -Giving a simple prefix arg will amend a previous commit, while -a double prefix arg will allow creating an empty one. - -If there is a rebase in progress, offer the user the option to -continue it. - -\\{magit-log-edit-mode-map}" - (interactive "P") - ;; If repository is dirty there is no point in trying to - ;; suggest to continue the rebase. Git will rebuke you and exit with - ;; error code, so suggest it only if theres absolutely nothing else - ;; to do and rebase is ongoing. - (if (and (magit-everything-clean-p) - (magit-rebase-info) - (y-or-n-p "Rebase in progress. Continue it? ")) - (magit-run-git-async "rebase" "--continue") - - ;; If there's nothing staged, set commit flag to `nil', thus - ;; avoiding unnescessary popping up of the log edit buffer in case - ;; when user chose to forgo commiting all unstaged changes - (let ((amend-p (= (prefix-numeric-value arg) 4)) - (empty-p (= (prefix-numeric-value arg) 16))) - (when (and magit-commit-all-when-nothing-staged - (not (magit-everything-clean-p)) - (not (magit-anything-staged-p))) - (cond ((eq magit-commit-all-when-nothing-staged 'ask-stage) - (when (y-or-n-p "Nothing staged. Stage everything now? ") - (magit-stage-all))) - ((not (magit-log-edit-get-field 'commit-all)) - (when (or (eq magit-commit-all-when-nothing-staged t) - (y-or-n-p - "Nothing staged. Commit all unstaged changes? ")) - (magit-log-edit-set-field 'commit-all "yes"))))) - (when amend-p - (magit-log-edit-toggle-amending)) - (when empty-p - (magit-log-edit-toggle-allow-empty)) - (let ((author-email (or (getenv "GIT_AUTHOR_EMAIL") "")) - (author-name (or (getenv "GIT_AUTHOR_NAME") "")) - (author-date (or (getenv "GIT_AUTHOR_DATE") ""))) - (if (not (string= author-email "")) - (magit-log-edit-set-field 'author (format "%s <%s>%s" - (if (string= "" author-name) author-email author-name) - author-email - (if (string= "" author-date) "" (format ", %s" author-date)))))) - (magit-pop-to-log-edit "commit")))) - -(defun magit-add-log () - (interactive) - (cond ((magit-rebase-info) - (if (y-or-n-p "Rebase in progress. Continue it? ") - (magit-run-git-async "rebase" "--continue"))) - (t - (let ((section (magit-current-section))) - (let ((fun (if (eq (magit-section-type section) 'hunk) - (save-window-excursion - (save-excursion - (magit-visit-item) - (add-log-current-defun))) - nil)) - (file (magit-diff-item-file - (cond ((eq (magit-section-type section) 'hunk) - (magit-hunk-item-diff section)) - ((eq (magit-section-type section) 'diff) - section) - (t - (error "No change at point")))))) - (magit-log-edit nil) - (goto-char (point-min)) - (cond ((not (search-forward-regexp - (format "^\\* %s" (regexp-quote file)) nil t)) - ;; No entry for file, create it. - (goto-char (point-max)) - (insert (format "\n* %s" file)) - (if fun - (insert (format " (%s)" fun))) - (insert ": ")) - (fun - ;; found entry for file, look for fun - (let ((limit (or (save-excursion - (and (search-forward-regexp "^\\* " - nil t) - (match-beginning 0))) - (point-max)))) - (cond ((search-forward-regexp (format "(.*\\<%s\\>.*):" - (regexp-quote fun)) - limit t) - ;; found it, goto end of current entry - (if (search-forward-regexp "^(" limit t) - (backward-char 2) - (goto-char limit))) - (t - ;; not found, insert new entry - (goto-char limit) - (if (bolp) - (open-line 1) - (newline)) - (insert (format "(%s): " fun)))))) - (t - ;; found entry for file, look for beginning it - (when (looking-at ":") - (forward-char 2))))))))) - -;;; Tags - -(magit-define-command tag (name rev) - "Create a new lightweight tag with the given NAME at REV. -\('git tag NAME')." - (interactive - (list - (read-string "Tag name: ") - (magit-read-rev "Place tag on: " (or (magit-default-rev) "HEAD")))) - (apply #'magit-run-git "tag" (append magit-custom-options (list name rev)))) - -(magit-define-command annotated-tag (name rev) - "Start composing an annotated tag with the given NAME. -Tag will point to the current 'HEAD'." - (interactive - (list - (read-string "Tag name: ") - (magit-read-rev "Place tag on: " (or (magit-default-rev) "HEAD")))) - (magit-log-edit-set-field 'tag-name name) - (magit-log-edit-set-field 'tag-rev rev) - (magit-log-edit-set-field 'tag-options magit-custom-options) - (magit-pop-to-log-edit "tag")) - -;;; Stashing - -(defun magit-wash-stash () - (if (search-forward-regexp "stash@{\\(.*?\\)}" (line-end-position) t) - (let ((stash (match-string-no-properties 0)) - (name (match-string-no-properties 1))) - (delete-region (match-beginning 0) (match-end 0)) - (goto-char (match-beginning 0)) - (fixup-whitespace) - (goto-char (line-beginning-position)) - (insert name) - (goto-char (line-beginning-position)) - (magit-with-section stash 'stash - (magit-set-section-info stash) - (forward-line))) - (forward-line)) - t) - -(defun magit-wash-stashes () - (let ((magit-old-top-section nil)) - (magit-wash-sequence #'magit-wash-stash))) - -(magit-define-inserter stashes () - (magit-git-section 'stashes - "Stashes:" 'magit-wash-stashes - "stash" "list")) - -(magit-define-command stash (description) - "Create new stash of working tree and staging area named DESCRIPTION. -Working tree and staging area revert to the current 'HEAD'. -With prefix argument, changes in staging area are kept. -\('git stash save [--keep-index] DESCRIPTION')" - (interactive "sStash description: ") - (apply 'magit-run-git `("stash" "save" ,@magit-custom-options "--" ,description))) - -(magit-define-command stash-snapshot () - "Create new stash of working tree and staging area; keep changes in place. -\('git stash save \"Snapshot...\"; git stash apply stash@{0}')" - (interactive) - (magit-with-refresh - (apply 'magit-run-git `("stash" "save" ,@magit-custom-options - ,(format-time-string "Snapshot taken at %Y-%m-%d %H:%M:%S" - (current-time)))) - (magit-run-git "stash" "apply" "stash@{0}"))) - -(defvar magit-currently-shown-stash nil) - -(define-derived-mode magit-stash-mode magit-mode "Magit Stash" - "Mode for looking at a git stash. - -\\{magit-stash-mode-map}" - :group 'magit) - -(defvar magit-stash-buffer-name "*magit-stash*" - "Buffer name for displaying a stash.") - -(defun magit-show-stash (stash &optional scroll) - (when (magit-section-p stash) - (setq stash (magit-section-info stash))) - (let ((dir default-directory) - (buf (get-buffer-create magit-stash-buffer-name)) - (stash-id (magit-git-string "rev-list" "-1" stash))) - (cond ((and (equal magit-currently-shown-stash stash-id) - (with-current-buffer buf - (> (length (buffer-string)) 1))) - (let ((win (get-buffer-window buf))) - (cond ((not win) - (display-buffer buf)) - (scroll - (with-selected-window win - (funcall scroll)))))) - (t - (setq magit-currently-shown-stash stash-id) - (display-buffer buf) - (with-current-buffer buf - (set-buffer buf) - (goto-char (point-min)) - (let* ((range (cons (concat stash "^2^") stash)) - (magit-current-diff-range range) - (args (magit-rev-range-to-git range))) - (magit-mode-init dir 'magit-diff-mode #'magit-refresh-diff-buffer - range args))))))) -;;; Commits - -(defun magit-commit-at-point (&optional nil-ok-p) - (let* ((section (magit-current-section)) - (commit (if (and section - (eq (magit-section-type section) 'commit)) - (magit-section-info section) - (get-text-property (point) 'revision)))) - (if nil-ok-p - commit - (or commit - (error "No commit at point"))))) - -(defun magit-apply-commit (commit &optional docommit noerase revert) - (let* ((parent-id (magit-choose-parent-id commit "cherry-pick")) - (success (magit-run* `(,magit-git-executable - ,@magit-git-standard-options - ,(if revert "revert" "cherry-pick") - ,@(if parent-id - (list "-m" (number-to-string parent-id))) - ,@(if (not docommit) (list "--no-commit")) - ,commit) - nil noerase))) - (when (and (not docommit) success) - (cond (revert - (magit-log-edit-append - (magit-format-commit commit "Reverting \"%s\""))) - (t - (magit-log-edit-append - (magit-format-commit commit "%s%n%n%b")) - (magit-log-edit-set-field - 'author - (magit-format-commit commit "%an <%ae>, %ai"))))) - success)) - -(defun magit-apply-item () - (interactive) - (magit-section-action (item info "apply") - ((pending commit) - (magit-apply-commit info) - (magit-rewrite-set-commit-property info 'used t)) - ((commit) - (magit-apply-commit info)) - ((unstaged *) - (error "Change is already in your working tree")) - ((staged *) - (error "Change is already in your working tree")) - ((hunk) - (magit-apply-hunk-item item)) - ((diff) - (magit-apply-diff-item item)) - ((stash) - (magit-run-git "stash" "apply" info)))) - -(defun magit-cherry-pick-item () - (interactive) - (magit-section-action (item info "cherry-pick") - ((pending commit) - (magit-apply-commit info t) - (magit-rewrite-set-commit-property info 'used t)) - ((commit) - (magit-apply-commit info t)) - ((stash) - (magit-run-git "stash" "pop" info)))) - -(defmacro magit-with-revert-confirmation (&rest body) - `(when (or (not magit-revert-item-confirm) - (yes-or-no-p "Really revert this item? ")) - ,@body)) - -(defun magit-revert-item () - (interactive) - (magit-section-action (item info "revert") - ((pending commit) - (magit-with-revert-confirmation - (magit-apply-commit info nil nil t) - (magit-rewrite-set-commit-property info 'used nil))) - ((commit) - (magit-with-revert-confirmation - (magit-apply-commit info nil nil t))) - ;; Reverting unstaged changes cannot be undone - ((unstaged *) - (magit-discard-item)) - ((hunk) - (magit-with-revert-confirmation - (magit-apply-hunk-item-reverse item))) - ((diff) - (magit-with-revert-confirmation - (magit-apply-diff-item item "--reverse"))))) - -(defun magit-log-show-more-entries (&optional arg) - "Grow the number of log entries shown. - -With no prefix optional ARG, show twice as many log entries. -With a numerical prefix ARG, add this number to the number of shown log entries. -With a non numeric prefix ARG, show all entries" - (interactive "P") - (make-local-variable 'magit-log-cutoff-length) - (cond - ((numberp arg) - (setq magit-log-cutoff-length (+ magit-log-cutoff-length arg))) - (arg - (setq magit-log-cutoff-length magit-log-infinite-length)) - (t (setq magit-log-cutoff-length (* magit-log-cutoff-length 2)))) - (let ((old-point (point))) - (magit-refresh) - (goto-char old-point))) - -(defun magit-refresh-log-buffer (range style args) - (magit-configure-have-graph) - (magit-configure-have-decorate) - (magit-configure-have-abbrev) - (setq magit-current-range range) - (magit-create-log-buffer-sections - (apply #'magit-git-section nil - (magit-rev-range-describe range "Commits") - (apply-partially 'magit-wash-log style) - `("log" - ,(format "--max-count=%s" magit-log-cutoff-length) - ,"--abbrev-commit" - ,(format "--abbrev=%s" magit-sha1-abbrev-length) - ,@(cond ((eq style 'long) (list "--stat" "-z")) - ((eq style 'oneline) (list "--pretty=oneline")) - (t nil)) - ,@(if magit-have-decorate (list "--decorate=full")) - ,@(if magit-have-graph (list "--graph")) - ,@args - "--")))) - -(define-derived-mode magit-log-mode magit-mode "Magit Log" - "Mode for looking at git log. - -\\{magit-log-mode-map}" - :group 'magit) - -(defvar magit-log-buffer-name "*magit-log*" - "Buffer name for display of log entries.") - -(magit-define-command log-ranged () - (interactive) - (magit-log t)) -(define-obsolete-function-alias 'magit-display-log-ranged 'magit-log-ranged) - -(magit-define-command log (&optional ask-for-range &rest extra-args) - (interactive) - (let* ((log-range (if ask-for-range - (magit-read-rev-range "Log" "HEAD") - "HEAD")) - (topdir (magit-get-top-dir default-directory)) - (args (nconc (list (magit-rev-range-to-git log-range)) - magit-custom-options - extra-args))) - (magit-buffer-switch magit-log-buffer-name) - (magit-mode-init topdir 'magit-log-mode #'magit-refresh-log-buffer log-range - 'oneline args))) - -(define-obsolete-function-alias 'magit-display-log 'magit-log) - -(magit-define-command log-long-ranged () - (interactive) - (magit-log-long t)) - -(magit-define-command log-long (&optional ranged) - (interactive) - (let* ((range (if ranged - (magit-read-rev-range "Long log" "HEAD") - "HEAD")) - (topdir (magit-get-top-dir default-directory)) - (args (append (list (magit-rev-range-to-git range)) - magit-custom-options))) - (magit-buffer-switch magit-log-buffer-name) - (magit-mode-init topdir 'magit-log-mode #'magit-refresh-log-buffer range - 'long args))) - -;;; Reflog - -(defvar magit-reflog-head nil - "The HEAD of the reflog in the current buffer. -This is only non-nil in reflog buffers.") -(make-variable-buffer-local 'magit-reflog-head) - -(defun magit-refresh-reflog-buffer (head args) - (setq magit-reflog-head head) - (magit-create-log-buffer-sections - (apply #'magit-git-section - 'reflog (format "Local history of head %s" head) 'magit-wash-log "log" - (append magit-git-log-options - (list - "--walk-reflogs" - (format "--max-count=%s" magit-log-cutoff-length) - args))))) - -(define-derived-mode magit-reflog-mode magit-log-mode "Magit Reflog" - "Mode for looking at git reflog. - -\\{magit-reflog-mode-map}" - :group 'magit) - -(magit-define-command reflog (&optional ask-for-range) - (interactive) - (let ((at (or (if ask-for-range - (magit-read-rev "Reflog of" (or (magit-guess-branch) "HEAD"))) - "HEAD"))) - (let* ((topdir (magit-get-top-dir default-directory)) - (args (magit-rev-to-git at))) - (magit-buffer-switch "*magit-reflog*") - (magit-mode-init topdir 'magit-reflog-mode - #'magit-refresh-reflog-buffer at args)))) - -(magit-define-command reflog-ranged () - (interactive) - (magit-reflog t)) - -;;; Diffing - -(defvar magit-ediff-buffers nil - "List of buffers that may be killed by `magit-ediff-restore'.") - -(defvar magit-ediff-windows nil - "The window configuration that will be restored when Ediff is finished.") - -(defun magit-ediff() - "View the current DIFF section in ediff." - (interactive) - (let ((diff (magit-current-section))) - (when (magit-section-hidden diff) - ;; Range is not set until the first time the diff is visible. - ;; This somewhat hackish code makes sure it's been visible at least once. - (magit-toggle-section) - (magit-toggle-section) - (setq diff (magit-current-section))) - (if (eq 'hunk (magit-section-type diff)) - (setq diff (magit-section-parent diff))) - (unless (eq 'diff (magit-section-type diff)) - (error "No diff at this location")) - (let* ((type (magit-diff-item-kind diff)) - (file1 (magit-diff-item-file diff)) - (file2 (magit-diff-item-file2 diff)) - (range (magit-diff-item-range diff))) - (cond - ((memq type '(new deleted typechange)) - (message "Why ediff a %s file?" type)) - ((and (eq type 'unmerged) - (eq (cdr range) 'working)) - (magit-interactive-resolve file1)) - ((consp (car range)) - (magit-ediff* (magit-show (caar range) file2) - (magit-show (cdar range) file2) - (magit-show (cdr range) file1))) - (t - (magit-ediff* (magit-show (car range) file2) - (magit-show (cdr range) file1))))))) - -(defun magit-ediff* (a b &optional c) - (setq magit-ediff-buffers (list a b c)) - (setq magit-ediff-windows (current-window-configuration)) - (add-hook 'ediff-quit-hook 'magit-ediff-restore 'append) - (if c - (ediff-buffers3 a b c) - (ediff-buffers a b))) - -(defun magit-ediff-restore() - "Kill any buffers in `magit-ediff-buffers' that are not visiting files and -restore the window state that was saved before ediff was called." - (dolist (buffer magit-ediff-buffers) - (if (and (null (buffer-file-name buffer)) - (buffer-live-p buffer)) - (kill-buffer buffer))) - (setq magit-ediff-buffers nil) - (set-window-configuration magit-ediff-windows) - (remove-hook 'ediff-quit-hook 'magit-ediff-restore)) - -(defun magit-refresh-diff-buffer (range args) - (let ((magit-current-diff-range (cond - ((stringp range) - (cons range 'working)) - ((null (cdr range)) - (cons (car range) 'working)) - (t - range)))) - (setq magit-current-range range) - (magit-create-buffer-sections - (magit-git-section 'diffbuf - (magit-rev-range-describe range "Changes") - 'magit-wash-diffs - "diff" (magit-diff-U-arg) args "--")))) - -(define-derived-mode magit-diff-mode magit-mode "Magit Diff" - "Mode for looking at a git diff. - -\\{magit-diff-mode-map}" - :group 'magit) - -(magit-define-command diff (range) - (interactive (list (magit-read-rev-range "Diff"))) - (if range - (let* ((dir default-directory) - (args (magit-rev-range-to-git range)) - (buf (get-buffer-create "*magit-diff*"))) - (display-buffer buf) - (with-current-buffer buf - (magit-mode-init dir 'magit-diff-mode #'magit-refresh-diff-buffer range args))))) - -(magit-define-command diff-working-tree (rev) - (interactive (list (magit-read-rev "Diff with" (magit-default-rev)))) - (magit-diff (or rev "HEAD"))) - -(defun magit-diff-with-mark () - (interactive) - (magit-diff (cons (magit-marked-commit) - (magit-commit-at-point)))) - -;;; Wazzup - -(defvar magit-wazzup-head nil - "The integration head for the current wazzup buffer. -This is only non-nil in wazzup buffers.") -(make-variable-buffer-local 'magit-wazzup-head) - -(defvar magit-wazzup-all-p nil - "Non-nil if the current wazzup buffer displays excluded branches. -This is only meaningful in wazzup buffers.") -(make-variable-buffer-local 'magit-wazzup-all-p) - -(defun magit-wazzup-toggle-ignore (branch edit) - (let ((ignore-file (concat (magit-git-dir) "info/wazzup-exclude"))) - (if edit - (setq branch (read-string "Branch to ignore for wazzup: " branch))) - (let ((ignored (magit-file-lines ignore-file))) - (cond ((member branch ignored) - (when (or (not edit) - (y-or-n-p "Branch %s is already ignored. Unignore? ")) - (setq ignored (delete branch ignored)))) - (t - (setq ignored (append ignored (list branch))))) - (magit-write-file-lines ignore-file ignored) - (magit-need-refresh)))) - -(defun magit-refresh-wazzup-buffer (head all) - (setq magit-wazzup-head head) - (setq magit-wazzup-all-p all) - (let ((branch-desc (or head "(detached) HEAD"))) - (unless head (setq head "HEAD")) - (magit-create-buffer-sections - (magit-with-section 'wazzupbuf nil - (insert (format "Wazzup, %s\n\n" branch-desc)) - (let* ((excluded (magit-file-lines (concat (magit-git-dir) "info/wazzup-exclude"))) - (all-branches (magit-list-interesting-refs)) - (branches (if all all-branches - (delq nil (mapcar - (lambda (b) - (and (not - (member (cdr b) excluded)) - b)) - all-branches)))) - (reported (make-hash-table :test #'equal))) - (dolist (branch branches) - (let* ((name (car branch)) - (ref (cdr branch)) - (hash (magit-rev-parse ref)) - (reported-branch (gethash hash reported))) - (unless (or (and reported-branch - (string= (file-name-nondirectory ref) - reported-branch)) - (not (magit-git-string "merge-base" head ref))) - (puthash hash (file-name-nondirectory ref) reported) - (let* ((n (length (magit-git-lines "log" "--pretty=oneline" - (concat head ".." ref)))) - (section - (let ((magit-section-hidden-default t)) - (magit-git-section - (cons ref 'wazzup) - (format "%s unmerged commits in %s%s" - n name - (if (member ref excluded) - " (normally ignored)" - "")) - 'magit-wash-log - "log" - (format "--max-count=%s" magit-log-cutoff-length) - "--abbrev-commit" - (format "--abbrev=%s" magit-sha1-abbrev-length) - "--graph" - "--pretty=oneline" - (format "%s..%s" head ref) - "--")))) - (magit-set-section-info ref section)))))))))) - -(define-derived-mode magit-wazzup-mode magit-mode "Magit Wazzup" - "Mode for looking at commits that could be merged from other branches. - -\\{magit-wazzup-mode-map}" - :group 'magit) - -(defun magit-wazzup (&optional all) - (interactive "P") - (let ((topdir (magit-get-top-dir default-directory)) - (current-branch (magit-get-current-branch))) - (magit-buffer-switch "*magit-wazzup*") - (magit-mode-init topdir 'magit-wazzup-mode - #'magit-refresh-wazzup-buffer - current-branch all))) - -(defun magit-filename (filename) - "Return the path of FILENAME relative to its git repository. - -If FILENAME is absolute, return a path relative to the git -repository containing it. Otherwise, return a path relative to -the current git repository." - (let ((topdir (expand-file-name - (magit-get-top-dir (or (file-name-directory filename) - default-directory)))) - (file (file-truename filename))) - (when (and (not (string= topdir "")) - ;; FILE must start with the git repository path - (zerop (string-match-p (concat "\\`" topdir) file))) - (substring file (length topdir))))) - -;; This variable is used to keep track of the current file in the -;; *magit-log* buffer when this one is dedicated to showing the log of -;; just 1 file. -(defvar magit-file-log-file nil) -(make-variable-buffer-local 'magit-file-log-file) - -(defun magit-refresh-file-log-buffer (file range style) - "Refresh the current file-log buffer by calling git. - -FILE is the path of the file whose log must be displayed. - -`magit-current-range' will be set to the value of RANGE. - -STYLE controls the display. It is either `'long', `'oneline', or something else. - " - (magit-configure-have-graph) - (magit-configure-have-decorate) - (magit-configure-have-abbrev) - (setq magit-current-range range) - (setq magit-file-log-file file) - (magit-create-log-buffer-sections - (apply #'magit-git-section nil - (magit-rev-range-describe range (format "Commits for file %s" file)) - (apply-partially 'magit-wash-log style) - `("log" - ,(format "--max-count=%s" magit-log-cutoff-length) - ,"--abbrev-commit" - ,(format "--abbrev=%s" magit-sha1-abbrev-length) - ,@(cond ((eq style 'long) (list "--stat" "-z")) - ((eq style 'oneline) (list "--pretty=oneline")) - (t nil)) - ,@(if magit-have-decorate (list "--decorate=full")) - ,@(if magit-have-graph (list "--graph")) - "--" - ,file)))) - -(defun magit-file-log (&optional all) - "Display the log for the currently visited file or another one. - -With a prefix argument or if no file is currently visited, ask -for the file whose log must be displayed." - (interactive "P") - (let ((topdir (magit-get-top-dir default-directory)) - (current-file (magit-filename - (if (or current-prefix-arg (not buffer-file-name)) - (magit-read-file-from-rev (magit-get-current-branch)) - buffer-file-name))) - (range "HEAD")) - (magit-buffer-switch "*magit-log*") - (magit-mode-init topdir 'magit-log-mode - #'magit-refresh-file-log-buffer - current-file range 'oneline))) - -(defun magit-show-file-revision () - "Open a new buffer showing the current file in the revision at point." - (interactive) - (flet ((magit-show-file-from-diff (item) - (switch-to-buffer-other-window - (magit-show (cdr (magit-diff-item-range item)) - (magit-diff-item-file item))))) - (magit-section-action (item info "show") - ((commit) - (let ((current-file (or magit-file-log-file - (magit-read-file-from-rev info)))) - (switch-to-buffer-other-window - (magit-show info current-file)))) - ((hunk) (magit-show-file-from-diff (magit-hunk-item-diff item))) - ((diff) (magit-show-file-from-diff item))))) - -;;; Miscellaneous - -(defun magit-ignore-modifiable-file (file edit) - "Prompt the user for the filename to be added to git ignore. -\\ -The minibuffer's future history (accessible with \\[next-history-element]) -contains predefined values (such as wildcards) that might -be of interest. -The history and default value are derived from the filename FILE. -If EDIT argument is negative, the prompt proposes wildcard by default. -" - (let* ((just-extension (concat "*." (file-name-extension file))) - (full-extension (concat (file-name-directory file) just-extension)) - (just-file (file-name-nondirectory file)) - ;; change the order in history depending on the negativity of - ;; EDIT. - (history (if (< (prefix-numeric-value edit) 0) - (list full-extension just-extension file just-file) - (list file full-extension just-extension just-file)))) - (read-string - (format "File to ignore [%s]: " (car history)) - nil nil history))) - -(defun magit-ignore-file (file edit local) - "Add FILE to the list of files to ignore. -\\ -If EDIT is non-`nil', prompt the user for the filename to -be added to git ignore. In this case, the minibuffer's -future history (accessible with \\[next-history-element]) contains predefined -values (such as wildcards) that might be of interest. - -If LOCAL is nil, the `.gitignore' file is updated. -Otherwise, it is `.git/info/exclude'." - (let* ((local-ignore-dir (concat (magit-git-dir) "info/")) - (ignore-file (if local - (concat local-ignore-dir "exclude") - ".gitignore"))) - (if edit - (setq file (magit-ignore-modifiable-file file edit))) - (if (and local (not (file-exists-p local-ignore-dir))) - (make-directory local-ignore-dir t)) - (with-temp-buffer - (when (file-exists-p ignore-file) - (insert-file-contents ignore-file)) - (goto-char (point-max)) - (unless (bolp) - (insert "\n")) - (insert file "\n") - (write-region nil nil ignore-file)) - (magit-need-refresh))) - -(defun magit-ignore-item () - "Add FILE to the `.gitignore' list of files to ignore. -\\ -With a prefix argument, prompt the user for the filename to -be added. In this case, the minibuffer's future history -\(accessible with \\[next-history-element]) contains predefined values (such as -wildcards) that might be of interest. If prefix argument is -negative, the prompt proposes wildcard by default." - (interactive) - (magit-section-action (item info "ignore") - ((untracked file) - (magit-ignore-file (concat "/" info) current-prefix-arg nil)) - ((wazzup) - (magit-wazzup-toggle-ignore info current-prefix-arg)))) - -(defun magit-ignore-item-locally () - "Add FILE to the `.git/info/exclude' list of files to ignore. -\\ -With a prefix argument, prompt the user for the filename to -be added. In this case, the minibuffer's future history -(accessible with \\[next-history-element]) contains predefined values (such as -wildcards) that might be of interest. If prefix argument is -negative, the prompt proposes wildcard by default." - (interactive) - (magit-section-action (item info "ignore") - ((untracked file) - (magit-ignore-file (concat "/" info) current-prefix-arg t)))) - -(defun magit-discard-diff (diff stagedp) - (let ((kind (magit-diff-item-kind diff)) - (file (magit-diff-item-file diff))) - (cond ((eq kind 'deleted) - (when (yes-or-no-p (format "Resurrect %s? " file)) - (magit-run-git "reset" "-q" "--" file) - (magit-run-git "checkout" "--" file))) - ((eq kind 'new) - (if (yes-or-no-p (format "Delete %s? " file)) - (magit-run-git "rm" "-f" "--" file))) - (t - (if (yes-or-no-p (format "Discard changes to %s? " file)) - (if stagedp - (magit-run-git "checkout" "HEAD" "--" file) - (magit-run-git "checkout" "--" file))))))) - -(defun magit-discard-item () - (interactive) - (magit-section-action (item info "discard") - ((untracked file) - (when (yes-or-no-p (format "Delete %s? " info)) - (if (and (file-directory-p info) - (not (file-symlink-p info))) - (magit-delete-directory info 'recursive) - (delete-file info)) - (magit-refresh-buffer))) - ((untracked) - (if (yes-or-no-p "Delete all untracked files and directories? ") - (magit-run-git "clean" "-df"))) - ((unstaged diff hunk) - (when (yes-or-no-p (if (magit-use-region-p) - "Discard changes in region? " - "Discard hunk? ")) - (magit-apply-hunk-item-reverse item))) - ((staged diff hunk) - (if (magit-file-uptodate-p (magit-diff-item-file - (magit-hunk-item-diff item))) - (when (yes-or-no-p (if (magit-use-region-p) - "Discard changes in region? " - "Discard hunk? ")) - (magit-apply-hunk-item-reverse item "--index")) - (error "Can't discard this hunk. Please unstage it first"))) - ((unstaged diff) - (magit-discard-diff item nil)) - ((staged diff) - (if (magit-file-uptodate-p (magit-diff-item-file item)) - (magit-discard-diff item t) - (error "Can't discard staged changes to this file. Please unstage it first"))) - ((diff diff) - (save-excursion - (magit-goto-parent-section) - (magit-discard-item))) - ((diff diff hunk) - (save-excursion - (magit-goto-parent-section) - (magit-goto-parent-section) - (magit-discard-item))) - ((hunk) - (error "Can't discard this hunk")) - ((diff) - (error "Can't discard this diff")) - ((stash) - (when (yes-or-no-p "Discard stash? ") - (magit-run-git "stash" "drop" info))) - ((branch) - (when (yes-or-no-p (if current-prefix-arg - "Force delete branch?" - "Delete branch? ")) - (magit-delete-branch info current-prefix-arg))) - ((remote) - (when (yes-or-no-p "Remove remote? ") - (magit-remove-remote info))))) - -(defun magit-move-item () - (interactive) - (magit-section-action (item info "move") - ((branch) - (call-interactively 'magit-move-branch)) - ((remote) - (call-interactively 'magit-rename-remote)))) - -(defmacro magit-visiting-file-item (&rest body) - `(let ((marker (save-window-excursion - (magit-visit-file-item) - (set-marker (make-marker) (point))))) - (save-excursion - (with-current-buffer (marker-buffer marker) - (goto-char marker) - ,@body)))) - -(defun magit-add-change-log-entry-no-option (&optional other-window) - "Add a change log entry for current change. -With a prefix argument, edit in other window. -The name of the change log file is set by variable change-log-default-name." - (interactive "P") - (if other-window - (magit-visiting-file-item (add-change-log-entry-other-window)) - (magit-visiting-file-item (add-change-log-entry)))) - -(defun magit-add-change-log-entry-other-window () - (interactive) - (magit-visiting-file-item (call-interactively 'add-change-log-entry-other-window))) - -(eval-after-load 'dired-x - '(defun magit-dired-jump (&optional other-window) - "Visit current item. -With a prefix argument, visit in other window." - (interactive "P") - (require 'dired-x) - (magit-section-action (item info "dired-jump") - ((untracked file) - (dired-jump other-window (file-truename info))) - ((diff) - (dired-jump other-window (file-truename (magit-diff-item-file item)))) - ((hunk) - (dired-jump other-window - (file-truename (magit-diff-item-file - (magit-hunk-item-diff item)))))))) - -(defun magit-visit-file-item (&optional other-window) - "Visit current file associated with item. -With a prefix argument, visit in other window." - (interactive "P") - (magit-section-action (item info "visit-file") - ((untracked file) - (funcall - (if other-window 'find-file-other-window 'find-file) - info)) - ((diff) - (let ((file (magit-diff-item-file item))) - (cond ((not (file-exists-p file)) - (error "Can't visit deleted file: %s" file)) - ((file-directory-p file) - (magit-status file)) - (t - (funcall - (if other-window 'find-file-other-window 'find-file) - file))))) - ((hunk) - (let ((file (magit-diff-item-file (magit-hunk-item-diff item))) - (line (magit-hunk-item-target-line item))) - (if (not (file-exists-p file)) - (error "Can't visit deleted file: %s" file)) - (funcall - (if other-window 'find-file-other-window 'find-file) - file) - (goto-char (point-min)) - (forward-line (1- line)))))) - -(defun magit-visit-item (&optional other-window) - "Visit current item. -With a prefix argument, visit in other window." - (interactive "P") - (magit-section-action (item info "visit") - ((untracked file) - (call-interactively 'magit-visit-file-item)) - ((diff) - (call-interactively 'magit-visit-file-item)) - ((hunk) - (call-interactively 'magit-visit-file-item)) - ((commit) - (magit-show-commit info nil nil 'select)) - ((stash) - (magit-show-stash info) - (pop-to-buffer magit-stash-buffer-name)) - ((branch) - (magit-checkout info)) - ((longer) - (magit-log-show-more-entries ())))) - -(defun magit-show-item-or-scroll-up () - (interactive) - (magit-section-action (item info) - ((commit) - (magit-show-commit info #'scroll-up)) - ((stash) - (magit-show-stash info #'scroll-up)) - (t - (scroll-up)))) - -(defun magit-show-item-or-scroll-down () - (interactive) - (magit-section-action (item info) - ((commit) - (magit-show-commit info #'scroll-down)) - ((stash) - (magit-show-stash info #'scroll-down)) - (t - (scroll-down)))) - -(defun magit-mark-item (&optional unmark) - (interactive "P") - (if unmark - (magit-set-marked-commit nil) - (magit-section-action (item info "mark") - ((commit) - (magit-set-marked-commit (if (eq magit-marked-commit info) - nil - info)))))) - -(defun magit-describe-item () - (interactive) - (let ((section (magit-current-section))) - (message "Section: %s %s-%s %S %S %S" - (magit-section-type section) - (magit-section-beginning section) - (magit-section-end section) - (magit-section-title section) - (magit-section-info section) - (magit-section-context-type section)))) - -(defun magit-copy-item-as-kill () - "Copy sha1 of commit at point into kill ring." - (interactive) - (magit-section-action (item info "copy") - ((commit) - (kill-new info) - (message "%s" info)))) - -(eval-when-compile (require 'server)) - -(defun magit-server-running-p () - "Test whether server is running (works with < 23 as well). - -Return values: - nil the server is definitely not running. - t the server seems to be running. - something else we cannot determine whether it's running without using - commands which may have to wait for a long time." - (require 'server) - (if (functionp 'server-running-p) - (server-running-p) - (condition-case nil - (if server-use-tcp - (with-temp-buffer - (insert-file-contents-literally (expand-file-name server-name server-auth-dir)) - (or (and (looking-at "127\\.0\\.0\\.1:[0-9]+ \\([0-9]+\\)") - (assq 'comm - (process-attributes - (string-to-number (match-string 1)))) - t) - :other)) - (delete-process - (make-network-process - :name "server-client-test" :family 'local :server nil :noquery t - :service (expand-file-name server-name server-socket-dir))) - t) - (file-error nil)))) - -(defun magit-interactive-rebase () - "Start a git rebase -i session, old school-style." - (interactive) - (unless (magit-server-running-p) - (server-start)) - (let* ((section (get-text-property (point) 'magit-section)) - (commit (and (member 'commit (magit-section-context-type section)) - (magit-section-info section))) - (old-editor (getenv "GIT_EDITOR"))) - (setenv "GIT_EDITOR" (concat (locate-file "emacsclient" exec-path) - " -s " server-name)) - (unwind-protect - (magit-run-git-async "rebase" "-i" - (or (and commit (concat commit "^")) - (magit-read-rev "Interactively rebase to" (magit-guess-branch)))) - (if old-editor - (setenv "GIT_EDITOR" old-editor))))) - -(define-derived-mode magit-branch-manager-mode magit-mode "Magit Branch" - "Magit Branches") - -(defun magit-quit-window (&optional kill-buffer) - "Bury the buffer and delete its window. With a prefix argument, kill the -buffer instead." - (interactive "P") - (quit-window kill-buffer (selected-window))) - -(defun magit--branch-name-at-point () - "Get the branch name in the line at point." - (let ((branch (magit-section-info (magit-current-section)))) - (or branch (error "No branch at point")))) - -(defun magit--branches-for-remote-repo (remote) - "Return a list of remote branch names for REMOTE. -These are the branch names with the remote name stripped." - (remq nil - (mapcar (lambda (line) - (save-match-data - (if (and (not (string-match-p " -> " line)) - (string-match (concat "^ +" remote "/\\([^ $]+\\)") - line)) - (match-string 1 line)))) - (magit-git-lines "branch" "-r")))) - -(defvar magit-branches-buffer-name "*magit-branches*") - -(defun magit--is-branch-at-point-remote () - "Return non-nil if the branch at point is a remote tracking branch" - (magit-remote-part-of-branch (magit--branch-name-at-point))) - -(defun magit-remote-part-of-branch (branch) - (when (string-match-p "^\\(?:refs/\\)?remotes\\/" branch) - (loop for remote in (magit-git-lines "remote") - when (string-match-p (format "^\\(?:refs/\\)?remotes\\/%s\\/" (regexp-quote remote)) branch) return remote))) - -(defun magit-branch-no-remote (branch) - (let ((remote (magit-remote-part-of-branch branch))) - (if remote - (progn - ;; This has to match if remote is non-nil - (assert (string-match (format "^\\(?:refs/\\)?remotes\\/%s\\/\\(.*\\)" (regexp-quote remote)) branch) - 'show-args "Unexpected string-match failure: %s %s") - (match-string 1 branch)) - branch))) - -(defun magit-wash-branch-line (&optional remote-name) - (looking-at (concat - "^\\([ *] \\)" ; 1: current branch marker - "\\(.+?\\) +" ; 2: branch name - - "\\(?:" - - "\\([0-9a-fA-F]+\\)" ; 3: sha1 - " " - "\\(?:\\[" - "\\([^:\n]+?\\)" ; 4: tracking (non-greedy + to avoid matching \n) - "\\(?:: \\)?" - "\\(?:ahead \\([0-9]+\\)\\)?" ; 5: ahead - "\\(?:, \\)?" - "\\(?:behind \\([0-9]+\\)\\)?" ; 6: behind - "\\] \\)?" - "\\(?:.*\\)" ; message - - "\\|" ; or - - "-> " ; the pointer to - "\\(.+\\)" ; 7: a ref - - "\\)\n")) - - (let* ((current-string (match-string 1)) - (branch (match-string 2)) - (sha1 (match-string 3)) - (tracking (match-string 4)) - (ahead (match-string 5)) - (behind (match-string 6)) - (other-ref (match-string 7)) - (current (string-match-p "^\\*" current-string))) - - ; the current line is deleted before being reconstructed - (delete-region (point) - (line-beginning-position 2)) - - (magit-with-section branch 'branch - (magit-set-section-info branch) - (insert-before-markers - ; sha1 - (propertize (or sha1 - (make-string magit-sha1-abbrev-length ? )) - 'face 'magit-log-sha1) - " " - ; current marker - (if current - "# " - " ") - ; branch name - (apply 'propertize (magit-branch-no-remote branch) - (if current - '(face magit-branch))) - ; other ref that this branch is pointing to - (if other-ref - (concat " -> " (substring other-ref (+ 1 (length remote-name)))) - "") - ; tracking information - (if (and tracking - (equal (magit-remote-branch-for branch t) - (concat "refs/remotes/" tracking))) - (concat " [" - ; getting rid of the tracking branch name if it is the same as the branch name - (let* ((tracking-remote (magit-get "branch" branch "remote")) - (tracking-branch (substring tracking (+ 1 (length tracking-remote))))) - (propertize (if (string= branch tracking-branch) - (concat "@ " tracking-remote) - (concat tracking-branch " @ " tracking-remote)) - 'face 'magit-log-head-label-remote)) - ; ahead/behind information - (if (or ahead - behind) - ": " - "") - (if ahead - (concat "ahead " - (propertize ahead - 'face (if current - 'magit-branch)) - (if behind - ", " - "")) - "") - (if behind - (concat "behind " - (propertize behind - 'face 'magit-log-head-label-remote)) - "") - "]") - "") - "\n")))) - -(defun magit-wash-remote-branches-group (group) - (let* ((remote-name (first group)) - (url (magit-get "remote" remote-name "url")) - (push-url (magit-get "remote" remote-name "pushurl")) - (urls (concat url (if push-url - (concat ", "push-url) - ""))) - (marker (second group))) - - (magit-with-section (concat "remote:" remote-name) 'remote - (magit-set-section-info remote-name) - (insert-before-markers (propertize (format "%s (%s):" remote-name urls) 'face 'magit-section-title) "\n") - (magit-wash-branches-between-point-and-marker marker remote-name)) - (insert-before-markers "\n"))) - -(defun magit-wash-branches-between-point-and-marker (marker &optional remote-name) - (save-restriction - (narrow-to-region (point) marker) - (magit-wash-sequence - (if remote-name - (apply-partially 'magit-wash-branch-line remote-name) - #'magit-wash-branch-line)))) - -(defun magit-wash-branches () - ; get the names of the remotes - (let* ((remotes (magit-git-lines "remote")) - ; get the location of remotes in the buffer - (markers - (append (mapcar (lambda (remote) - (save-excursion - (when (search-forward-regexp - (concat "^ remotes\\/" remote) nil t) - (beginning-of-line) - (point-marker)))) - remotes) - (list (save-excursion - (goto-char (point-max)) - (point-marker))))) - ; list of remote elements to display in the buffer - (remote-groups (loop for remote in remotes - for end-markers on (cdr markers) - for marker = (loop for x in end-markers thereis x) - collect (list remote marker)))) - - ; actual displaying of information - (magit-with-section "local" nil - (insert-before-markers (propertize "Local:" 'face 'magit-section-title) "\n") - (magit-set-section-info ".") - (magit-wash-branches-between-point-and-marker - (loop for x in markers thereis x))) - - (insert-before-markers "\n") - - (mapc 'magit-wash-remote-branches-group remote-groups) - - ; make sure markers point to nil so that they can be garbage collected - (mapc (lambda (marker) - (when marker - (set-marker marker nil))) - markers))) - -(defun magit-refresh-branch-manager () - (magit-create-buffer-sections - (magit-git-section "branches" nil 'magit-wash-branches - "branch" - "-vva" - (format "--abbrev=%s" magit-sha1-abbrev-length)))) - -(magit-define-command branch-manager () - (interactive) - (let ((topdir (magit-get-top-dir default-directory))) - (magit-buffer-switch magit-branches-buffer-name) - (magit-mode-init topdir 'magit-branch-manager-mode #'magit-refresh-branch-manager))) - -(defun magit-change-what-branch-tracks () - "Change which remote branch the current branch tracks." - (interactive) - (if (magit--is-branch-at-point-remote) - (error "Cannot modify a remote branch")) - (let* ((local-branch (magit--branch-name-at-point)) - (new-tracked (magit-read-rev "Change tracked branch to" - nil - (lambda (ref) - (not (string-match-p "refs/remotes/" - ref))))) - new-remote new-branch) - (unless (string= (or new-tracked "") "") - (cond (;; Match refs that are unknown in the local repository if - ;; `magit-remote-ref-format' is set to - ;; `name-then-remote'. Can be useful if you want to - ;; create a new branch in a remote repository. - (string-match "^\\([^ ]+\\) +(\\(.+\\))$" ; 1: branch name; 2: remote name - new-tracked) - (setq new-remote (match-string 2 new-tracked) - new-branch (concat "refs/heads/" (match-string 1 new-tracked)))) - ((string-match "^\\(?:refs/remotes/\\)?\\([^/]+\\)/\\(.+\\)" ; 1: remote name; 2: branch name - new-tracked) - (setq new-remote (match-string 1 new-tracked) - new-branch (concat "refs/heads/" (match-string 2 new-tracked)))) - (t (error "Cannot parse the remote and branch name")))) - (magit-set new-remote "branch" local-branch "remote") - (magit-set new-branch "branch" local-branch "merge") - (magit-branch-manager) - (if (string= (magit-get-current-branch) local-branch) - (magit-refresh-buffer (magit-find-status-buffer default-directory))))) - -(defvar magit-ediff-file) - -(defun magit-interactive-resolve (file) - (require 'ediff) - (let ((merge-status (magit-git-string "ls-files" "-u" "--" file)) - (base-buffer (generate-new-buffer (concat file ".base"))) - (our-buffer (generate-new-buffer (concat file ".current"))) - (their-buffer (generate-new-buffer (concat file ".merged"))) - (windows (current-window-configuration))) - (if (null merge-status) - (error "Cannot resolve %s" file)) - (with-current-buffer base-buffer - (if (string-match "^[0-9]+ [0-9a-f]+ 1" merge-status) - (insert (magit-git-output `("cat-file" "blob" ,(concat ":1:" file)))))) - (with-current-buffer our-buffer - (if (string-match "^[0-9]+ [0-9a-f]+ 2" merge-status) - (insert (magit-git-output `("cat-file" "blob" ,(concat ":2:" file))))) - (let ((buffer-file-name file)) - (normal-mode))) - (with-current-buffer their-buffer - (if (string-match "^[0-9]+ [0-9a-f]+ 3" merge-status) - (insert (magit-git-output `("cat-file" "blob" ,(concat ":3:" file))))) - (let ((buffer-file-name file)) - (normal-mode))) - ;; We have now created the 3 buffer with ours, theirs and the ancestor files - (with-current-buffer (ediff-merge-buffers-with-ancestor our-buffer their-buffer base-buffer) - (make-local-variable 'magit-ediff-file) - (setq magit-ediff-file file) - (make-local-variable 'magit-ediff-windows) - (setq magit-ediff-windows windows) - (make-local-variable 'ediff-quit-hook) - (add-hook 'ediff-quit-hook - (lambda () - (let ((buffer-A ediff-buffer-A) - (buffer-B ediff-buffer-B) - (buffer-C ediff-buffer-C) - (buffer-Ancestor ediff-ancestor-buffer) - (file magit-ediff-file) - (file-buffer) - (windows magit-ediff-windows)) - (ediff-cleanup-mess) - (find-file file) - (setq file-buffer (current-buffer)) - (erase-buffer) - (insert-buffer-substring buffer-C) - (kill-buffer buffer-A) - (kill-buffer buffer-B) - (kill-buffer buffer-C) - (when (bufferp buffer-Ancestor) (kill-buffer buffer-Ancestor)) - (set-window-configuration windows) - (magit-save-some-buffers - "Conflict resolution finished; you may save the buffer" - (lambda () (eq (current-buffer) file-buffer))))))))) - -(defun magit-interactive-resolve-item () - (interactive) - (magit-section-action (item info "resolv") - ((diff) - (magit-interactive-resolve (cadr info))))) - -(defun magit-submodule-update (&optional init) - "Update the submodule of the current git repository - -With a prefix arg, do a submodule update --init" - (interactive "P") - (let ((default-directory (magit-get-top-dir default-directory))) - (apply #'magit-run-git-async "submodule" "update" (if init '("--init") ())))) - -(defun magit-submodule-update-init () - "Update and init the submodule of the current git repository." - (interactive) - (magit-submodule-update t)) - -(defun magit-submodule-init () - "Initialize the submodules" - (interactive) - (let ((default-directory (magit-get-top-dir default-directory))) - (magit-run-git-async "submodule" "init"))) - -(defun magit-submodule-sync () - "Synchronizes submodules' remote URL configuration" - (interactive) - (let ((default-directory (magit-get-top-dir default-directory))) - (magit-run-git-async "submodule" "sync"))) - -(defun magit-run-git-gui () - "Run `git gui' for the current git repository" - (interactive) - (let* ((default-directory (magit-get-top-dir default-directory))) - (magit-start-process "Git Gui" nil magit-git-executable "gui"))) - -(defun magit-run-gitk () - "Run `gitk --all' for the current git repository" - (interactive) - (let ((default-directory (magit-get-top-dir default-directory))) - (cond - ((eq system-type 'windows-nt) - ;; Gitk is a shell script, and Windows doesn't know how to - ;; "execute" it. The Windows version of Git comes with an - ;; implementation of "sh" and everything else it needs, but - ;; Windows users might not have added the directory where it's - ;; installed to their path - (let ((git-bin-dir (file-name-directory magit-gitk-executable)) - (exec-path exec-path) - (process-environment process-environment)) - (when git-bin-dir - ;; Adding it onto the end so that anything the user - ;; specified will get tried first. Emacs looks in - ;; exec-path; PATH is the environment variable inherited by - ;; the process. I need to change both. - (setq exec-path (append exec-path (list git-bin-dir))) - (push (format "PATH=%s;%s" - (getenv "PATH") - (replace-regexp-in-string "/" "\\\\" git-bin-dir)) - process-environment)) - (magit-start-process "Gitk" nil "sh" magit-gitk-executable "--all"))) - (t - (magit-start-process "Gitk" nil magit-gitk-executable "--all"))))) - -(defun magit-load-config-extensions () - "Try to load magit extensions that are defined at git config -layer. This can be added to `magit-mode-hook' for example" - (dolist (ext (magit-get-all "magit.extension")) - (let ((sym (intern (format "magit-%s-mode" ext)))) - (when (and (fboundp sym) - (not (eq sym 'magit-wip-save-mode))) - (funcall sym 1))))) - -(provide 'magit) - -;; rest of magit core -(require 'magit-key-mode) -(require 'magit-bisect) - -;;; magit.el ends here diff --git a/elpa/magit-1.2.0/magit.el-e b/elpa/magit-1.2.0/magit.el-e deleted file mode 100644 index 5923afc1..00000000 --- a/elpa/magit-1.2.0/magit.el-e +++ /dev/null @@ -1,6001 +0,0 @@ -;;; magit.el --- control Git from Emacs - -;; Copyright (C) 2010 Aaron Culich. -;; Copyright (C) 2010 Alan Falloon. -;; Copyright (C) 2008, 2010 Alex Ott. -;; Copyright (C) 2008, 2009, 2010 Alexey Voinov. -;; Copyright (C) 2010 Ben Walton. -;; Copyright (C) 2010 Chris Bernard. -;; Copyright (C) 2010 Christian Kluge. -;; Copyright (C) 2008 Daniel Farina. -;; Copyright (C) 2010 David Abrahams. -;; Copyright (C) 2009 David Wallin. -;; Copyright (C) 2009, 2010 Hannu Koivisto. -;; Copyright (C) 2009 Ian Eure. -;; Copyright (C) 2009 Jesse Alama. -;; Copyright (C) 2009 John Wiegley. -;; Copyright (C) 2010 Leo. -;; Copyright (C) 2008, 2009 Marcin Bachry. -;; Copyright (C) 2008, 2009 Marius Vollmer. -;; Copyright (C) 2010 Mark Hepburn. -;; Copyright (C) 2010 Moritz Bunkus. -;; Copyright (C) 2010 Nathan Weizenbaum. -;; Copyright (C) 2010 Oscar Fuentes. -;; Copyright (C) 2009 Pavel Holejsovsky. -;; Copyright (C) 2011-2012 Peter J Weisberg -;; Copyright (C) 2009, 2010 Phil Jackson. -;; Copyright (C) 2010 Philip Weaver. -;; Copyright (C) 2010 Ramkumar Ramachandra. -;; Copyright (C) 2010 Remco van 't Veer. -;; Copyright (C) 2009 René Stadler. -;; Copyright (C) 2010 Robin Green. -;; Copyright (C) 2010 Roger Crew. -;; Copyright (C) 2009, 2010, 2011 Rémi Vanicat. -;; Copyright (C) 2010 Sean Bryant. -;; Copyright (C) 2009, 2011 Steve Purcell. -;; Copyright (C) 2010 Timo Juhani Lindfors. -;; Copyright (C) 2010, 2011 Yann Hodique. -;; Copyright (C) 2010 Ævar Arnfjörð Bjarmason. -;; Copyright (C) 2010 Óscar Fuentes. - -;; Original Author: Marius Vollmer -;; Former Maintainer: Phil Jackson -;; Maintenance Group: https://github.com/organizations/magit/teams/53130 -;; Currently composed of: -;; - Phil Jackson -;; - Peter J Weisberg -;; - Yann Hodique -;; - Rémi Vanicat -;; Version: @GIT_DEV_VERSION@ -;; Keywords: tools - -;; -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see . - -;;; Commentary: - -;; Invoking the magit-status function will show a buffer with the -;; status of the current git repository and its working tree. That -;; buffer offers key bindings for manipulating the status in simple -;; ways. -;; -;; The status buffer mainly shows the difference between the working -;; tree and the index, and the difference between the index and the -;; current HEAD. You can add individual hunks from the working tree -;; to the index, and you can commit the index. -;; -;; See the Magit User Manual for more information. - -;;; Code: - -(eval-when-compile (require 'cl)) -(require 'log-edit) -(require 'easymenu) -(require 'diff-mode) - -;; Silences byte-compiler warnings -(eval-and-compile - (unless (fboundp 'declare-function) (defmacro declare-function (&rest args)))) - -(eval-when-compile (require 'view)) -(declare-function view-mode 'view) -(eval-when-compile (require 'iswitchb)) -(eval-when-compile (require 'ido)) -(eval-when-compile (require 'ediff)) - -;; Dummy to be used by the defcustoms when first loading the file. -(eval-when (load eval) - (defalias 'magit-set-variable-and-refresh 'set-default)) - -;;; Code: -(defgroup magit nil - "Controlling Git from Emacs." - :prefix "magit-" - :group 'tools) - -(defcustom magit-git-executable "git" - "The name of the Git executable." - :group 'magit - :type 'string) - -(defcustom magit-gitk-executable (concat (file-name-directory magit-git-executable) - "gitk") - "The name of the Gitk executable." - :group 'magit - :type 'string) - -(defcustom magit-git-standard-options '("--no-pager") - "Standard options when running Git." - :group 'magit - :type '(repeat string)) - -(defcustom magit-repo-dirs nil - "Directories containing Git repositories. -Magit will look into these directories for Git repositories and -offer them as choices for `magit-status'." - :group 'magit - :type '(repeat string)) - -(defcustom magit-repo-dirs-depth 3 - "The maximum depth to look for Git repos. -When looking for a Git repository below the directories in `magit-repo-dirs', -Magit will only descend this many levels deep." - :group 'magit - :type 'integer) - -(defcustom magit-set-upstream-on-push nil - "Non-nil means that `magit-push' may use --set-upstream when pushing a branch. -This only applies if the branch does not have an upstream set yet. -Setting this to t will ask if --set-upstream should be used. -Setting it to 'dontask will always use --set-upstream. -Setting it to 'refuse will refuse to push unless a remote branch has already been set. - ---set-upstream is supported with git > 1.7.0" - :group 'magit - :type '(choice (const :tag "Never" nil) - (const :tag "Ask" t) - (const :tag "Refuse" refuse) - (const :tag "Always" dontask))) - -(defcustom magit-save-some-buffers t - "Non-nil means that \\[magit-status] will save modified buffers before running. -Setting this to t will ask which buffers to save, setting it to 'dontask will -save all modified buffers without asking." - :group 'magit - :type '(choice (const :tag "Never" nil) - (const :tag "Ask" t) - (const :tag "Save without asking" dontask))) - -(defcustom magit-save-some-buffers-predicate - 'magit-save-buffers-predicate-tree-only - "A predicate function to decide whether to save a buffer. - -Used by function `magit-save-some-buffers' when the variable of -the same name is non-nil." - - :group 'magit - :type '(radio (function-item magit-save-buffers-predicate-tree-only) - (function-item magit-save-buffers-predicate-all) - (function :tag "Other"))) - -(defcustom magit-default-tracking-name-function - 'magit-default-tracking-name-remote-plus-branch - "Specifies the function to use to generate default tracking branch names -when doing a \\[magit-checkout]. - -The default is magit-default-tracking-name-remote-plus-branch, -which generates a tracking name of the form 'REMOTE-BRANCHNAME'." - :group 'magit - :type '(radio (function-item magit-default-tracking-name-remote-plus-branch) - (function-item magit-default-tracking-name-branch-only) - (function :tag "Other"))) - -(defcustom magit-commit-all-when-nothing-staged 'ask - "Determines what \\[magit-log-edit] does when nothing is staged. -Setting this to nil will make it do nothing, setting it to t will -arrange things so that the actual commit command will use the \"--all\" option, -setting it to 'ask will first ask for confirmation whether to do this, -and setting it to 'ask-stage will cause all changes to be staged, -after a confirmation." - :group 'magit - :type '(choice (const :tag "No" nil) - (const :tag "Always" t) - (const :tag "Ask" ask) - (const :tag "Ask to stage everything" ask-stage))) - -(defcustom magit-commit-signoff nil - "Add the \"Signed-off-by:\" line when committing." - :group 'magit - :type 'boolean) - -(defcustom magit-sha1-abbrev-length 7 - "The number of digits to show when a sha1 is displayed in abbreviated form." - :group 'magit - :type 'integer) - -(defcustom magit-log-cutoff-length 100 - "The maximum number of commits to show in the log and whazzup buffers." - :group 'magit - :type 'integer) - -(defcustom magit-log-infinite-length 99999 - "Number of log used to show as maximum for `magit-log-cutoff-length'." - :group 'magit - :type 'integer) - -(defcustom magit-log-auto-more nil - "Insert more log entries automatically when moving past the last entry. - -Only considered when moving past the last entry with -`magit-goto-*-section' commands." - :group 'magit - :type 'boolean) - -(defcustom magit-process-popup-time -1 - "Popup the process buffer if a command takes longer than this many seconds." - :group 'magit - :type '(choice (const :tag "Never" -1) - (const :tag "Immediately" 0) - (integer :tag "After this many seconds"))) - -(defcustom magit-revert-item-confirm t - "Require acknowledgment before reverting an item." - :group 'magit - :type 'boolean) - -(defcustom magit-log-edit-confirm-cancellation nil - "Require acknowledgment before canceling the log edit buffer." - :group 'magit - :type 'boolean) - -(defcustom magit-remote-ref-format 'branch-then-remote - "What format to use for autocompleting refs, in pariticular for remotes. - -Autocompletion is used by functions like `magit-checkout', -`magit-interactive-rebase' and others which offer branch name -completion. - -The value 'name-then-remote means remotes will be of the -form \"name (remote)\", while the value 'remote-slash-name -means that they'll be of the form \"remote/name\". I.e. something that's -listed as \"remotes/upstream/next\" by \"git branch -l -a\" -will be \"upstream/next\"." - :group 'magit - :type '(choice (const :tag "name (remote)" branch-then-remote) - (const :tag "remote/name" remote-slash-branch))) - -(defcustom magit-process-connection-type (not (eq system-type 'cygwin)) - "Connection type used for the git process. - -If nil, use pipes: this is usually more efficient, and works on Cygwin. -If t, use ptys: this enables magit to prompt for passphrases when needed." - :group 'magit - :type '(choice (const :tag "pipe" nil) - (const :tag "pty" t))) - -(defcustom magit-completing-read-function 'magit-builtin-completing-read - "Function to be called when requesting input from the user." - :group 'magit - :type '(radio (function-item magit-iswitchb-completing-read) - (function-item magit-ido-completing-read) - (function-item magit-builtin-completing-read) - (function :tag "Other"))) - -(defcustom magit-create-branch-behaviour 'at-head - "Where magit will create a new branch if not supplied a branchname or ref. - -The value 'at-head means a new branch will be created at the tip -of your current branch, while the value 'at-point means magit -will try to find a valid reference at point..." - :group 'magit - :type '(choice (const :tag "at HEAD" at-head) - (const :tag "at point" at-point))) - -(defcustom magit-status-buffer-switch-function 'pop-to-buffer - "Function for `magit-status' to use for switching to the status buffer. - -The function is given one argument, the status buffer." - :group 'magit - :type '(radio (function-item switch-to-buffer) - (function-item pop-to-buffer) - (function :tag "Other"))) - -(defcustom magit-rewrite-inclusive t - "Whether magit includes the selected base commit in a rewrite operation. - -t means both the selected commit as well as any subsequent -commits will be rewritten. This is magit's default behaviour, -equivalent to 'git rebase -i ${REV}~1' - - A'---B'---C'---D' - ^ - -nil means the selected commit will be literally used as 'base', -so only subsequent commits will be rewritten. This is consistent -with git-rebase, equivalent to 'git rebase -i ${REV}', yet more -cumbersome to use from the status buffer. - - A---B'---C'---D' - ^" - :group 'magit - :type '(choice (const :tag "Always" t) - (const :tag "Never" nil) - (const :tag "Ask" ask))) - -(defcustom magit-highlight-whitespace t - "Specifies where to highlight whitespace errors. -See `magit-highlight-trailing-whitespace', -`magit-highlight-indentation'. The symbol t means in all diffs, -'status means only in the status buffer, and nil means nowhere." - :group 'magit - :type '(choice (const :tag "Always" t) - (const :tag "Never" nil) - (const :tag "In status buffer" status)) - :set 'magit-set-variable-and-refresh) - -(defcustom magit-highlight-trailing-whitespace t - "Highlight whitespace at the end of a line in diffs. -Used only when `magit-highlight-whitespace' is non-nil." - :group 'magit - :type 'boolean - :set 'magit-set-variable-and-refresh) - -(defcustom magit-highlight-indentation nil - "Highlight the \"wrong\" indentation style. -Used only when `magit-highlight-whitespace' is non-nil. - -The value is a list of cons cells. The car is a regular -expression, and the cdr is the value that applies to repositories -whose directory matches the regular expression. If more than one -item matches, then the *last* item in the list applies. So, the -default value should come first in the list. - -If the value is `tabs', highlight indentation with tabs. If the -value is an integer, highlight indentation with at least that -many spaces. Otherwise, highlight neither." - :group 'magit - :type `(repeat (cons (string :tag "Directory regexp") - (choice (const :tag "Tabs" tabs) - (integer :tag "Spaces" :value ,tab-width) - (const :tag "Neither" nil)))) - :set 'magit-set-variable-and-refresh) - -(defcustom magit-diff-refine-hunk nil - "Show fine (word-granularity) differences within diff hunks. - -There are three possible settings: - - nil means to never show fine differences - - t means to only show fine differences for the currently - selected diff hunk - - `all' means to always show fine differences for all displayed diff hunks" - :group 'magit - :type '(choice (const :tag "Never" nil) - (const :tag "Selected only" t) - (const :tag "All" all)) - :set 'magit-set-variable-and-refresh) - -(defvar magit-current-indentation nil - "Indentation highlight used in the current buffer. -This is calculated from `magit-highlight-indentation'.") -(make-variable-buffer-local 'magit-current-indentation) - -(defgroup magit-faces nil - "Customize the appearance of Magit." - :prefix "magit-" - :group 'faces - :group 'magit) - -(defface magit-header - '((t :inherit header-line)) - "Face for generic header lines. - -Many Magit faces inherit from this one by default." - :group 'magit-faces) - -(defface magit-section-title - '((t :inherit magit-header)) - "Face for section titles." - :group 'magit-faces) - -(defface magit-branch - '((t :inherit magit-header)) - "Face for the current branch." - :group 'magit-faces) - -(defface magit-diff-file-header - '((t :inherit diff-file-header)) - "Face for diff file header lines." - :group 'magit-faces) - -(defface magit-diff-hunk-header - '((t :inherit diff-hunk-header)) - "Face for diff hunk header lines." - :group 'magit-faces) - -(defface magit-diff-add - '((t :inherit diff-added)) - "Face for lines in a diff that have been added." - :group 'magit-faces) - -(defface magit-diff-none - '((t :inherit diff-context)) - "Face for lines in a diff that are unchanged." - :group 'magit-faces) - -(defface magit-diff-del - '((t :inherit diff-removed)) - "Face for lines in a diff that have been deleted." - :group 'magit-faces) - -(defface magit-log-graph - '((((class color) (background light)) - :foreground "grey11") - (((class color) (background dark)) - :foreground "grey80")) - "Face for the graph element of the log output." - :group 'magit-faces) - -(defface magit-log-sha1 - '((((class color) (background light)) - :foreground "firebrick") - (((class color) (background dark)) - :foreground "tomato")) - "Face for the sha1 element of the log output." - :group 'magit-faces) - -(defface magit-log-message - '((t)) - "Face for the message element of the log output." - :group 'magit-faces) - -(defface magit-item-highlight - '((t :inherit highlight)) - "Face for highlighting the current item." - :group 'magit-faces) - -(defface magit-item-mark - '((t :inherit secondary-selection)) - "Face for highlighting marked item." - :group 'magit-faces) - -(defface magit-log-head-label-bisect-good - '((((class color) (background light)) - :box t - :background "light green" - :foreground "dark olive green") - (((class color) (background dark)) - :box t - :background "light green" - :foreground "dark olive green")) - "Face for good bisect refs." - :group 'magit-faces) - -(defface magit-log-head-label-bisect-bad - '((((class color) (background light)) - :box t - :background "IndianRed1" - :foreground "IndianRed4") - (((class color) (background dark)) - :box t - :background "IndianRed1" - :foreground "IndianRed4")) - "Face for bad bisect refs." - :group 'magit-faces) - -(defface magit-log-head-label-remote - '((((class color) (background light)) - :box t - :background "Grey85" - :foreground "OliveDrab4") - (((class color) (background dark)) - :box t - :background "Grey11" - :foreground "DarkSeaGreen2")) - "Face for remote branch head labels shown in log buffer." - :group 'magit-faces) - -(defface magit-log-head-label-tags - '((((class color) (background light)) - :box t - :background "LemonChiffon1" - :foreground "goldenrod4") - (((class color) (background dark)) - :box t - :background "LemonChiffon1" - :foreground "goldenrod4")) - "Face for tag labels shown in log buffer." - :group 'magit-faces) - -(defface magit-log-head-label-patches - '((((class color) (background light)) - :box t - :background "IndianRed1" - :foreground "IndianRed4") - (((class color) (background dark)) - :box t - :background "IndianRed1" - :foreground "IndianRed4")) - "Face for Stacked Git patches." - :group 'magit-faces) - -(defface magit-whitespace-warning-face - '((t :inherit trailing-whitespace)) - "Face for highlighting whitespace errors in Magit diffs." - :group 'magit-faces) - -(defvar magit-custom-options '() - "List of custom options to pass to Git. -Do not customize this (used in the `magit-key-mode' implementation).") - -(defvar magit-read-rev-history nil - "The history of inputs to `magit-read-rev'.") - -(defvar magit-buffer-internal nil - "Track associated *magit* buffers. -Do not customize this (used in the `magit-log-edit-mode' implementation -to switch back to the *magit* buffer associated with a given commit -operation after commit).") - -(defvar magit-back-navigation-history nil - "History items that will be visited by successively going \"back\".") -(make-variable-buffer-local 'magit-back-navigation-history) -(put 'magit-back-navigation-history 'permanent-local t) - -(defvar magit-forward-navigation-history nil - "History items that will be visited by successively going \"forward\".") -(make-variable-buffer-local 'magit-forward-navigation-history) -(put 'magit-forward-navigation-history 'permanent-local t) - -(defvar magit-omit-untracked-dir-contents nil - "When non-nil magit will only list an untracked directory, not its contents.") - -(defvar magit-tmp-buffer-name " *magit-tmp*") - -(defface magit-log-head-label-local - '((((class color) (background light)) - :box t - :background "Grey85" - :foreground "LightSkyBlue4") - (((class color) (background dark)) - :box t - :background "Grey13" - :foreground "LightSkyBlue1")) - "Face for local branch head labels shown in log buffer." - :group 'magit-faces) - -(defface magit-log-head-label-default - '((((class color) (background light)) - :box t - :background "Grey50") - (((class color) (background dark)) - :box t - :background "Grey50")) - "Face for unknown ref labels shown in log buffer." - :group 'magit-faces) - -(defvar magit-mode-map - (let ((map (make-keymap))) - (suppress-keymap map t) - (define-key map (kbd "n") 'magit-goto-next-section) - (define-key map (kbd "p") 'magit-goto-previous-section) - (define-key map (kbd "^") 'magit-goto-parent-section) - (define-key map (kbd "M-n") 'magit-goto-next-sibling-section) - (define-key map (kbd "M-p") 'magit-goto-previous-sibling-section) - (define-key map (kbd "TAB") 'magit-toggle-section) - (define-key map (kbd "") 'magit-expand-collapse-section) - (define-key map (kbd "1") 'magit-show-level-1) - (define-key map (kbd "2") 'magit-show-level-2) - (define-key map (kbd "3") 'magit-show-level-3) - (define-key map (kbd "4") 'magit-show-level-4) - (define-key map (kbd "M-1") 'magit-show-level-1-all) - (define-key map (kbd "M-2") 'magit-show-level-2-all) - (define-key map (kbd "M-3") 'magit-show-level-3-all) - (define-key map (kbd "M-4") 'magit-show-level-4-all) - (define-key map (kbd "M-h") 'magit-show-only-files) - (define-key map (kbd "M-H") 'magit-show-only-files-all) - (define-key map (kbd "M-s") 'magit-show-level-4) - (define-key map (kbd "M-S") 'magit-show-level-4-all) - (define-key map (kbd "g") 'magit-refresh) - (define-key map (kbd "G") 'magit-refresh-all) - (define-key map (kbd "?") 'magit-describe-item) - (define-key map (kbd "!") 'magit-key-mode-popup-running) - (define-key map (kbd ":") 'magit-git-command) - (define-key map (kbd "C-x 4 a") 'magit-add-change-log-entry-other-window) - (define-key map (kbd "L") 'magit-add-change-log-entry-no-option) - (define-key map (kbd "RET") 'magit-visit-item) - (define-key map (kbd "SPC") 'magit-show-item-or-scroll-up) - (define-key map (kbd "DEL") 'magit-show-item-or-scroll-down) - (define-key map (kbd "C-w") 'magit-copy-item-as-kill) - (define-key map (kbd "R") 'magit-rebase-step) - (define-key map (kbd "t") 'magit-key-mode-popup-tagging) - (define-key map (kbd "r") 'magit-key-mode-popup-rewriting) - (define-key map (kbd "P") 'magit-key-mode-popup-pushing) - (define-key map (kbd "f") 'magit-key-mode-popup-fetching) - (define-key map (kbd "b") 'magit-key-mode-popup-branching) - (define-key map (kbd "M") 'magit-key-mode-popup-remoting) - (define-key map (kbd "B") 'magit-key-mode-popup-bisecting) - (define-key map (kbd "F") 'magit-key-mode-popup-pulling) - (define-key map (kbd "l") 'magit-key-mode-popup-logging) - (define-key map (kbd "$") 'magit-display-process) - (define-key map (kbd "c") 'magit-log-edit) - (define-key map (kbd "E") 'magit-interactive-rebase) - (define-key map (kbd "e") 'magit-ediff) - (define-key map (kbd "w") 'magit-wazzup) - (define-key map (kbd "q") 'magit-quit-window) - (define-key map (kbd "m") 'magit-key-mode-popup-merging) - (define-key map (kbd "x") 'magit-reset-head) - (define-key map (kbd "v") 'magit-revert-item) - (define-key map (kbd "a") 'magit-apply-item) - (define-key map (kbd "A") 'magit-cherry-pick-item) - (define-key map (kbd "d") 'magit-diff-working-tree) - (define-key map (kbd "D") 'magit-diff) - (define-key map (kbd "-") 'magit-diff-smaller-hunks) - (define-key map (kbd "+") 'magit-diff-larger-hunks) - (define-key map (kbd "0") 'magit-diff-default-hunks) - (define-key map (kbd "h") 'magit-toggle-diff-refine-hunk) - map)) - -(defvar magit-commit-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-b") 'magit-show-commit-backward) - (define-key map (kbd "C-c C-f") 'magit-show-commit-forward) - map)) - -(defvar magit-status-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "s") 'magit-stage-item) - (define-key map (kbd "S") 'magit-stage-all) - (define-key map (kbd "u") 'magit-unstage-item) - (define-key map (kbd "U") 'magit-unstage-all) - (define-key map (kbd "i") 'magit-ignore-item) - (define-key map (kbd "I") 'magit-ignore-item-locally) - (define-key map (kbd ".") 'magit-mark-item) - (define-key map (kbd "=") 'magit-diff-with-mark) - (define-key map (kbd "k") 'magit-discard-item) - (define-key map (kbd "C") 'magit-add-log) - (define-key map (kbd "X") 'magit-reset-working-tree) - (define-key map (kbd "z") 'magit-key-mode-popup-stashing) - map)) - -(eval-after-load 'dired-x - '(define-key magit-status-mode-map [remap dired-jump] 'magit-dired-jump)) - -(defvar magit-log-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd ".") 'magit-mark-item) - (define-key map (kbd "=") 'magit-diff-with-mark) - (define-key map (kbd "e") 'magit-log-show-more-entries) - map)) - -(defvar magit-wazzup-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd ".") 'magit-mark-item) - (define-key map (kbd "=") 'magit-diff-with-mark) - (define-key map (kbd "i") 'magit-ignore-item) - map)) - -(defvar magit-branch-manager-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "c") 'magit-create-branch) - (define-key map (kbd "a") 'magit-add-remote) - (define-key map (kbd "r") 'magit-move-item) - (define-key map (kbd "k") 'magit-discard-item) - (define-key map (kbd "T") 'magit-change-what-branch-tracks) - map)) - -(defvar magit-bug-report-url - "http://github.com/magit/magit/issues") - -(defconst magit-version "@GIT_DEV_VERSION@" - "The version of Magit that you're using.") - -(defun magit-bug-report (str) - "Asks the user to submit a bug report about the error described in STR." -;; XXX - should propose more information to be included. - (message (concat - "Unknown error: %s\n" - "Please, with as much information as possible, file a bug at\n" - "%s\n" - "You are using Magit version %s.") - str magit-bug-report-url magit-version)) - -(defun magit-buffer-switch (buf) - (if (string-match "magit" (buffer-name)) - (switch-to-buffer buf) - (pop-to-buffer buf))) - -;;; Macros - -(defmacro magit-with-refresh (&rest body) - (declare (indent 0)) - `(magit-refresh-wrapper (lambda () ,@body))) - -;;; Git features - -(defvar magit-have-graph 'unset) -(defvar magit-have-decorate 'unset) -(defvar magit-have-abbrev 'unset) -(make-variable-buffer-local 'magit-have-graph) -(put 'magit-have-graph 'permanent-local t) -(make-variable-buffer-local 'magit-have-decorate) -(put 'magit-have-decorate 'permanent-local t) -(make-variable-buffer-local 'magit-have-abbrev) -(put 'magit-have-abbrev 'permanent-local t) - -(defun magit-configure-have-graph () - (if (eq magit-have-graph 'unset) - (let ((res (magit-git-exit-code "log" "--graph" "--max-count=0"))) - (setq magit-have-graph (eq res 0))))) - -(defun magit-configure-have-decorate () - (if (eq magit-have-decorate 'unset) - (let ((res (magit-git-exit-code "log" "--decorate=full" "--max-count=0"))) - (setq magit-have-decorate (eq res 0))))) - -(defun magit-configure-have-abbrev () - (if (eq magit-have-abbrev 'unset) - (let ((res (magit-git-exit-code "log" "--no-abbrev-commit" "--max-count=0"))) - (setq magit-have-abbrev (eq res 0))))) - -;;; Compatibilities - -(eval-and-compile - (defun magit-max-args-internal (function) - "Returns the maximum number of arguments accepted by FUNCTION." - (if (symbolp function) - (setq function (symbol-function function))) - (if (subrp function) - (let ((max (cdr (subr-arity function)))) - (if (eq 'many max) - most-positive-fixnum - max)) - (if (eq 'macro (car-safe function)) - (setq function (cdr function))) - (let ((arglist (if (byte-code-function-p function) - (aref function 0) - (second function)))) - (if (memq '&rest arglist) - most-positive-fixnum - (length (remq '&optional arglist)))))) - - (if (functionp 'start-file-process) - (defalias 'magit-start-process 'start-file-process) - (defalias 'magit-start-process 'start-process)) - - (unless (fboundp 'string-match-p) - (defun string-match-p (regexp string &optional start) - "Same as `string-match' except this function does not -change the match data." - (let ((inhibit-changing-match-data t)) - (string-match regexp string start)))) - - (if (fboundp 'with-silent-modifications) - (defalias 'magit-with-silent-modifications 'with-silent-modifications) - (defmacro magit-with-silent-modifications (&rest body) - "Execute body without changing `buffer-modified-p'. Also, do not -record undo information." - `(set-buffer-modified-p - (prog1 (buffer-modified-p) - (let ((buffer-undo-list t) - before-change-functions - after-change-functions) - ,@body))))) - - (if (>= (magit-max-args-internal 'delete-directory) 2) - (defalias 'magit-delete-directory 'delete-directory) - (defun magit-delete-directory (directory &optional recursive) - "Deletes a directory named DIRECTORY. If RECURSIVE is non-nil, -recursively delete all of DIRECTORY's contents as well. - -Does not follow symlinks." - (if (or (file-symlink-p directory) - (not (file-directory-p directory))) - (delete-file directory) - (if recursive - ;; `directory-files-no-dot-files-regex' borrowed from Emacs 23 - (dolist (file (directory-files directory 'full "\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) - (magit-delete-directory file recursive))) - (delete-directory directory))))) - -;;; Utilities - -(defun magit-set-variable-and-refresh (symbol value) - "Set SYMBOL to VALUE and call `magit-refresh-all'" - (set-default symbol value) - (magit-refresh-all)) - -(defun magit-iswitchb-completing-read (prompt choices &optional predicate require-match - initial-input hist def) - "iswitchb-based completing-read almost-replacement." - (require 'iswitchb) - (let ((iswitchb-make-buflist-hook - (lambda () - (setq iswitchb-temp-buflist (if (consp (first choices)) - (mapcar #'car choices) - choices))))) - (iswitchb-read-buffer prompt (or initial-input def) require-match))) - -(defun magit-ido-completing-read (prompt choices &optional predicate require-match initial-input hist def) - "ido-based completing-read almost-replacement." - (require 'ido) - (let ((selected (ido-completing-read prompt (if (consp (first choices)) - (mapcar #'car choices) - choices) - predicate require-match initial-input hist def))) - (if (consp (first choices)) - (or (cdr (assoc selected choices)) - selected) - selected))) - -(defun magit-builtin-completing-read (prompt choices &optional predicate require-match - initial-input hist def) - "Magit wrapper for standard `completing-read' function." - (completing-read (if (and def (> (length prompt) 2) - (string-equal ": " (substring prompt -2))) - (format "%s (default %s): " (substring prompt 0 -2) def) - prompt) - choices predicate require-match initial-input hist def)) - -(defun magit-completing-read (prompt choices &optional predicate require-match - initial-input hist def) - (funcall magit-completing-read-function prompt choices predicate require-match - initial-input hist def)) - -(defun magit-use-region-p () - (if (fboundp 'use-region-p) - (use-region-p) - (and transient-mark-mode mark-active))) - -(defun magit-goto-line (line) - "Like `goto-line' but doesn't set the mark." - (save-restriction - (widen) - (goto-char 1) - (forward-line (1- line)))) - -(defun magit-trim-line (str) - (if (string= str "") - nil - (if (equal (elt str (- (length str) 1)) ?\n) - (substring str 0 (- (length str) 1)) - str))) - -(defun magit-split-lines (str) - (if (string= str "") - nil - (let ((lines (nreverse (split-string str "\n")))) - (if (string= (car lines) "") - (setq lines (cdr lines))) - (nreverse lines)))) - -(defun magit-git-insert (args) - (insert (magit-git-output args))) - -(defun magit-git-output (args) - (magit-cmd-output magit-git-executable (append magit-git-standard-options args))) - -(defun magit-cmd-insert (cmd args) - (insert (magit-cmd-output cmd args))) - -(defun magit-cmd-output (cmd args) - (let ((cmd-output (with-output-to-string - (with-current-buffer standard-output - (apply #'process-file - cmd - nil (list t nil) nil - args))))) - (replace-regexp-in-string "\e\\[.*?m" "" cmd-output))) - -(defun magit-git-string (&rest args) - (magit-trim-line (magit-git-output args))) - -(defun magit-git-lines (&rest args) - (magit-split-lines (magit-git-output args))) - -(defun magit-git-exit-code (&rest args) - (apply #'process-file magit-git-executable nil nil nil - (append magit-git-standard-options args))) - -(defun magit-file-lines (file) - (when (file-exists-p file) - (with-temp-buffer - (insert-file-contents file) - (let ((rev (nreverse (split-string (buffer-string) "\n")))) - (nreverse (if (equal (car rev) "") - (cdr rev) - rev)))))) - -(defun magit-write-file-lines (file lines) - (with-temp-buffer - (dolist (l lines) - (insert l "\n")) - (write-file file))) - -(defun magit-get (&rest keys) - "Return the value of Git config entry specified by KEYS." - (magit-git-string "config" (mapconcat 'identity keys "."))) - -(defun magit-get-all (&rest keys) - "Return all values of the Git config entry specified by KEYS." - (magit-git-lines "config" "--get-all" (mapconcat 'identity keys "."))) - -(defun magit-get-boolean (&rest keys) - "Return the boolean value of Git config entry specified by KEYS." - (equal (magit-git-string "config" "--bool" (mapconcat 'identity keys ".")) - "true")) - -(defun magit-set (val &rest keys) - "Set Git config settings specified by KEYS to VAL." - (if val - (magit-git-string "config" (mapconcat 'identity keys ".") val) - (magit-git-string "config" "--unset" (mapconcat 'identity keys ".")))) - -(defun magit-remove-conflicts (alist) - (let ((dict (make-hash-table :test 'equal)) - (result nil)) - (dolist (a alist) - (puthash (car a) (cons (cdr a) (gethash (car a) dict)) - dict)) - (maphash (lambda (key value) - (if (= (length value) 1) - (push (cons key (car value)) result) - (let ((sub (magit-remove-conflicts - (mapcar (lambda (entry) - (let ((dir (directory-file-name - (substring entry 0 (- (length key)))))) - (cons (concat (file-name-nondirectory dir) "/" key) - entry))) - value)))) - (setq result (append result sub))))) - dict) - result)) - -(defun magit-git-repo-p (dir) - (file-exists-p (expand-file-name ".git" dir))) - -(defun magit-git-dir () - "Returns the .git directory for the current repository." - (concat (expand-file-name (magit-git-string "rev-parse" "--git-dir")) "/")) - -(defun magit-no-commit-p () - "Return non-nil if there is no commit in the current git repository." - (not (magit-git-string - "rev-list" "HEAD" "--max-count=1"))) - -(defun magit-list-repos* (dir level) - (if (magit-git-repo-p dir) - (list dir) - (apply #'append - (mapcar (lambda (entry) - (unless (or (string= (substring entry -3) "/..") - (string= (substring entry -2) "/.")) - (magit-list-repos* entry (+ level 1)))) - (and (file-directory-p dir) - (< level magit-repo-dirs-depth) - (directory-files dir t nil t)))))) - -(defun magit-list-repos (dirs) - (magit-remove-conflicts - (apply #'append - (mapcar (lambda (dir) - (mapcar #'(lambda (repo) - (cons (file-name-nondirectory repo) - repo)) - (magit-list-repos* dir 0))) - dirs)))) - -(defun magit-get-top-dir (cwd) - (let ((cwd (expand-file-name (file-truename cwd)))) - (when (file-directory-p cwd) - (let* ((default-directory (file-name-as-directory cwd)) - (cdup (magit-git-string "rev-parse" "--show-cdup"))) - (when cdup - (file-name-as-directory (expand-file-name cdup cwd))))))) - -(defun magit-get-ref (ref) - (magit-git-string "symbolic-ref" "-q" ref)) - -(defun magit-get-current-branch () - (let* ((head (magit-get-ref "HEAD")) - (pos (and head (string-match "^refs/heads/" head)))) - (if pos - (substring head 11) - nil))) - -(defun magit-get-remote (branch) - "Return the name of the remote for BRANCH. -If branch is nil or it has no remote, but a remote named -\"origin\" exists, return that. Otherwise, return nil." - (let ((remote (or (and branch (magit-get "branch" branch "remote")) - (and (magit-get "remote" "origin" "url") "origin")))) - (if (string= remote "") nil remote))) - -(defun magit-get-current-remote () - "Return the name of the remote for the current branch. -If there is no current branch, or no remote for that branch, -but a remote named \"origin\" is configured, return that. -Otherwise, return nil." - (magit-get-remote (magit-get-current-branch))) - -(defun magit-ref-exists-p (ref) - (= (magit-git-exit-code "show-ref" "--verify" ref) 0)) - -(defun magit-read-top-dir (dir) - "Ask the user for a Git repository. The choices offered by -auto-completion will be the repositories under `magit-repo-dirs'. -If `magit-repo-dirs' is nil or DIR is non-nill, then -autocompletion will offer directory names." - (if (and (not dir) magit-repo-dirs) - (let* ((repos (magit-list-repos magit-repo-dirs)) - (reply (magit-completing-read "Git repository: " repos))) - (file-name-as-directory - (or (cdr (assoc reply repos)) - (if (file-directory-p reply) - (expand-file-name reply) - (error "Not a repository or a directory: %s" reply))))) - (file-name-as-directory - (read-directory-name "Git repository: " - (or (magit-get-top-dir default-directory) - default-directory))))) - -(defun magit-rev-parse (ref) - "Return the SHA hash for REF." - (magit-git-string "rev-parse" ref)) - -(defun magit-ref-ambiguous-p (ref) - "Return whether or not REF is ambiguous." - ;; If REF is ambiguous, rev-parse just prints errors, - ;; so magit-git-string returns nil. - (not (magit-git-string "rev-parse" "--abbrev-ref" ref))) - -(defun magit-name-rev (rev &optional no-trim) - "Return a human-readable name for REV. -Unlike git name-rev, this will remove tags/ and remotes/ prefixes -if that can be done unambiguously (unless optional arg NO-TRIM is -non-nil). In addition, it will filter out revs involving HEAD." - (when rev - (let ((name (magit-git-string "name-rev" "--no-undefined" "--name-only" rev))) - ;; There doesn't seem to be a way of filtering HEAD out from name-rev, - ;; so we have to do it manually. - ;; HEAD-based names are too transient to allow. - (when (and (stringp name) - (string-match "^\\(.*\\" name)) - (setq name (magit-rev-parse rev))))) - (setq rev (or name rev)) - (when (string-match "^\\(?:tags\\|remotes\\)/\\(.*\\)" rev) - (let ((plain-name (match-string 1 rev))) - (unless (or no-trim (magit-ref-ambiguous-p plain-name)) - (setq rev plain-name)))) - rev))) - -(defun magit-highlight-line-whitespace () - (when (and magit-highlight-whitespace - (or (derived-mode-p 'magit-status-mode) - (not (eq magit-highlight-whitespace 'status)))) - (if (and magit-highlight-trailing-whitespace - (looking-at "^[-+].*?\\([ \t]+\\)$")) - (overlay-put (make-overlay (match-beginning 1) (match-end 1)) - 'face 'magit-whitespace-warning-face)) - (if (or (and (eq magit-current-indentation 'tabs) - (looking-at "^[-+]\\( *\t[ \t]*\\)")) - (and (integerp magit-current-indentation) - (looking-at (format "^[-+]\\([ \t]* \\{%s,\\}[ \t]*\\)" - magit-current-indentation)))) - (overlay-put (make-overlay (match-beginning 1) (match-end 1)) - 'face 'magit-whitespace-warning-face)))) - -(defun magit-put-line-property (prop val) - (put-text-property (line-beginning-position) (line-beginning-position 2) - prop val)) - -(defun magit-format-commit (commit format) - (magit-git-string "log" "--max-count=1" - (concat "--pretty=format:" format) - commit)) - -(defun magit-current-line () - (buffer-substring-no-properties (line-beginning-position) - (line-end-position))) - -(defun magit-insert-region (beg end buf) - (let ((text (buffer-substring-no-properties beg end))) - (with-current-buffer buf - (insert text)))) - -(defun magit-insert-current-line (buf) - (let ((text (buffer-substring-no-properties - (line-beginning-position) (line-beginning-position 2)))) - (with-current-buffer buf - (insert text)))) - -(defun magit-file-uptodate-p (file) - (eq (magit-git-exit-code "diff" "--quiet" "--" file) 0)) - -(defun magit-anything-staged-p () - (not (eq (magit-git-exit-code "diff" "--quiet" "--cached") 0))) - -(defun magit-everything-clean-p () - (and (not (magit-anything-staged-p)) - (eq (magit-git-exit-code "diff" "--quiet") 0))) - -(defun magit-commit-parents (commit) - (cdr (split-string (magit-git-string "rev-list" "-1" "--parents" commit)))) - -;; XXX - let the user choose the parent - -(defun magit-choose-parent-id (commit op) - (let* ((parents (magit-commit-parents commit))) - (if (> (length parents) 1) - (error "Can't %s merge commits" op) - nil))) - -;;; Revisions and ranges - -(defvar magit-current-range nil - "The range described by the current buffer. -This is only non-nil in diff and log buffers. - -This has three possible (non-nil) forms. If it's a string REF or -a singleton list (REF), then the range is from REF to the current -working directory state (or HEAD in a log buffer). If it's a -pair (START . END), then the range is START..END.") -(make-variable-buffer-local 'magit-current-range) - -(defun magit-list-interesting-refs (&optional uninteresting) - "Return interesting references as given by `git show-ref'. -Removes references matching UNINTERESTING from the -results. UNINTERESTING can be either a function taking a single -argument or a list of strings used as regexps." - (let ((refs ())) - (dolist (line (magit-git-lines "show-ref")) - (if (string-match "[^ ]+ +\\(.*\\)" line) - (let ((ref (match-string 1 line))) - (cond ((and (functionp uninteresting) - (funcall uninteresting ref))) - ((and (not (functionp uninteresting)) - (loop for i in uninteresting thereis (string-match i ref)))) - (t - (let ((fmt-ref (magit-format-ref ref))) - (when fmt-ref - (push (cons fmt-ref - (replace-regexp-in-string "^refs/heads/" - "" ref)) - refs)))))))) - (nreverse refs))) - -(defun magit-format-ref (ref) - "Convert fully-specified ref REF into its displayable form -according to `magit-remote-ref-format'" - (cond - ((null ref) - nil) - ((string-match "refs/heads/\\(.*\\)" ref) - (match-string 1 ref)) - ((string-match "refs/tags/\\(.*\\)" ref) - (format (if (eq magit-remote-ref-format 'branch-then-remote) - "%s (tag)" - "%s") - (match-string 1 ref))) - ((string-match "refs/remotes/\\([^/]+\\)/\\(.+\\)" ref) - (if (eq magit-remote-ref-format 'branch-then-remote) - (format "%s (%s)" - (match-string 2 ref) - (match-string 1 ref)) - (format "%s/%s" - (match-string 1 ref) - (match-string 2 ref)))))) - -(defun magit-tree-contents (treeish) - "Returns a list of all files under TREEISH. TREEISH can be a tree, -a commit, or any reference to one of those." - (let ((return-value nil)) - (with-temp-buffer - (magit-git-insert (list "ls-tree" "-r" treeish)) - (if (eql 0 (buffer-size)) - (error "%s is not a commit or tree." treeish)) - (goto-char (point-min)) - (while (search-forward-regexp "\t\\(.*\\)" nil 'noerror) - (push (match-string 1) return-value))) - return-value)) - -(defvar magit-uninteresting-refs '("refs/remotes/\\([^/]+\\)/HEAD$" "refs/stash")) - -(defun magit-read-file-from-rev (revision) - (magit-completing-read (format "Retrieve file from %s: " revision) - (magit-tree-contents revision) - nil - 'require-match - nil - 'magit-read-file-hist - (if buffer-file-name - (let ((topdir-length (length (magit-get-top-dir default-directory)))) - (substring (buffer-file-name) topdir-length))))) - -(defun magit-read-rev (prompt &optional default uninteresting) - (let* ((interesting-refs (magit-list-interesting-refs - (or uninteresting magit-uninteresting-refs))) - (reply (magit-completing-read (concat prompt ": ") interesting-refs - nil nil nil 'magit-read-rev-history default)) - (rev (or (cdr (assoc reply interesting-refs)) reply))) - (if (string= rev "") - nil - rev))) - -(defun magit-read-rev-range (op &optional def-beg def-end) - (let ((beg (magit-read-rev (format "%s start" op) - def-beg))) - (if (not beg) - nil - (save-match-data - (if (string-match "^\\(.+\\)\\.\\.\\(.+\\)$" beg) - (cons (match-string 1 beg) (match-string 2 beg)) - (let ((end (magit-read-rev (format "%s end" op) def-end))) - (cons beg end))))))) - -(defun magit-rev-to-git (rev) - (or rev - (error "No revision specified")) - (if (string= rev ".") - (magit-marked-commit) - rev)) - -(defun magit-rev-range-to-git (range) - (or range - (error "No revision range specified")) - (if (stringp range) - range - (if (cdr range) - (format "%s..%s" - (magit-rev-to-git (car range)) - (magit-rev-to-git (cdr range))) - (format "%s" (magit-rev-to-git (car range)))))) - -(defun magit-rev-describe (rev) - (or rev - (error "No revision specified")) - (if (string= rev ".") - "mark" - (magit-name-rev rev))) - -(defun magit-rev-range-describe (range things) - (or range - (error "No revision range specified")) - (if (stringp range) - (format "%s in %s" things range) - (if (cdr range) - (format "%s from %s to %s" things - (magit-rev-describe (car range)) - (magit-rev-describe (cdr range))) - (format "%s at %s" things (magit-rev-describe (car range)))))) - -(defun magit-default-rev (&optional no-trim) - (or (magit-name-rev (magit-commit-at-point t) no-trim) - (let ((branch (magit-guess-branch))) - (if branch - (if (string-match "^refs/\\(.*\\)" branch) - (match-string 1 branch) - branch))))) - -(defun magit-read-remote (&optional prompt def) - "Read the name of a remote. -PROMPT is used as the prompt, and defaults to \"Remote\". -DEF is the default value." - (let* ((prompt (or prompt "Remote")) - (def (or def (magit-guess-remote))) - (remotes (magit-git-lines "remote")) - - (reply (magit-completing-read (concat prompt ": ") remotes - nil nil nil nil def))) - (if (string= reply "") nil reply))) - -(defun magit-read-remote-branch (remote &optional prompt default) - (let* ((prompt (or prompt (format "Remote branch (in %s)" remote))) - (branches (delete nil - (mapcar - (lambda (b) - (and (not (string-match " -> " b)) - (string-match (format "^ *%s/\\(.*\\)$" - (regexp-quote remote)) b) - (match-string 1 b))) - (magit-git-lines "branch" "-r")))) - (reply (magit-completing-read (concat prompt ": ") branches - nil nil nil nil default))) - (if (string= reply "") nil reply))) - -;;; Sections - -;; A buffer in magit-mode is organized into hierarchical sections. -;; These sections are used for navigation and for hiding parts of the -;; buffer. -;; -;; Most sections also represent the objects that Magit works with, -;; such as files, diffs, hunks, commits, etc. The 'type' of a section -;; identifies what kind of object it represents (if any), and the -;; parent and grand-parent, etc provide the context. - -(defstruct magit-section - parent title beginning end children hidden type info - needs-refresh-on-show) - -(defvar magit-top-section nil - "The top section of the current buffer.") -(make-variable-buffer-local 'magit-top-section) -(put 'magit-top-section 'permanent-local t) - -(defvar magit-old-top-section nil) - -(defvar magit-section-hidden-default nil) - -(defun magit-new-section (title type) - "Create a new section with title TITLE and type TYPE in current buffer. - -If not `magit-top-section' exist, the new section will be the new top-section -otherwise, the new-section will be a child of the current top-section. - -If TYPE is nil, the section won't be highlighted." - (let* ((s (make-magit-section :parent magit-top-section - :title title - :type type - :hidden magit-section-hidden-default)) - (old (and magit-old-top-section - (magit-find-section (magit-section-path s) - magit-old-top-section)))) - (if magit-top-section - (push s (magit-section-children magit-top-section)) - (setq magit-top-section s)) - (if old - (setf (magit-section-hidden s) (magit-section-hidden old))) - s)) - -(defun magit-cancel-section (section) - "Delete the section SECTION." - (delete-region (magit-section-beginning section) - (magit-section-end section)) - (let ((parent (magit-section-parent section))) - (if parent - (setf (magit-section-children parent) - (delq section (magit-section-children parent))) - (setq magit-top-section nil)))) - -(defmacro magit-with-section (title type &rest body) - "Create a new section of title TITLE and type TYPE and evaluate BODY there. - -Sections created inside BODY will become children of the new -section. BODY must leave point at the end of the created section. - -If TYPE is nil, the section won't be highlighted." - (declare (indent 2)) - (let ((s (make-symbol "*section*"))) - `(let* ((,s (magit-new-section ,title ,type)) - (magit-top-section ,s)) - (setf (magit-section-beginning ,s) (point)) - ,@body - (setf (magit-section-end ,s) (point)) - (setf (magit-section-children ,s) - (nreverse (magit-section-children ,s))) - ,s))) - -(defun magit-set-section (title type start end) - "Create a new section of title TITLE and type TYPE with specified start and -end positions." - (let ((section (magit-new-section title type))) - (setf (magit-section-beginning section) start) - (setf (magit-section-end section) end) - section)) - -(defun magit-set-section-info (info &optional section) - (setf (magit-section-info (or section magit-top-section)) info)) - -(defun magit-set-section-needs-refresh-on-show (flag &optional section) - (setf (magit-section-needs-refresh-on-show - (or section magit-top-section)) - flag)) - -(defmacro magit-create-buffer-sections (&rest body) - "Empty current buffer of text and Magit's sections, and then evaluate BODY." - (declare (indent 0)) - `(let ((inhibit-read-only t)) - (erase-buffer) - (let ((magit-old-top-section magit-top-section)) - (setq magit-top-section nil) - ,@body - (when (null magit-top-section) - (magit-with-section 'top nil - (insert "(empty)\n"))) - (magit-propertize-section magit-top-section) - (magit-section-set-hidden magit-top-section - (magit-section-hidden magit-top-section))))) - -(defun magit-propertize-section (section) - "Add text-property needed for SECTION." - (put-text-property (magit-section-beginning section) - (magit-section-end section) - 'magit-section section) - (dolist (s (magit-section-children section)) - (magit-propertize-section s))) - -(defun magit-find-section (path top) - "Find the section at the path PATH in subsection of section TOP." - (if (null path) - top - (let ((secs (magit-section-children top))) - (while (and secs (not (equal (car path) - (magit-section-title (car secs))))) - (setq secs (cdr secs))) - (and (car secs) - (magit-find-section (cdr path) (car secs)))))) - -(defun magit-section-path (section) - "Return the path of SECTION." - (if (not (magit-section-parent section)) - '() - (append (magit-section-path (magit-section-parent section)) - (list (magit-section-title section))))) - -(defun magit-find-section-after (pos) - "Find the first section that begins after POS." - (magit-find-section-after* pos (list magit-top-section))) - -(defun magit-find-section-after* (pos secs) - "Find the first section that begins after POS in the list SECS -\(including children of sections in SECS)." - (while (and secs - (<= (magit-section-beginning (car secs)) pos)) - (setq secs (if (magit-section-hidden (car secs)) - (cdr secs) - (append (magit-section-children (car secs)) - (cdr secs))))) - (car secs)) - -(defun magit-find-section-before (pos) - "Return the last section that begins before POS." - (let ((section (magit-find-section-at pos))) - (do* ((current (or (magit-section-parent section) - section) - next) - (next (if (not (magit-section-hidden current)) - (magit-find-section-before* pos (magit-section-children current))) - (if (not (magit-section-hidden current)) - (magit-find-section-before* pos (magit-section-children current))))) - ((null next) current)))) - -(defun magit-find-section-before* (pos secs) - "Find the last section that begins before POS in the list SECS." - (let ((prev nil)) - (while (and secs - (< (magit-section-beginning (car secs)) pos)) - (setq prev (car secs)) - (setq secs (cdr secs))) - prev)) - -(defun magit-current-section () - "Return the Magit section at point." - (magit-find-section-at (point))) - -(defun magit-find-section-at (pos) - "Return the Magit section at POS." - (or (get-text-property pos 'magit-section) - magit-top-section)) - -(defun magit-insert-section (section-title-and-type - buffer-title washer cmd &rest args) - "Run CMD and put its result in a new section. - -SECTION-TITLE-AND-TYPE is either a string that is the title of the section -or (TITLE . TYPE) where TITLE is the title of the section and TYPE is its type. - -If there is no type, or if type is nil, the section won't be highlighted. - -BUFFER-TITLE is the inserted title of the section - -WASHER is a function that will be run after CMD. -The buffer will be narrowed to the inserted text. -It should add sectioning as needed for Magit interaction. - -CMD is an external command that will be run with ARGS as arguments." - (let* ((body-beg nil) - (section-title (if (consp section-title-and-type) - (car section-title-and-type) - section-title-and-type)) - (section-type (if (consp section-title-and-type) - (cdr section-title-and-type) - nil)) - (section - (magit-with-section section-title section-type - (if buffer-title - (insert (propertize buffer-title 'face 'magit-section-title) - "\n")) - (setq body-beg (point)) - (magit-cmd-insert cmd args) - (if (not (eq (char-before) ?\n)) - (insert "\n")) - (if washer - (save-restriction - (narrow-to-region body-beg (point)) - (goto-char (point-min)) - (funcall washer) - (goto-char (point-max))))))) - (if (= body-beg (point)) - (magit-cancel-section section) - (insert "\n")) - section)) - -(defun magit-git-section (section-title-and-type - buffer-title washer &rest args) - "Run git and put its result in a new section. - -see `magit-insert-section' for meaning of the arguments" - (apply #'magit-insert-section - section-title-and-type - buffer-title - washer - magit-git-executable - (append magit-git-standard-options args))) - -(defun magit-goto-next-section () - "Go to the next section." - (interactive) - (let ((next (magit-find-section-after (point)))) - (if next - (magit-goto-section next) - (message "No next section")))) - -(defun magit-goto-previous-section () - "Go to the previous section." - (interactive) - (if (eq (point) 1) - (message "No previous section") - (magit-goto-section (magit-find-section-before (point))))) - -(defun magit-goto-parent-section () - "Go to the parent section." - (interactive) - (let ((parent (magit-section-parent (magit-current-section)))) - (when parent - (goto-char (magit-section-beginning parent))))) - -(defun magit-goto-next-sibling-section () - "Go to the next sibling section." - (interactive) - (let* ((initial (point)) - (section (magit-current-section)) - (end (- (magit-section-end section) 1)) - (parent (magit-section-parent section)) - (siblings (magit-section-children parent)) - (next-sibling (magit-find-section-after* end siblings))) - (if next-sibling - (magit-goto-section next-sibling) - (magit-goto-next-section)))) - -(defun magit-goto-previous-sibling-section () - "Go to the previous sibling section." - (interactive) - (let* ((section (magit-current-section)) - (beginning (magit-section-beginning section)) - (parent (magit-section-parent section)) - (siblings (magit-section-children parent)) - (previous-sibling (magit-find-section-before* beginning siblings))) - (if previous-sibling - (magit-goto-section previous-sibling) - (magit-goto-parent-section)))) - -(defun magit-goto-section (section) - (goto-char (magit-section-beginning section)) - (cond - ((and magit-log-auto-more - (eq (magit-section-type section) 'longer)) - (magit-log-show-more-entries) - (forward-line -1) - (magit-goto-next-section)) - ((and (eq (magit-section-type section) 'commit) - (derived-mode-p 'magit-log-mode)) - (magit-show-commit section)))) - -(defun magit-goto-section-at-path (path) - "Go to the section described by PATH." - (let ((sec (magit-find-section path magit-top-section))) - (if sec - (goto-char (magit-section-beginning sec)) - (message "No such section")))) - -(defun magit-for-all-sections (func &optional top) - "Run FUNC on TOP and recursively on all its children. - -Default value for TOP is `magit-top-section'" - (let ((section (or top magit-top-section))) - (when section - (funcall func section) - (dolist (c (magit-section-children section)) - (magit-for-all-sections func c))))) - -(defun magit-section-set-hidden (section hidden) - "Hide SECTION if HIDDEN is not nil, show it otherwise." - (setf (magit-section-hidden section) hidden) - (if (and (not hidden) - (magit-section-needs-refresh-on-show section)) - (magit-refresh) - (let ((inhibit-read-only t) - (beg (save-excursion - (goto-char (magit-section-beginning section)) - (forward-line) - (point))) - (end (magit-section-end section))) - (if (< beg end) - (put-text-property beg end 'invisible hidden))) - (if (not hidden) - (dolist (c (magit-section-children section)) - (magit-section-set-hidden c (magit-section-hidden c)))))) - -(defun magit-section-any-hidden (section) - "Return true if SECTION or any of its children is hidden." - (or (magit-section-hidden section) - (let ((kids (magit-section-children section))) - (while (and kids (not (magit-section-any-hidden (car kids)))) - (setq kids (cdr kids))) - kids))) - -(defun magit-section-collapse (section) - "Show SECTION and hide all its children." - (dolist (c (magit-section-children section)) - (setf (magit-section-hidden c) t)) - (magit-section-set-hidden section nil)) - -(defun magit-section-expand (section) - "Show SECTION and all its children." - (dolist (c (magit-section-children section)) - (setf (magit-section-hidden c) nil)) - (magit-section-set-hidden section nil)) - -(defun magit-section-expand-all-aux (section) - "Show recursively all SECTION's children." - (dolist (c (magit-section-children section)) - (setf (magit-section-hidden c) nil) - (magit-section-expand-all-aux c))) - -(defun magit-section-expand-all (section) - "Show SECTION and all its children." - (magit-section-expand-all-aux section) - (magit-section-set-hidden section nil)) - -(defun magit-section-hideshow (flag-or-func) - "Show or hide current section depending on FLAG-OR-FUNC. - -If FLAG-OR-FUNC is a function, it will be ran on current section -IF FLAG-OR-FUNC is a Boolean value, the section will be hidden if its true, shown otherwise" - (let ((section (magit-current-section))) - (when (magit-section-parent section) - (goto-char (magit-section-beginning section)) - (if (functionp flag-or-func) - (funcall flag-or-func section) - (magit-section-set-hidden section flag-or-func))))) - -(defun magit-show-section () - "Show current section." - (interactive) - (magit-section-hideshow nil)) - -(defun magit-hide-section () - "Hide current section." - (interactive) - (magit-section-hideshow t)) - -(defun magit-collapse-section () - "Hide all subsection of current section." - (interactive) - (magit-section-hideshow #'magit-section-collapse)) - -(defun magit-expand-section () - "Show all subsection of current section." - (interactive) - (magit-section-hideshow #'magit-section-expand)) - -(defun magit-toggle-file-section () - "Like `magit-toggle-section' but toggle at file granularity." - (interactive) - (when (eq 'hunk (first (magit-section-context-type (magit-current-section)))) - (magit-goto-parent-section)) - (magit-toggle-section)) - -(defun magit-toggle-section () - "Toggle hidden status of current section." - (interactive) - (magit-section-hideshow - (lambda (s) - (magit-section-set-hidden s (not (magit-section-hidden s)))))) - -(defun magit-expand-collapse-section () - "Toggle hidden status of subsections of current section." - (interactive) - (magit-section-hideshow - (lambda (s) - (cond ((magit-section-any-hidden s) - (magit-section-expand-all s)) - (t - (magit-section-collapse s)))))) - -(defun magit-cycle-section () - "Cycle between expanded, hidden and collapsed state for current section. - -Hidden: only the first line of the section is shown -Collapsed: only the first line of the subsection is shown -Expanded: everything is shown." - (interactive) - (magit-section-hideshow - (lambda (s) - (cond ((magit-section-hidden s) - (magit-section-collapse s)) - ((notany #'magit-section-hidden (magit-section-children s)) - (magit-section-set-hidden s t)) - (t - (magit-section-expand s)))))) - -(defun magit-section-lineage (s) - "Return list of parent, grand-parents... for section S." - (when s - (cons s (magit-section-lineage (magit-section-parent s))))) - -(defun magit-section-show-level (section level threshold path) - (magit-section-set-hidden section (>= level threshold)) - (when (and (< level threshold) - (not (magit-no-commit-p))) - (if path - (magit-section-show-level (car path) (1+ level) threshold (cdr path)) - (dolist (c (magit-section-children section)) - (magit-section-show-level c (1+ level) threshold nil))))) - -(defun magit-show-level (level all) - "Show section whose level is less than LEVEL, hide the others. -If ALL is non nil, do this in all sections, -otherwise do it only on ancestors and descendants of current section." - (magit-with-refresh - (if all - (magit-section-show-level magit-top-section 0 level nil) - (let ((path (reverse (magit-section-lineage (magit-current-section))))) - (magit-section-show-level (car path) 0 level (cdr path)))))) - -(defun magit-show-only-files () - "Show section that are files, but not there subsection. - -Do this in on ancestors and descendants of current section." - (interactive) - (if (derived-mode-p 'magit-status-mode) - (call-interactively 'magit-show-level-2) - (call-interactively 'magit-show-level-1))) - -(defun magit-show-only-files-all () - "Show section that are files, but not there subsection. - -Do this for all sections" - (interactive) - (if (derived-mode-p 'magit-status-mode) - (call-interactively 'magit-show-level-2-all) - (call-interactively 'magit-show-level-1-all))) - -(defmacro magit-define-level-shower-1 (level all) - "Define an interactive function to show function of level LEVEL. - -If ALL is non nil, this function will affect all section, -otherwise it will affect only ancestors and descendants of current section." - (let ((fun (intern (format "magit-show-level-%s%s" - level (if all "-all" "")))) - (doc (format "Show sections on level %s." level))) - `(defun ,fun () - ,doc - (interactive) - (magit-show-level ,level ,all)))) - -(defmacro magit-define-level-shower (level) - "Define two interactive function to show function of level LEVEL. -one for all, one for current lineage." - `(progn - (magit-define-level-shower-1 ,level nil) - (magit-define-level-shower-1 ,level t))) - -(defmacro magit-define-section-jumper (sym title) - "Define an interactive function to go to section SYM. - -TITLE is the displayed title of the section." - (let ((fun (intern (format "magit-jump-to-%s" sym))) - (doc (format "Jump to section `%s'." title))) - `(progn - (defun ,fun () - ,doc - (interactive) - (magit-goto-section-at-path '(,sym))) - (put ',fun 'definition-name ',sym)))) - -(defmacro magit-define-inserter (sym arglist &rest body) - (declare (indent defun)) - (let ((fun (intern (format "magit-insert-%s" sym))) - (before (intern (format "magit-before-insert-%s-hook" sym))) - (after (intern (format "magit-after-insert-%s-hook" sym))) - (doc (format "Insert items for `%s'." sym))) - `(progn - (defvar ,before nil) - (defvar ,after nil) - (defun ,fun ,arglist - ,doc - (run-hooks ',before) - ,@body - (run-hooks ',after)) - (put ',before 'definition-name ',sym) - (put ',after 'definition-name ',sym) - (put ',fun 'definition-name ',sym)))) - -(defvar magit-highlighted-section nil) - -(defun magit-refine-section (section) - "Apply temporary refinements to the display of SECTION. -Refinements can be undone with `magit-unrefine-section'." - (let ((type (and section (magit-section-type section)))) - (cond ((and (eq type 'hunk) - magit-diff-refine-hunk - (not (eq magit-diff-refine-hunk 'all))) - ;; Refine the current hunk to show fine details, using - ;; diff-mode machinery. - (save-excursion - (goto-char (magit-section-beginning magit-highlighted-section)) - (diff-refine-hunk)))))) - -(defun magit-unrefine-section (section) - "Remove refinements to the display of SECTION done by `magit-refine-section'." - (let ((type (and section (magit-section-type section)))) - (cond ((and (eq type 'hunk) - magit-diff-refine-hunk - (not (eq magit-diff-refine-hunk 'all))) - ;; XXX this should be in some diff-mode function, like - ;; `diff-unrefine-hunk' - (remove-overlays (magit-section-beginning section) - (magit-section-end section) - 'diff-mode 'fine))))) - -(defvar magit-highlight-overlay nil) - -(defun magit-highlight-section () - "Highlight current section if it has a type." - (let ((section (magit-current-section))) - (when (not (eq section magit-highlighted-section)) - (when magit-highlighted-section - ;; remove any refinement from previous hunk - (magit-unrefine-section magit-highlighted-section)) - (setq magit-highlighted-section section) - (if (not magit-highlight-overlay) - (let ((ov (make-overlay 1 1))) - (overlay-put ov 'face 'magit-item-highlight) - (setq magit-highlight-overlay ov))) - (if (and section (magit-section-type section)) - (progn - (magit-refine-section section) - (move-overlay magit-highlight-overlay - (magit-section-beginning section) - (magit-section-end section) - (current-buffer))) - (delete-overlay magit-highlight-overlay))))) - -(defun magit-section-context-type (section) - (if (null section) - '() - (let ((c (or (magit-section-type section) - (if (symbolp (magit-section-title section)) - (magit-section-title section))))) - (if c - (cons c (magit-section-context-type - (magit-section-parent section))) - '())))) - -(defun magit-prefix-p (prefix list) - "Returns non-nil if PREFIX is a prefix of LIST. PREFIX and LIST should both be -lists. - -If the car of PREFIX is the symbol '*, then return non-nil if the cdr of PREFIX -is a sublist of LIST (as if '* matched zero or more arbitrary elements of LIST)" - ;;; Very schemish... - (or (null prefix) - (if (eq (car prefix) '*) - (or (magit-prefix-p (cdr prefix) list) - (and (not (null list)) - (magit-prefix-p prefix (cdr list)))) - (and (not (null list)) - (equal (car prefix) (car list)) - (magit-prefix-p (cdr prefix) (cdr list)))))) - -(defmacro magit-section-case (head &rest clauses) - "Make different action depending of current section. - -HEAD is (SECTION INFO &optional OPNAME), - SECTION will be bind to the current section, - INFO will be bind to the info's of the current section, - OPNAME is a string that will be used to describe current action, - -CLAUSES is a list of CLAUSE, each clause is (SECTION-TYPE &BODY) -where SECTION-TYPE describe section where BODY will be run. - -This returns non-nil if some section matches. If the -corresponding body return a non-nil value, it is returned, -otherwise it returns t. - -If no section matches, this returns nil if no OPNAME was given -and throws an error otherwise." - (declare (indent 1)) - (let ((section (car head)) - (info (cadr head)) - (type (make-symbol "*type*")) - (context (make-symbol "*context*")) - (opname (caddr head))) - `(let* ((,section (magit-current-section)) - (,info (and ,section (magit-section-info ,section))) - (,type (and ,section (magit-section-type ,section))) - (,context (magit-section-context-type ,section))) - (cond ,@(mapcar (lambda (clause) - (if (eq (car clause) t) - `(t (or (progn ,@(cdr clause)) - t)) - (let ((prefix (reverse (car clause))) - (body (cdr clause))) - `((magit-prefix-p ',prefix ,context) - (or (progn ,@body) - t))))) - clauses) - ,@(when opname - `(((run-hook-with-args-until-success - ',(intern (format "magit-%s-action-hook" opname)))) - ((not ,type) - (error "Nothing to %s here" ,opname)) - (t - (error "Can't %s a %s" - ,opname - (or (get ,type 'magit-description) - ,type))))))))) - -(defmacro magit-section-action (head &rest clauses) - (declare (indent 1)) - `(magit-with-refresh - (magit-section-case ,head ,@clauses))) - -(defmacro magit-add-action (head &rest clauses) - "Add additional actions to a pre-existing operator. -The syntax is identical to `magit-section-case', except that -OPNAME is mandatory and specifies the operation to which to add -the actions." - (declare (indent 1)) - (let ((section (car head)) - (info (cadr head)) - (type (caddr head))) - `(add-hook ',(intern (format "magit-%s-action-hook" type)) - (lambda () - ,(macroexpand - ;; Don't pass in the opname so we don't recursively - ;; run the hook again, and so we don't throw an - ;; error if no action matches. - `(magit-section-case (,section ,info) - ,@clauses)))))) - -(defun magit-wash-sequence (func) - "Run FUNC until end of buffer is reached. - -FUNC should leave point at the end of the modified region" - (while (and (not (eobp)) - (funcall func)))) - -(defmacro magit-define-command (sym arglist &rest body) - "Macro to define a magit command. -It will define the magit-SYM function having ARGLIST as argument. -It will also define the magit-SYM-command-hook variable. - -The defined function will call the function in the hook in -order until one return non nil. If they all return nil then body will be called. - -It is used to define hookable magit command: command defined by this -function can be enriched by magit extension like magit-topgit and magit-svn" - (declare (indent defun) - (debug (&define name lambda-list - [&optional stringp] ; Match the doc string, if present. - [&optional ("interactive" interactive)] - def-body))) - (let ((fun (intern (format "magit-%s" sym))) - (hook (intern (format "magit-%s-command-hook" sym))) - (doc (format "Command for `%s'." sym)) - (inter nil) - (instr body)) - (when (stringp (car body)) - (setq doc (car body) - instr (cdr body))) - (let ((form (car instr))) - (when (eq (car form) 'interactive) - (setq inter form - instr (cdr instr)))) - `(progn - (defvar ,hook nil) - (defun ,fun ,arglist - ,doc - ,inter - (or (run-hook-with-args-until-success - ',hook ,@(remq '&optional (remq '&rest arglist))) - ,@instr)) - (put ',fun 'definition-name ',sym) - (put ',hook 'definition-name ',sym)))) - -;;; Running commands - -(defun magit-set-mode-line-process (str) - (let ((pr (if str (concat " " str) ""))) - (save-excursion - (magit-for-all-buffers (lambda () - (setq mode-line-process pr)))))) - -(defun magit-process-indicator-from-command (comps) - (if (magit-prefix-p (cons magit-git-executable magit-git-standard-options) - comps) - (setq comps (nthcdr (+ (length magit-git-standard-options) 1) comps))) - (cond ((or (null (cdr comps)) - (not (member (car comps) '("remote")))) - (car comps)) - (t - (concat (car comps) " " (cadr comps))))) - -(defvar magit-process nil) -(defvar magit-process-client-buffer nil) -(defvar magit-process-buffer-name "*magit-process*" - "Buffer name for running git commands.") - -(defun magit-run* (cmd-and-args - &optional logline noerase noerror nowait input) - (if (and magit-process - (get-buffer magit-process-buffer-name)) - (error "Git is already running")) - (let ((cmd (car cmd-and-args)) - (args (cdr cmd-and-args)) - (dir default-directory) - (buf (get-buffer-create magit-process-buffer-name)) - (successp nil)) - (magit-set-mode-line-process - (magit-process-indicator-from-command cmd-and-args)) - (setq magit-process-client-buffer (current-buffer)) - (with-current-buffer buf - (view-mode 1) - (set (make-local-variable 'view-no-disable-on-exit) t) - (setq view-exit-action - (lambda (buffer) - (with-current-buffer buffer - (bury-buffer)))) - (setq buffer-read-only t) - (let ((inhibit-read-only t)) - (setq default-directory dir) - (if noerase - (goto-char (point-max)) - (erase-buffer)) - (insert "$ " (or logline - (mapconcat 'identity cmd-and-args " ")) - "\n") - (cond (nowait - (setq magit-process - (let ((process-connection-type magit-process-connection-type)) - (apply 'magit-start-process cmd buf cmd args))) - (set-process-sentinel magit-process 'magit-process-sentinel) - (set-process-filter magit-process 'magit-process-filter) - (when input - (with-current-buffer input - (process-send-region magit-process - (point-min) (point-max))) - (process-send-eof magit-process) - (sit-for 0.1 t)) - (cond ((= magit-process-popup-time 0) - (pop-to-buffer (process-buffer magit-process))) - ((> magit-process-popup-time 0) - (run-with-timer - magit-process-popup-time nil - (function - (lambda (buf) - (with-current-buffer buf - (when magit-process - (display-buffer (process-buffer magit-process)) - (goto-char (point-max)))))) - (current-buffer)))) - (setq successp t)) - (input - (with-current-buffer input - (setq default-directory dir) - (setq magit-process - ;; Don't use a pty, because it would set icrnl - ;; which would modify the input (issue #20). - (let ((process-connection-type nil)) - (apply 'magit-start-process cmd buf cmd args))) - (set-process-filter magit-process 'magit-process-filter) - (process-send-region magit-process - (point-min) (point-max)) - (process-send-eof magit-process) - (while (equal (process-status magit-process) 'run) - (sit-for 0.1 t)) - (setq successp - (equal (process-exit-status magit-process) 0)) - (setq magit-process nil)) - (magit-set-mode-line-process nil) - (magit-need-refresh magit-process-client-buffer)) - (t - (setq successp - (equal (apply 'process-file cmd nil buf nil args) 0)) - (magit-set-mode-line-process nil) - (magit-need-refresh magit-process-client-buffer)))) - (or successp - noerror - (error - "%s ... [Hit %s or see buffer %s for details]" - (or (with-current-buffer (get-buffer magit-process-buffer-name) - (when (re-search-backward - (concat "^error: \\(.*\\)" paragraph-separate) nil t) - (match-string 1))) - "Git failed") - (with-current-buffer magit-process-client-buffer - (key-description (car (where-is-internal - 'magit-display-process)))) - magit-process-buffer-name)) - successp))) - -(autoload 'dired-uncache "dired") -(defun magit-process-sentinel (process event) - (let ((msg (format "%s %s." (process-name process) (substring event 0 -1))) - (successp (string-match "^finished" event)) - (key (with-current-buffer magit-process-client-buffer - (key-description (car (where-is-internal - 'magit-display-process)))))) - (with-current-buffer (process-buffer process) - (let ((inhibit-read-only t)) - (goto-char (point-max)) - (insert msg "\n") - (message (if successp msg - (format "%s Hit %s or see buffer %s for details." - msg key (current-buffer))))) - (unless (memq (process-status process) '(run open)) - (dired-uncache default-directory))) - (setq magit-process nil) - (magit-set-mode-line-process nil) - (magit-refresh-buffer magit-process-client-buffer))) - -(defun magit-password (proc string) - "Checks if git/ssh asks for a password and ask the user for it." - (let (ask) - (cond ((or (string-match "^Enter passphrase for key '\\\(.*\\\)': $" string) - (string-match "^\\\(.*\\\)'s password:" string) - (string-match "^Password for '\\\(.*\\\)':" string)) - (setq ask (format "Password for '%s': " (match-string 1 string)))) - ((string-match "^[pP]assword:" string) - (setq ask "Password:"))) - (when ask - (process-send-string proc (concat (read-passwd ask nil) "\n"))))) - -(defun magit-username (proc string) - "Checks if git asks for a username and ask the user for it." - (when (string-match "^Username for '\\\(.*\\\)':" string) - (process-send-string proc - (concat - (read-string (format "Username for '%s': " - (match-string 1 string)) - nil nil (user-login-name)) - "\n")))) - -(defun magit-process-filter (proc string) - (save-current-buffer - (set-buffer (process-buffer proc)) - (let ((inhibit-read-only t)) - (magit-username proc string) - (magit-password proc string) - (goto-char (process-mark proc)) - ;; Find last ^M in string. If one was found, ignore everything - ;; before it and delete the current line. - (let ((ret-pos (length string))) - (while (and (>= (setq ret-pos (1- ret-pos)) 0) - (/= ?\r (aref string ret-pos)))) - (cond ((>= ret-pos 0) - (goto-char (line-beginning-position)) - (delete-region (point) (line-end-position)) - (insert (substring string (+ ret-pos 1)))) - (t - (insert string)))) - (set-marker (process-mark proc) (point))))) - -(defun magit-run (cmd &rest args) - (magit-with-refresh - (magit-run* (cons cmd args)))) - -(defun magit-run-git (&rest args) - (magit-with-refresh - (magit-run* (append (cons magit-git-executable - magit-git-standard-options) - args)))) - -(defun magit-run-git-with-input (input &rest args) - (magit-with-refresh - (magit-run* (append (cons magit-git-executable - magit-git-standard-options) - args) - nil nil nil nil input))) - -(defun magit-run-git-async (&rest args) - (message "Running %s %s" magit-git-executable (mapconcat 'identity args " ")) - (magit-run* (append (cons magit-git-executable - magit-git-standard-options) - args) - nil nil nil t)) - -(defun magit-run-async-with-input (input cmd &rest args) - (magit-run* (cons cmd args) nil nil nil t input)) - -(defun magit-display-process () - "Display output from most recent git command." - (interactive) - (unless (get-buffer magit-process-buffer-name) - (error "No Git commands have run")) - (display-buffer magit-process-buffer-name)) - -;;; Mode - -;; We define individual functions (instead of using lambda etc) so -;; that the online help can show something meaningful. - -(magit-define-section-jumper untracked "Untracked files") -(magit-define-section-jumper unstaged "Unstaged changes") -(magit-define-section-jumper staged "Staged changes") -(magit-define-section-jumper unpushed "Unpushed commits") - -(magit-define-level-shower 1) -(magit-define-level-shower 2) -(magit-define-level-shower 3) -(magit-define-level-shower 4) - -(easy-menu-define magit-mode-menu magit-mode-map - "Magit menu" - '("Magit" - ["Refresh" magit-refresh t] - ["Refresh all" magit-refresh-all t] - "---" - ["Stage" magit-stage-item t] - ["Stage all" magit-stage-all t] - ["Unstage" magit-unstage-item t] - ["Unstage all" magit-unstage-all t] - ["Commit" magit-log-edit t] - ["Add log entry" magit-add-log t] - ["Tag" magit-tag t] - ["Annotated tag" magit-annotated-tag t] - "---" - ["Diff working tree" magit-diff-working-tree t] - ["Diff" magit-diff t] - ("Log" - ["Short Log" magit-log t] - ["Long Log" magit-log-long t] - ["Reflog" magit-reflog t] - ["Extended..." magit-key-mode-popup-logging t]) - "---" - ["Cherry pick" magit-cherry-pick-item t] - ["Apply" magit-apply-item t] - ["Revert" magit-revert-item t] - "---" - ["Ignore" magit-ignore-item t] - ["Ignore locally" magit-ignore-item-locally t] - ["Discard" magit-discard-item t] - ["Reset head" magit-reset-head t] - ["Reset working tree" magit-reset-working-tree t] - ["Stash" magit-stash t] - ["Snapshot" magit-stash-snapshot t] - "---" - ["Branch..." magit-checkout t] - ["Merge" magit-manual-merge t] - ["Interactive resolve" magit-interactive-resolve-item t] - ["Rebase" magit-rebase-step t] - ("Rewrite" - ["Start" magit-rewrite-start t] - ["Stop" magit-rewrite-stop t] - ["Finish" magit-rewrite-finish t] - ["Abort" magit-rewrite-abort t] - ["Set used" magit-rewrite-set-used t] - ["Set unused" magit-rewrite-set-unused t]) - "---" - ["Push" magit-push t] - ["Pull" magit-pull t] - ["Remote update" magit-remote-update t] - ("Submodule" - ["Submodule update" magit-submodule-update t] - ["Submodule update and init" magit-submodule-update-init t] - ["Submodule init" magit-submodule-init t] - ["Submodule sync" magit-submodule-sync t]) - "---" - ("Extensions") - "---" - ["Display Git output" magit-display-process t] - ["Quit Magit" magit-quit-window t])) - -(defvar magit-mode-hook nil "Hook run by `magit-mode'.") - -(put 'magit-mode 'mode-class 'special) - -(defvar magit-refresh-function nil) -(make-variable-buffer-local 'magit-refresh-function) -(put 'magit-refresh-function 'permanent-local t) - -(defvar magit-refresh-args nil) -(make-variable-buffer-local 'magit-refresh-args) -(put 'magit-refresh-args 'permanent-local t) - -(defvar last-point) - -(defun magit-remember-point () - (setq last-point (point))) - -(defun magit-invisible-region-end (pos) - (while (and (not (= pos (point-max))) (invisible-p pos)) - (setq pos (next-char-property-change pos))) - pos) - -(defun magit-invisible-region-start (pos) - (while (and (not (= pos (point-min))) (invisible-p pos)) - (setq pos (1- (previous-char-property-change pos)))) - pos) - -(defun magit-correct-point-after-command () - "Move point outside of invisible regions. - -Emacs often leaves point in invisible regions, it seems. To fix -this, we move point ourselves and never let Emacs do its own -adjustments. - -When point has to be moved out of an invisible region, it can be -moved to its end or its beginning. We usually move it to its -end, except when that would move point back to where it was -before the last command." - (if (invisible-p (point)) - (let ((end (magit-invisible-region-end (point)))) - (goto-char (if (= end last-point) - (magit-invisible-region-start (point)) - end)))) - (setq disable-point-adjustment t)) - -(defun magit-post-command-hook () - (magit-correct-point-after-command) - (magit-highlight-section)) - -(defun magit-mode () - "Review the status of a git repository and act on it. - -Please see the manual for a complete description of Magit. - -\\{magit-mode-map}" - (kill-all-local-variables) - (buffer-disable-undo) - (setq buffer-read-only t - truncate-lines t - major-mode 'magit-mode - mode-name "Magit" - mode-line-process "") - (add-hook 'pre-command-hook #'magit-remember-point nil t) - (add-hook 'post-command-hook #'magit-post-command-hook t t) - (use-local-map magit-mode-map) - (setq magit-current-indentation (magit-indentation-for default-directory)) - ;; Emacs' normal method of showing trailing whitespace gives weird - ;; results when `magit-whitespace-warning-face' is different from - ;; `trailing-whitespace'. - (if (and magit-highlight-whitespace magit-highlight-trailing-whitespace) - (setq show-trailing-whitespace nil)) - (run-mode-hooks 'magit-mode-hook)) - -(defun magit-mode-init (dir submode refresh-func &rest refresh-args) - (setq default-directory dir - magit-refresh-function refresh-func - magit-refresh-args refresh-args) - (funcall submode) - (magit-refresh-buffer)) - -(defun magit-indentation-for (dir) - (let (result) - (dolist (pair magit-highlight-indentation) - (if (string-match-p (car pair) dir) - (setq result (cdr pair)))) - result)) - -(defun magit-find-buffer (submode &optional dir) - (let ((topdir (magit-get-top-dir (or dir default-directory)))) - (dolist (buf (buffer-list)) - (if (with-current-buffer buf - (and (eq major-mode submode) - default-directory - (equal (expand-file-name default-directory) topdir))) - (return buf))))) - -(defun magit-find-status-buffer (&optional dir) - (magit-find-buffer 'magit-status-mode dir)) - -(defun magit-for-all-buffers (func &optional dir) - (dolist (buf (buffer-list)) - (with-current-buffer buf - (if (and (derived-mode-p 'magit-mode) - (or (null dir) - (equal default-directory dir))) - (funcall func))))) - -(defun magit-refresh-buffer (&optional buffer) - (with-current-buffer (or buffer (current-buffer)) - (let* ((old-line (line-number-at-pos)) - (old-point (point)) - (old-section (magit-current-section)) - (old-path (and old-section - (magit-section-path (magit-current-section))))) - (beginning-of-line) - (let ((section-line (and old-section - (count-lines - (magit-section-beginning old-section) - (point)))) - (line-char (- old-point (point)))) - (if magit-refresh-function - (apply magit-refresh-function - magit-refresh-args)) - (magit-refresh-marked-commits-in-buffer) - (let ((s (and old-path (magit-find-section old-path magit-top-section)))) - (cond (s - (goto-char (magit-section-beginning s)) - (forward-line section-line) - (forward-char line-char)) - (t - (magit-goto-line old-line))) - (dolist (w (get-buffer-window-list (current-buffer))) - (set-window-point w (point))) - (magit-highlight-section)))))) - -(defun magit-string-has-prefix-p (string prefix) - (eq (compare-strings string nil (length prefix) prefix nil nil) t)) - -(defun magit-revert-buffers (dir &optional ignore-modtime) - (dolist (buffer (buffer-list)) - (when (and buffer - (buffer-file-name buffer) - ;; don't revert indirect buffers, as the parent will be reverted - (not (buffer-base-buffer buffer)) - (magit-string-has-prefix-p (buffer-file-name buffer) dir) - (file-readable-p (buffer-file-name buffer)) - (or ignore-modtime (not (verify-visited-file-modtime buffer))) - (not (buffer-modified-p buffer))) - (with-current-buffer buffer - (condition-case var - (revert-buffer t t nil) - (error (let ((signal-data (cadr var))) - (cond (t (magit-bug-report signal-data)))))))))) - -(defun magit-update-vc-modeline (dir) - "Update the modeline for buffers representable by magit." - (dolist (buffer (buffer-list)) - (when (and buffer - (buffer-file-name buffer) - (magit-string-has-prefix-p (buffer-file-name buffer) dir)) - (with-current-buffer buffer - (condition-case var - (vc-find-file-hook) - (error (let ((signal-data (cadr var))) - (cond (t (magit-bug-report signal-data)))))))))) - -(defvar magit-refresh-needing-buffers nil) -(defvar magit-refresh-pending nil) - -(defun magit-refresh-wrapper (func) - (if magit-refresh-pending - (funcall func) - (let* ((dir default-directory) - (status-buffer (magit-find-status-buffer dir)) - (magit-refresh-needing-buffers nil) - (magit-refresh-pending t)) - (unwind-protect - (funcall func) - (when magit-refresh-needing-buffers - (magit-revert-buffers dir) - (dolist (b (adjoin status-buffer - magit-refresh-needing-buffers)) - (magit-refresh-buffer b))))))) - -(defun magit-need-refresh (&optional buffer) - "Mark BUFFER as needing to be refreshed. If BUFFER is nil, use the -current buffer." - (pushnew (or buffer (current-buffer)) magit-refresh-needing-buffers :test 'eq)) - -(defun magit-refresh () - "Refresh current buffer to match repository state. -Also revert every unmodified buffer visiting files -in the corresponding directory." - (interactive) - (magit-with-refresh - (magit-need-refresh))) - -(defun magit-refresh-all () - "Refresh all magit buffers to match respective repository states. -Also revert every unmodified buffer visiting files -in the corresponding directories." - (interactive) - (magit-for-all-buffers #'magit-refresh-buffer default-directory)) - -;;; Untracked files - -(defun magit-wash-untracked-file () - (if (looking-at "^? \\(.*\\)$") - (let ((file (match-string-no-properties 1))) - (delete-region (point) (+ (line-end-position) 1)) - (magit-with-section file 'file - (magit-set-section-info file) - (insert "\t" file "\n")) - t) - nil)) - -(defun magit-wash-untracked-files () - ;; Setting magit-old-top-section to nil speeds up washing: no time - ;; is wasted looking up the old visibility, which doesn't matter for - ;; untracked files. - ;; - ;; XXX - speed this up in a more general way. - ;; - (let ((magit-old-top-section nil)) - (magit-wash-sequence #'magit-wash-untracked-file))) - -(defun magit-insert-untracked-files () - (unless (string= (magit-get "status" "showUntrackedFiles") "no") - (apply 'magit-git-section - `(untracked - "Untracked files:" - magit-wash-untracked-files - "ls-files" "--others" "-t" "--exclude-standard" - ,@(when magit-omit-untracked-dir-contents - '("--directory")))))) - -;;; Diffs and Hunks - -(defvar magit-diff-context-lines 3) - -(defun magit-diff-U-arg () - (format "-U%d" magit-diff-context-lines)) - -(defun magit-diff-smaller-hunks (&optional count) - "Decrease the context for diff hunks by COUNT." - (interactive "p") - (setq magit-diff-context-lines (max 0 (- magit-diff-context-lines count))) - (magit-refresh)) - -(defun magit-diff-larger-hunks (&optional count) - "Increase the context for diff hunks by COUNT." - (interactive "p") - (setq magit-diff-context-lines (+ magit-diff-context-lines count)) - (magit-refresh)) - -(defun magit-diff-default-hunks () - "Reset context for diff hunks to the default size." - (interactive "") - (setq magit-diff-context-lines 3) - (magit-refresh)) - -(defun magit-toggle-diff-refine-hunk (&optional other) - (interactive "P") - "Turn diff-hunk refining on or off. - -If hunk refining is currently on, then hunk refining is turned off. -If hunk refining is off, then hunk refining is turned on, in -`selected' mode (only the currently selected hunk is refined). - -With a prefix argument, the \"third choice\" is used instead: -If hunk refining is currently on, then refining is kept on, but -the refining mode (`selected' or `all') is switched. -If hunk refining is off, then hunk refining is turned on, in -`all' mode (all hunks refined). - -Customize `magit-diff-refine-hunk' to change the default mode." - (let* ((old magit-diff-refine-hunk) - (new - (if other - (if (eq old 'all) t 'all) - (not old)))) - - ;; remove any old refining in currently highlighted section - (when (and magit-highlighted-section old (not (eq old 'all))) - (magit-unrefine-section magit-highlighted-section)) - - ;; set variable to new value locally - (set (make-local-variable 'magit-diff-refine-hunk) new) - - ;; if now highlighting in "selected only" mode, turn refining back - ;; on in the current section - (when (and magit-highlighted-section new (not (eq new 'all))) - (magit-refine-section magit-highlighted-section)) - - ;; `all' mode being turned on or off needs a complete refresh - (when (or (eq old 'all) (eq new 'all)) - (magit-refresh)))) - -(defun magit-diff-line-file () - (cond ((looking-at "^diff --git ./\\(.*\\) ./\\(.*\\)$") - (match-string-no-properties 2)) - ((looking-at "^diff --cc +\\(.*\\)$") - (match-string-no-properties 1)) - (t - nil))) - -(defun magit-wash-diffs () - (magit-wash-sequence #'magit-wash-diff-or-other-file)) - -(defun magit-wash-diff-or-other-file () - (or (magit-wash-diff) - (magit-wash-other-file))) - -(defun magit-wash-other-file () - (if (looking-at "^? \\(.*\\)$") - (let ((file (match-string-no-properties 1))) - (delete-region (point) (+ (line-end-position) 1)) - (magit-with-section file 'file - (magit-set-section-info file) - (insert "\tNew " file "\n")) - t) - nil)) - -(defvar magit-hide-diffs nil) - -(defvar magit-indentation-level 1) - -(defun magit-insert-diff-title (status file file2) - (let ((status-text (case status - ((unmerged) - (format "Unmerged %s" file)) - ((new) - (format "New %s" file)) - ((deleted) - (format "Deleted %s" file)) - ((renamed) - (format "Renamed %s (from %s)" - file file2)) - ((modified) - (format "Modified %s" file)) - ((typechange) - (format "Typechange %s" file)) - (t - (format "? %s" file))))) - (insert (make-string magit-indentation-level ?\t) status-text "\n"))) - -(defvar magit-current-diff-range nil - "Used internally when setting up magit diff sections.") - -(defun magit-wash-typechange-section (file) - (magit-set-section-info (list 'typechange file)) - (let ((first-start (point-marker)) - (second-start (progn (forward-line 1) - (search-forward-regexp "^diff") - (beginning-of-line) - (point-marker)))) - (let ((magit-indentation-level (+ magit-indentation-level 1))) - (save-restriction - (narrow-to-region first-start second-start) - (goto-char (point-min)) - (magit-with-section file 'diff - (magit-wash-diff-section))) - (save-restriction - (narrow-to-region second-start (point-max)) - (goto-char (point-min)) - (magit-with-section file 'diff - (magit-wash-diff-section)))))) - -(defun magit-wash-diff-section () - (cond ((looking-at "^\\* Unmerged path \\(.*\\)") - (let ((file (match-string-no-properties 1))) - (delete-region (point) (line-end-position)) - (insert "\tUnmerged " file "\n") - (magit-set-section-info (list 'unmerged file nil)) - t)) - ((looking-at "^diff") - (let ((file (magit-diff-line-file)) - (end (save-excursion - (forward-line) ;; skip over "diff" line - (if (search-forward-regexp "^diff\\|^@@" nil t) - (goto-char (match-beginning 0)) - (goto-char (point-max))) - (point-marker)))) - (let* ((status (cond - ((looking-at "^diff --cc") - 'unmerged) - ((save-excursion - (search-forward-regexp "^new file" end t)) - 'new) - ((save-excursion - (search-forward-regexp "^deleted" end t)) - 'deleted) - ((save-excursion - (search-forward-regexp "^rename" end t)) - 'renamed) - (t - 'modified))) - (file2 (cond - ((save-excursion - (search-forward-regexp "^rename from \\(.*\\)" - end t)) - (match-string-no-properties 1))))) - (magit-set-section-info (list status - file - (or file2 file) - magit-current-diff-range)) - (magit-insert-diff-title status file file2) - (when (search-forward-regexp "\\(--- \\(.*\\)\n\\+\\+\\+ \\(.*\\)\n\\)" () t) - (when (match-string 1) - (add-text-properties (match-beginning 1) (match-end 1) - '(face magit-diff-hunk-header)) - (add-text-properties (match-beginning 2) (match-end 2) - '(face magit-diff-file-header)) - (add-text-properties (match-beginning 3) (match-end 3) - '(face magit-diff-file-header)))) - (goto-char end) - (let ((magit-section-hidden-default nil)) - (magit-wash-sequence #'magit-wash-hunk)))) - t) - (t - nil))) - -(defun magit-wash-diff () - (let ((magit-section-hidden-default magit-hide-diffs)) - (magit-with-section (magit-current-line) 'diff - (magit-wash-diff-section)))) - -(defun magit-diff-item-kind (diff) - (car (magit-section-info diff))) - -(defun magit-diff-item-file (diff) - (cadr (magit-section-info diff))) - -(defun magit-diff-item-file2 (diff) - (caddr (magit-section-info diff))) - -(defun magit-diff-item-range (diff) - (nth 3 (magit-section-info diff))) - -(defun magit-wash-hunk () - (cond ((looking-at "\\(^@+\\)[^@]*@+.*") - (let ((n-columns (1- (length (match-string 1)))) - (head (match-string 0)) - (hunk-start-pos (point))) - (magit-with-section head 'hunk - (add-text-properties (match-beginning 0) (match-end 0) - '(face magit-diff-hunk-header)) - (forward-line) - (while (not (or (eobp) - (looking-at "^diff\\|^@@"))) - (magit-highlight-line-whitespace) - (let ((prefix (buffer-substring-no-properties - (point) (min (+ (point) n-columns) (point-max))))) - (cond ((string-match "\\+" prefix) - (magit-put-line-property 'face 'magit-diff-add)) - ((string-match "-" prefix) - (magit-put-line-property 'face 'magit-diff-del)) - (t - (magit-put-line-property 'face 'magit-diff-none)))) - (forward-line))) - - (when (eq magit-diff-refine-hunk 'all) - (save-excursion - (goto-char hunk-start-pos) - (diff-refine-hunk)))) - t) - (t - nil))) - -(defvar magit-diff-options nil) - -(defun magit-insert-diff (file status) - (let ((cmd magit-git-executable) - (args (append (list "diff") - (list (magit-diff-U-arg)) - magit-diff-options - (list "--" file)))) - (let ((p (point))) - (magit-git-insert args) - (if (not (eq (char-before) ?\n)) - (insert "\n")) - (save-restriction - (narrow-to-region p (point)) - (goto-char p) - (cond - ((eq status 'typechange) - (magit-insert-diff-title status file file) - (magit-wash-typechange-section file)) - (t - (magit-wash-diff-section))) - (goto-char (point-max)))))) - -(defvar magit-last-raw-diff nil) -(defvar magit-ignore-unmerged-raw-diffs nil) - -(defun magit-wash-raw-diffs () - (let ((magit-last-raw-diff nil)) - (magit-wash-sequence #'magit-wash-raw-diff))) - -(defun magit-wash-raw-diff () - (if (looking-at - ":\\([0-7]+\\) \\([0-7]+\\) [0-9a-f]+ [0-9a-f]+ \\(.\\)[0-9]*\t\\([^\t\n]+\\)$") - (let ((old-perm (match-string-no-properties 1)) - (new-perm (match-string-no-properties 2)) - (status (case (string-to-char (match-string-no-properties 3)) - (?A 'new) - (?D 'deleted) - (?M 'modified) - (?U 'unmerged) - (?T 'typechange) - (t nil))) - (file (match-string-no-properties 4))) - ;; If this is for the same file as the last diff, ignore it. - ;; Unmerged files seem to get two entries. - ;; We also ignore unmerged files when told so. - (if (or (equal file magit-last-raw-diff) - (and magit-ignore-unmerged-raw-diffs (eq status 'unmerged))) - (delete-region (point) (+ (line-end-position) 1)) - (setq magit-last-raw-diff file) - ;; The 'diff' section that is created here will not work with - ;; magit-insert-diff-item-patch etc when we leave it empty. - ;; Luckily, raw diffs are only produced for staged and - ;; unstaged changes, and we never call - ;; magit-insert-diff-item-patch on them. This is a bit - ;; brittle, of course. - (let ((magit-section-hidden-default magit-hide-diffs)) - (magit-with-section file 'diff - (delete-region (point) (+ (line-end-position) 1)) - (if (not (magit-section-hidden magit-top-section)) - (magit-insert-diff file status) - (magit-set-section-info (list status file nil)) - (magit-set-section-needs-refresh-on-show t) - (magit-insert-diff-title status file nil))))) - t) - nil)) - -(defun magit-hunk-item-diff (hunk) - (let ((diff (magit-section-parent hunk))) - (or (eq (magit-section-type diff) 'diff) - (error "Huh? Parent of hunk not a diff")) - diff)) - -(defun magit-diff-item-insert-header (diff buf) - (let ((beg (save-excursion - (goto-char (magit-section-beginning diff)) - (forward-line) - (point))) - (end (if (magit-section-children diff) - (magit-section-beginning (car (magit-section-children diff))) - (magit-section-end diff)))) - (magit-insert-region beg end buf))) - -(defun magit-insert-diff-item-patch (diff buf) - (let ((beg (save-excursion - (goto-char (magit-section-beginning diff)) - (forward-line) - (point))) - (end (magit-section-end diff))) - (magit-insert-region beg end buf))) - -(defun magit-insert-hunk-item-patch (hunk buf) - (magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf) - (magit-insert-region (magit-section-beginning hunk) (magit-section-end hunk) - buf)) - -(defun magit-insert-hunk-item-region-patch (hunk reverse beg end buf) - (magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf) - (save-excursion - (goto-char (magit-section-beginning hunk)) - (magit-insert-current-line buf) - (forward-line) - (let ((copy-op (if reverse "+" "-"))) - (while (< (point) (magit-section-end hunk)) - (if (and (<= beg (point)) (< (point) end)) - (magit-insert-current-line buf) - (cond ((looking-at " ") - (magit-insert-current-line buf)) - ((looking-at copy-op) - (let ((text (buffer-substring-no-properties - (+ (point) 1) (line-beginning-position 2)))) - (with-current-buffer buf - (insert " " text)))))) - (forward-line)))) - (with-current-buffer buf - (diff-fixup-modifs (point-min) (point-max)))) - -(defun magit-hunk-item-is-conflict-p (hunk) - ;;; XXX - Using the title is a bit too clever... - (string-match "^diff --cc" - (magit-section-title (magit-hunk-item-diff hunk)))) - -(defun magit-hunk-item-target-line (hunk) - (save-excursion - (beginning-of-line) - (let ((line (line-number-at-pos))) - (goto-char (magit-section-beginning hunk)) - (if (not (looking-at "@@+ .* \\+\\([0-9]+\\)\\(,[0-9]+\\)? @@+")) - (error "Hunk header not found")) - (let ((target (string-to-number (match-string 1)))) - (forward-line) - (while (< (line-number-at-pos) line) - ;; XXX - deal with combined diffs - (if (not (looking-at "-")) - (setq target (+ target 1))) - (forward-line)) - target)))) - -(defun magit-show (commit filename &optional select prefix) - "Returns a buffer containing the contents of the file FILENAME, as stored in -COMMIT. COMMIT may be one of the following: - -- A string with the name of a commit, such as \"head\" or \"dae86e\". See 'git - help revisions' for syntax. -- The symbol 'index, indicating that you want the version in Git's index or - staging area. -- The symbol 'working, indicating that you want the version in the working - directory. In this case you'll get a buffer visiting the file. If there's - already a buffer visiting that file, you'll get that one. - -When called interactively or when SELECT is non-nil, make the buffer active, -either in another window or (with a prefix argument) in the current window." - (interactive (let* ((revision (magit-read-rev "Retrieve file from revision")) - (filename (magit-read-file-from-rev revision))) - (list revision filename t current-prefix-arg))) - (if (eq commit 'working) - (find-file-noselect filename) - (let ((buffer (create-file-buffer (format "%s.%s" filename (replace-regexp-in-string ".*/" "" (prin1-to-string commit t)))))) - (cond - ((eq commit 'index) - (let ((checkout-string (magit-git-string "checkout-index" - "--temp" - filename))) - (string-match "^\\(.*\\)\t" checkout-string) - (with-current-buffer buffer - (let ((tmpname (match-string 1 checkout-string))) - (magit-with-silent-modifications - (insert-file-contents tmpname nil nil nil t)) - (delete-file tmpname))))) - (t - (with-current-buffer buffer - (magit-with-silent-modifications - (magit-git-insert (list "cat-file" "-p" - (concat commit ":" filename))))))) - (with-current-buffer buffer - (let ((buffer-file-name filename)) - (normal-mode)) - (goto-char (point-min))) - (if select - (if prefix - (switch-to-buffer buffer) - (switch-to-buffer-other-window buffer)) - buffer)))) - -(defmacro with-magit-tmp-buffer (var &rest body) - (declare (indent 1) - (debug (symbolp &rest form))) - `(let ((,var (generate-new-buffer magit-tmp-buffer-name))) - (unwind-protect - (progn ,@body) - (kill-buffer ,var)))) - -(defun magit-apply-diff-item (diff &rest args) - (when (zerop magit-diff-context-lines) - (setq args (cons "--unidiff-zero" args))) - (with-magit-tmp-buffer tmp - (magit-insert-diff-item-patch diff tmp) - (apply #'magit-run-git-with-input tmp - "apply" (append args (list "-"))))) - -(defun magit-apply-hunk-item* (hunk reverse &rest args) - "Apply single hunk or part of a hunk to the index or working file. - -This function is the core of magit's stage, unstage, apply, and -revert operations. HUNK (or the portion of it selected by the -region) will be applied to either the index, if \"--cached\" is a -member of ARGS, or to the working file otherwise." - (let ((zero-context (zerop magit-diff-context-lines)) - (use-region (magit-use-region-p))) - (when zero-context - (setq args (cons "--unidiff-zero" args))) - (when reverse - (setq args (cons "--reverse" args))) - (when (and use-region zero-context) - (error (concat "Not enough context to partially apply hunk. " - "Use `+' to increase context."))) - (with-magit-tmp-buffer tmp - (if use-region - (magit-insert-hunk-item-region-patch - hunk reverse (region-beginning) (region-end) tmp) - (magit-insert-hunk-item-patch hunk tmp)) - (apply #'magit-run-git-with-input tmp - "apply" (append args (list "-")))))) - -(defun magit-apply-hunk-item (hunk &rest args) - (apply #'magit-apply-hunk-item* hunk nil args)) - -(defun magit-apply-hunk-item-reverse (hunk &rest args) - (apply #'magit-apply-hunk-item* hunk t args)) - -(magit-define-inserter unstaged-changes (title) - (let ((magit-hide-diffs t) - (magit-current-diff-range (cons 'index 'working))) - (let ((magit-diff-options (append '() magit-diff-options))) - (magit-git-section 'unstaged title 'magit-wash-raw-diffs - "diff-files")))) - -(magit-define-inserter staged-changes (staged no-commit) - (let ((magit-current-diff-range (cons "HEAD" 'index))) - (when staged - (let ((magit-hide-diffs t) - (base (if no-commit - (magit-git-string "mktree") - "HEAD"))) - (let ((magit-diff-options (append '("--cached") magit-diff-options)) - (magit-ignore-unmerged-raw-diffs t)) - (magit-git-section 'staged "Staged changes:" 'magit-wash-raw-diffs - "diff-index" "--cached" - base)))))) - -;;; Logs and Commits - - ; Note: making this a plain defcustom would probably let users break - ; the parser too easily -(defvar magit-git-log-options - (list - "--pretty=format:* %h %s" - (format "--abbrev=%s" magit-sha1-abbrev-length))) - ; --decorate=full otherwise some ref prefixes are stripped - ; '("--pretty=format:* %H%d %s" "--decorate=full")) - -;; -;; Regexps for parsing ref names -;; -;; see the `git-check-ref-format' manpage for details - -(defconst magit-ref-nonchars "\000-\037\177 ~^:?*[\\" - "Characters specifically disallowed from appearing in Git symbolic refs. - -Evaluate (man \"git-check-ref-format\") for details") - -(defconst magit-ref-nonslash-re - (concat "\\(?:" - ;; "no slash-separated component can begin with a dot ." (rule 1) - "[^" magit-ref-nonchars "./]" - ;; "cannot have two consecutive dots .. anywhere." (rule 3) - "\\.?" - "\\)*") - "Regexp that matches the non-slash parts of a ref name. - -Evaluate (man \"git-check-ref-format\") for details") - -(defconst magit-refname-re - (concat - "\\(?:HEAD\\|" - - "\\(?:tag: \\)?" - - ;; optional non-slash sequence at the beginning - magit-ref-nonslash-re - - ;; any number of slash-prefixed sequences - "\\(?:" - "/" - magit-ref-nonslash-re - "\\)*" - - "/" ;; "must contain at least one /." (rule 2) - magit-ref-nonslash-re - - ;; "cannot end with a slash / nor a dot .." (rule 5) - "[^" magit-ref-nonchars "./]" - - "\\)" - ) - "Regexp that matches a git symbolic reference name. - -Evaluate (man \"git-check-ref-format\") for details") - -(defconst magit-log-oneline-re - (concat - "^\\([_\\*|/ -.]+\\)?" ; graph (1) - "\\(?:" - "\\([0-9a-fA-F]+\\)" ; sha1 (2) - "\\(?:" ; refs (3) - " " - "\\(" - "(" - magit-refname-re "\\(?:, " magit-refname-re "\\)*" - ")" - "\\)" - "\\)?" - "\\)?" - " ?\\(.*\\)$" ; msg (4) - )) - -(defconst magit-log-longline-re - (concat - ;; use \0 delimiter (from -z option) to identify commits. this prevents - ;; commit messages containing lines like "commit 00000" from polluting the - ;; display - "\\(?:\\(?:\\`\\|\0\\)" - "\\([_\\*|/ -.]+\\)?" ; graph (1) - "commit " - "\\([0-9a-fA-F]+\\)" ; sha1 (2) - "\\(?:" ; refs (3) - " " - "\\(" - "(" - magit-refname-re "\\(?:, " magit-refname-re "\\)*" - ")" - "\\)" - "\\)?" - "$\\)?" - " ?\\(.*\\)$" ; msg (4) - )) - -(defvar magit-present-log-line-function 'magit-present-log-line - "The function to use when generating a log line. -It takes four args: CHART, SHA1, REFS and MESSAGE. The function -must return a string which will represent the log line.") - -(defun magit-log-get-bisect-state-color (suffix) - (if (string= suffix "bad") - (list suffix 'magit-log-head-label-bisect-bad) - (list suffix 'magit-log-head-label-bisect-good))) - -(defun magit-log-get-patches-color (suffix) - (list (and (string-match ".+/\\(.+\\)" suffix) - (match-string 1 suffix)) - 'magit-log-head-label-patches)) - -(defvar magit-log-remotes-color-hook nil) - -(defun magit-log-get-remotes-color (suffix) - (or - (run-hook-with-args-until-success - 'magit-log-remotes-color-hook suffix) - (list suffix 'magit-log-head-label-remote))) - -(defvar magit-refs-namespaces - '(("tags" . magit-log-head-label-tags) - ("remotes" magit-log-get-remotes-color) - ("heads" . magit-log-head-label-local) - ("patches" magit-log-get-patches-color) - ("bisect" magit-log-get-bisect-state-color))) - -(defun magit-ref-get-label-color (r) - (let ((uninteresting (loop for re in magit-uninteresting-refs - thereis (string-match re r)))) - (if uninteresting (list nil nil) - (let* ((ref-re "\\(?:tag: \\)?refs/\\(?:\\([^/]+\\)/\\)?\\(.+\\)") - (label (and (string-match ref-re r) - (match-string 2 r))) - (res (let ((colorizer - (cdr (assoc (match-string 1 r) - magit-refs-namespaces)))) - (cond ((null colorizer) - (list r 'magit-log-head-label-default)) - ((symbolp colorizer) - (list label colorizer)) - ((listp colorizer) - (funcall (car colorizer) - (match-string 2 r))) - (t - (list r 'magit-log-head-label-default)))))) - res)))) - -(defun magit-present-log-line (graph sha1 refs message) - "The default log line generator." - (let ((string-refs - (when refs - (let ((colored-labels - (delete nil - (mapcar (lambda (r) - (destructuring-bind (label face) - (magit-ref-get-label-color r) - (and label - (propertize label 'face face)))) - refs)))) - (concat - (mapconcat 'identity colored-labels " ") - " "))))) - - (concat - (if sha1 - (propertize sha1 'face 'magit-log-sha1) - (insert-char ? magit-sha1-abbrev-length)) - " " - (when graph - (propertize graph 'face 'magit-log-graph)) - string-refs - (when message - (propertize message 'face 'magit-log-message))))) - -(defvar magit-log-count () - "Internal var used to count the number of logs actually added in a buffer.") - -(defmacro magit-create-log-buffer-sections (&rest body) - "Empty current buffer of text and magit's section, and then evaluate BODY. - -if the number of logs inserted in the buffer is `magit-log-cutoff-length' -insert a line to tell how to insert more of them" - (declare (indent 0)) - `(let ((magit-log-count 0) (inhibit-read-only t)) - (magit-create-buffer-sections - (magit-with-section 'log nil - ,@body - (if (= magit-log-count magit-log-cutoff-length) - (magit-with-section "longer" 'longer - (insert "type \"e\" to show more logs\n"))))))) - -(defun magit-wash-log-line (style) - (beginning-of-line) - (let ((line-re (cond ((eq style 'long) magit-log-longline-re) - (t magit-log-oneline-re)))) - (cond - ((looking-at line-re) - (let ((chart (match-string 1)) - (sha1 (match-string 2)) - (msg (match-string 4)) - (refs (when (match-string 3) - (delq nil - (mapcar - (lambda (s) - (and (not - (or (string= s "tag:") - (string= s "HEAD"))) ; as of 1.6.6 - s)) - (split-string (match-string 3) "[(), ]" t)))))) - (delete-region (point-at-bol) (point-at-eol)) - (insert (funcall magit-present-log-line-function chart sha1 refs msg)) - (goto-char (point-at-bol)) - (if sha1 - (magit-with-section sha1 'commit - (when magit-log-count (setq magit-log-count (1+ magit-log-count))) - (magit-set-section-info sha1) - (forward-line)) - (forward-line)))) - (t - (forward-line))) - t)) - -(defun magit-wash-log (&optional style) - (let ((magit-old-top-section nil)) - (magit-wash-sequence (apply-partially 'magit-wash-log-line style)))) - -(defvar magit-currently-shown-commit nil) - -(defun magit-wash-commit () - (let ((magit-current-diff-range)) - (when (looking-at "^commit \\([0-9a-fA-F]\\{40\\}\\)") - (setq magit-current-diff-range (match-string 1)) - (add-text-properties (match-beginning 1) (match-end 1) - '(face magit-log-sha1))) - (cond - ((search-forward-regexp "^Merge: \\([0-9a-fA-F]+\\) \\([0-9a-fA-F]+\\)$" nil t) - (setq magit-current-diff-range (cons (cons (match-string 1) - (match-string 2)) - magit-current-diff-range)) - (let ((first (magit-set-section nil 'commit (match-beginning 1) (match-end 1))) - (second (magit-set-section nil 'commit (match-beginning 2) (match-end 2)))) - (magit-set-section-info (match-string 1) first) - (magit-set-section-info (match-string 2) second)) - (make-commit-button (match-beginning 1) (match-end 1)) - (make-commit-button (match-beginning 2) (match-end 2))) - (t - (setq magit-current-diff-range (cons (concat magit-current-diff-range "^") - magit-current-diff-range)))) - (search-forward-regexp "^$") - (while (and - (search-forward-regexp "\\(\\b[0-9a-fA-F]\\{4,40\\}\\b\\)\\|\\(^diff\\)" nil 'noerror) - (not (match-string 2))) - (let ((sha1 (match-string 1)) - (start (match-beginning 1)) - (end (match-end 1))) - (when (string-equal "commit" (magit-git-string "cat-file" "-t" sha1)) - (make-commit-button start end) - (let ((section (magit-set-section sha1 'commit start end))) - (magit-set-section-info sha1 section))))) - (beginning-of-line) - (when (looking-at "^diff") - (magit-wash-diffs)) - (goto-char (point-max)) - (insert "\n") - (if magit-back-navigation-history - (magit-with-section "[back]" 'button - (insert-text-button "[back]" - 'help-echo "Previous commit" - 'action 'magit-show-commit-backward - 'follow-link t - 'mouse-face 'magit-item-highlight))) - (insert " ") - (if magit-forward-navigation-history - (magit-with-section "[forward]" 'button - (insert-text-button "[forward]" - 'help-echo "Next commit" - 'action 'magit-show-commit-forward - 'follow-link t - 'mouse-face 'magit-item-highlight))))) - -(defun make-commit-button (start end) - (make-text-button start end - 'help-echo "Visit commit" - 'action (lambda (button) - (save-excursion - (goto-char button) - (magit-visit-item))) - 'follow-link t - 'mouse-face 'magit-item-highlight - 'face 'magit-log-sha1)) - -(defun magit-refresh-commit-buffer (commit) - (magit-configure-have-abbrev) - (magit-configure-have-decorate) - (magit-create-buffer-sections - (apply #'magit-git-section nil nil - 'magit-wash-commit - "log" - "--max-count=1" - "--pretty=medium" - `(,@(if magit-have-abbrev (list "--no-abbrev-commit")) - ,@(if magit-have-decorate (list "--decorate=full")) - "--cc" - "-p" ,commit)))) - -(define-derived-mode magit-commit-mode magit-mode "Magit" - "Mode to view a git commit. - -\\{magit-commit-mode-map}" - :group 'magit) - -(defvar magit-commit-buffer-name "*magit-commit*" - "Buffer name for displaying commit log messages.") - -(defun magit-show-commit (commit &optional scroll inhibit-history select) - "Show information about a commit in the buffer named by -`magit-commit-buffer-name'. COMMIT can be any valid name for a commit -in the current Git repository. - -When called interactively or when SELECT is non-nil, switch to -the commit buffer using `pop-to-buffer'. - -Unless INHIBIT-HISTORY is non-nil, the commit currently shown -will be pushed onto `magit-back-navigation-history' and -`magit-forward-navigation-history' will be cleared. - -Noninteractively, if the commit is already displayed and SCROLL -is provided, call SCROLL's function definition in the commit -window. (`scroll-up' and `scroll-down' are typically passed in -for this argument.)" - (interactive (list (magit-read-rev "Show commit (hash or ref)") - nil nil t)) - (when (magit-section-p commit) - (setq commit (magit-section-info commit))) - (unless (eql 0 (magit-git-exit-code "cat-file" "commit" commit)) - (error "%s is not a commit" commit)) - (let ((dir default-directory) - (buf (get-buffer-create magit-commit-buffer-name))) - (cond - ((and (equal magit-currently-shown-commit commit) - ;; if it's empty then the buffer was killed - (with-current-buffer buf - (> (length (buffer-string)) 1))) - (let ((win (get-buffer-window buf))) - (cond ((not win) - (display-buffer buf)) - (scroll - (with-selected-window win - (funcall scroll)))))) - (commit - (display-buffer buf) - (with-current-buffer buf - (unless inhibit-history - (push (cons default-directory magit-currently-shown-commit) - magit-back-navigation-history) - (setq magit-forward-navigation-history nil)) - (setq magit-currently-shown-commit commit) - (goto-char (point-min)) - (magit-mode-init dir 'magit-commit-mode - #'magit-refresh-commit-buffer commit)))) - (if select - (pop-to-buffer buf)))) - -(defun magit-show-commit-backward (&optional ignored) - ;; Ignore argument passed by push-button - "Show the commit at the head of `magit-back-navigation-history in -`magit-commit-buffer-name`." - (interactive) - (with-current-buffer magit-commit-buffer-name - (unless magit-back-navigation-history - (error "No previous commit.")) - (let ((histitem (pop magit-back-navigation-history))) - (push (cons default-directory magit-currently-shown-commit) - magit-forward-navigation-history) - (setq default-directory (car histitem)) - (magit-show-commit (cdr histitem) nil 'inhibit-history)))) - -(defun magit-show-commit-forward (&optional ignored) - ;; Ignore argument passed by push-button - "Show the commit at the head of `magit-forward-navigation-history in -`magit-commit-buffer-name`." - (interactive) - (with-current-buffer magit-commit-buffer-name - (unless magit-forward-navigation-history - (error "No next commit.")) - (let ((histitem (pop magit-forward-navigation-history))) - (push (cons default-directory magit-currently-shown-commit) - magit-back-navigation-history) - (setq default-directory (car histitem)) - (magit-show-commit (cdr histitem) nil 'inhibit-history)))) - -(defvar magit-marked-commit nil) - -(defvar magit-mark-overlay nil) -(make-variable-buffer-local 'magit-mark-overlay) -(put 'magit-mark-overlay 'permanent-local t) - -(defun magit-refresh-marked-commits () - (magit-for-all-buffers #'magit-refresh-marked-commits-in-buffer)) - -(defun magit-refresh-marked-commits-in-buffer () - (if (not magit-mark-overlay) - (let ((ov (make-overlay 1 1))) - (overlay-put ov 'face 'magit-item-mark) - (setq magit-mark-overlay ov))) - (delete-overlay magit-mark-overlay) - (magit-for-all-sections - (lambda (section) - (when (and (eq (magit-section-type section) 'commit) - (equal (magit-section-info section) - magit-marked-commit)) - (move-overlay magit-mark-overlay - (magit-section-beginning section) - (magit-section-end section) - (current-buffer)))))) - -(defun magit-set-marked-commit (commit) - (setq magit-marked-commit commit) - (magit-refresh-marked-commits)) - -(defun magit-marked-commit () - (or magit-marked-commit - (error "No commit marked"))) - -(defun magit-remote-branch-name (remote branch) - "Get the name of the branch BRANCH on remote REMOTE" - (if (string= remote ".") - branch - (concat remote "/" branch))) - -(magit-define-inserter unpulled-commits (remote branch) - (when remote - (apply #'magit-git-section - 'unpulled "Unpulled commits:" 'magit-wash-log "log" - (append magit-git-log-options - (list - (format "HEAD..%s" (magit-remote-branch-name remote branch))))))) - -(magit-define-inserter unpushed-commits (remote branch) - (when remote - (apply #'magit-git-section - 'unpushed "Unpushed commits:" 'magit-wash-log "log" - (append magit-git-log-options - (list - (format "%s..HEAD" (magit-remote-branch-name remote branch))))))) - -(defun magit-remote-branch-for (local-branch &optional fully-qualified-name) - "Guess the remote branch name that LOCAL-BRANCH is tracking. -Gives a fully qualified name (e.g., refs/remotes/origin/master) if -FULLY-QUALIFIED-NAME is non-nil." - (let ((merge (magit-get "branch" local-branch "merge"))) - (save-match-data - (if (and merge (string-match "^refs/heads/\\(.+\\)" merge)) - (concat (if fully-qualified-name - (let ((remote-name (magit-get "branch" local-branch "remote"))) - (if (string= "." remote-name) - "refs/heads/" - (concat "refs/remotes/" remote-name "/")))) - (match-string 1 merge)))))) - -;;; Status - -(defvar magit-remote-string-hook nil) - -(defun magit-remote-string (remote remote-branch remote-rebase) - (cond - ((string= "." remote) - (concat - (when remote-rebase "onto ") - "branch " - (propertize remote-branch 'face 'magit-branch))) - (remote - (concat - (when remote-rebase "onto ") - (propertize remote-branch 'face 'magit-branch) - " @ " - remote - " (" - (magit-get "remote" remote "url") - ")")) - (t - (run-hook-with-args-until-success 'magit-remote-string-hook)))) - -(declare-function magit--bisect-info-for-status "magit-bisect" (branch)) - -(defun magit-refresh-status () - (magit-create-buffer-sections - (magit-with-section 'status nil - (let* ((branch (magit-get-current-branch)) - (remote (and branch (magit-get "branch" branch "remote"))) - (remote-rebase (and branch (magit-get-boolean "branch" branch "rebase"))) - (remote-branch (or (and branch (magit-remote-branch-for branch)) branch)) - (remote-string (magit-remote-string remote remote-branch remote-rebase)) - (head (magit-git-string - "log" - "--max-count=1" - "--abbrev-commit" - (format "--abbrev=%s" magit-sha1-abbrev-length) - "--pretty=oneline")) - (no-commit (not head))) - (when remote-string - (insert "Remote: " remote-string "\n")) - (insert (format "Local: %s %s\n" - (propertize (magit--bisect-info-for-status branch) - 'face 'magit-branch) - (abbreviate-file-name default-directory))) - (insert (format "Head: %s\n" - (if no-commit "nothing commited (yet)" head))) - (let ((merge-heads (magit-file-lines (concat (magit-git-dir) - "MERGE_HEAD")))) - (if merge-heads - (insert (format "Merging: %s\n" - (mapconcat 'identity - (mapcar 'magit-name-rev merge-heads) - ", "))))) - (let ((rebase (magit-rebase-info))) - (if rebase - (insert (apply 'format "Rebasing: onto %s (%s of %s); Press \"R\" to Abort, Skip, or Continue\n" rebase)))) - (insert "\n") - (magit-git-exit-code "update-index" "--refresh") - (magit-insert-stashes) - (magit-insert-untracked-files) - (magit-insert-pending-changes) - (magit-insert-pending-commits) - (magit-insert-unpulled-commits remote remote-branch) - (let ((staged (or no-commit (magit-anything-staged-p)))) - (magit-insert-unstaged-changes - (if staged "Unstaged changes:" "Changes:")) - (magit-insert-staged-changes staged no-commit)) - (magit-insert-unpushed-commits remote remote-branch) - (run-hooks 'magit-refresh-status-hook))))) - -(defun magit-init (dir) - "Initialize git repository in the DIR directory." - (interactive (list (read-directory-name "Directory for Git repository: "))) - (let* ((dir (file-name-as-directory (expand-file-name dir))) - (topdir (magit-get-top-dir dir))) - (when (or (not topdir) - (yes-or-no-p - (format - (if (string-equal topdir dir) - "There is already a Git repository in %s. Reinitialize? " - "There is a Git repository in %s. Create another in %s? ") - topdir dir))) - (unless (file-directory-p dir) - (and (y-or-n-p (format "Directory %s does not exists. Create it? " dir)) - (make-directory dir))) - (let ((default-directory dir)) - (magit-run* (list magit-git-executable "init")))))) - -(define-derived-mode magit-status-mode magit-mode "Magit" - "Mode for looking at git status. - -\\{magit-status-mode-map}" - :group 'magit) - -(defvar magit-default-directory nil) - -(defun magit-save-some-buffers (&optional msg pred) - "Save some buffers if variable `magit-save-some-buffers' is non-nil. -If variable `magit-save-some-buffers' is set to 'dontask then -don't ask the user before saving the buffers, just go ahead and -do it. - -Optional argument MSG is displayed in the minibuffer if variable -`magit-save-some-buffers' is nil. - -Optional second argument PRED determines which buffers are considered: -If PRED is nil, all the file-visiting buffers are considered. -If PRED is t, then certain non-file buffers will also be considered. -If PRED is a zero-argument function, it indicates for each buffer whether -to consider it or not when called with that buffer current." - (interactive) - (let ((predicate-function (or pred magit-save-some-buffers-predicate)) - (magit-default-directory default-directory)) - (if magit-save-some-buffers - (save-some-buffers - (eq magit-save-some-buffers 'dontask) - predicate-function) - (when msg - (message msg))))) - -(defun magit-save-buffers-predicate-all () - "Prompt to save all buffers with unsaved changes" - t) - -(defun magit-save-buffers-predicate-tree-only () - "Only prompt to save buffers which are within the current git project (as - determined by the dir passed to `magit-status'." - (and buffer-file-name - (string= (magit-get-top-dir magit-default-directory) - (magit-get-top-dir (file-name-directory buffer-file-name))))) - -;;;###autoload -(defun magit-status (dir) - "Open a Magit status buffer for the Git repository containing -DIR. If DIR is not within a Git repository, offer to create a -Git repository in DIR. - -Interactively, a prefix argument means to ask the user which Git -repository to use even if `default-directory' is under Git control. -Two prefix arguments means to ignore `magit-repo-dirs' when asking for -user input." - (interactive (list (if current-prefix-arg - (magit-read-top-dir - (> (prefix-numeric-value current-prefix-arg) - 4)) - (or (magit-get-top-dir default-directory) - (magit-read-top-dir nil))))) - (magit-save-some-buffers) - (let ((topdir (magit-get-top-dir dir))) - (unless topdir - (when (y-or-n-p (format "There is no Git repository in %S. Create one? " - dir)) - (magit-init dir) - (setq topdir (magit-get-top-dir dir)))) - (when topdir - (let ((buf (or (magit-find-status-buffer topdir) - (generate-new-buffer - (concat "*magit: " - (file-name-nondirectory - (directory-file-name topdir)) "*"))))) - (funcall magit-status-buffer-switch-function buf) - (magit-mode-init topdir 'magit-status-mode #'magit-refresh-status))))) - -(magit-define-command automatic-merge (revision) - "Merge REVISION into the current 'HEAD'; commit unless merge fails. -\('git merge REVISION')." - (interactive (list (magit-read-rev "Merge" (magit-guess-branch)))) - (if revision - (magit-run-git "merge" (magit-rev-to-git revision)))) - -(magit-define-command manual-merge (revision) - "Merge REVISION into the current 'HEAD'; commit unless merge fails. -\('git merge REVISION')." - (interactive (list (magit-read-rev "Merge" (magit-guess-branch)))) - (when revision - (apply 'magit-run-git - "merge" "--no-commit" - (magit-rev-to-git revision) - magit-custom-options) - (when (file-exists-p ".git/MERGE_MSG") - (magit-log-edit)))) - -;;; Staging and Unstaging - -(defun magit-stage-item (&optional ask) - "Add the item at point to the staging area. -If ASK is set, ask for the file name rather than picking the one -at point." - (interactive "P") - (if ask - (magit-run-git "add" (read-file-name "File to stage: ")) - (magit-section-action (item info "stage") - ((untracked file) - (magit-run-git "add" info)) - ((untracked) - (apply #'magit-run-git "add" "--" - (magit-git-lines "ls-files" "--other" "--exclude-standard"))) - ((unstaged diff hunk) - (if (magit-hunk-item-is-conflict-p item) - (error (concat "Can't stage individual resolution hunks. " - "Please stage the whole file."))) - (magit-apply-hunk-item item "--cached")) - ((unstaged diff) - (magit-run-git "add" "-u" (magit-diff-item-file item))) - ((staged *) - (error "Already staged")) - ((diff diff) - (save-excursion - (magit-goto-parent-section) - (magit-stage-item))) - ((diff diff hunk) - (save-excursion - (magit-goto-parent-section) - (magit-goto-parent-section) - (magit-stage-item))) - ((hunk) - (error "Can't stage this hunk")) - ((diff) - (error "Can't stage this diff"))))) - -(defun magit-unstage-item () - "Remove the item at point from the staging area." - (interactive) - (magit-section-action (item info "unstage") - ((staged diff hunk) - (magit-apply-hunk-item-reverse item "--cached")) - ((staged diff) - (if (eq (car info) 'unmerged) - (error "Can't unstage an unmerged file. Resolve it first")) - (if (magit-no-commit-p) - (magit-run-git "rm" "--cached" "--" (magit-diff-item-file item)) - (magit-run-git "reset" "-q" "HEAD" "--" (magit-diff-item-file item)))) - ((unstaged *) - (error "Already unstaged")) - ((diff diff) - (save-excursion - (magit-goto-parent-section) - (magit-unstage-item))) - ((diff diff hunk) - (save-excursion - (magit-goto-parent-section) - (magit-goto-parent-section) - (magit-unstage-item))) - ((hunk) - (error "Can't unstage this hunk")) - ((diff) - (error "Can't unstage this diff")))) - -(defun magit-stage-all (&optional also-untracked-p) - "Add all remaining changes in tracked files to staging area. -With prefix argument, add remaining untracked files as well. -\('git add -u .' or 'git add .', respectively)." - (interactive "P") - (if also-untracked-p - (magit-run-git "add" ".") - (magit-run-git "add" "-u" "."))) - -(defun magit-unstage-all () - "Remove all changes from staging area. -\('git reset --mixed HEAD')." - (interactive) - (magit-run-git "reset" "HEAD")) - -;;; Branches - -(defun escape-branch-name (branch) - "Escapes branch names to remove problematic characters." - (replace-regexp-in-string "[/]" "-" branch)) - -(defun magit-default-tracking-name-remote-plus-branch - (remote branch) - "Use the remote name plus a hyphen plus the escaped branch name for tracking branches." - (concat remote "-" (escape-branch-name branch))) - -(defun magit-default-tracking-name-branch-only - (remote branch) - "Use just the escaped branch name for tracking branches." - (escape-branch-name branch)) - -(defun magit-get-tracking-name (remote branch) - "Given a REMOTE and a BRANCH name, ask the user for a local -tracking brach name suggesting a sensible default." - (when (yes-or-no-p - (format "Create local tracking branch for %s? " branch)) - (let* ((default-name - (funcall magit-default-tracking-name-function remote branch)) - (chosen-name (read-string (format "Call local branch (%s): " default-name) - nil - nil - default-name))) - (when (magit-ref-exists-p (concat "refs/heads/" chosen-name)) - (error "'%s' already exists." chosen-name)) - chosen-name))) - -(defun magit-maybe-create-local-tracking-branch (rev) - "Depending on the users wishes, create a tracking branch for -rev... maybe." - (if (string-match "^\\(?:refs/\\)?remotes/\\([^/]+\\)/\\(.+\\)" rev) - (let* ((remote (match-string 1 rev)) - (branch (match-string 2 rev)) - (tracker-name (magit-get-tracking-name remote branch))) - (when tracker-name - (magit-run-git "checkout" "-b" tracker-name rev) - t)) - nil)) - -(magit-define-command checkout (revision) - "Switch 'HEAD' to REVISION and update working tree. -Fails if working tree or staging area contain uncommitted changes. -If REVISION is a remote branch, offer to create a local tracking branch. -\('git checkout [-b] REVISION')." - (interactive - (list (let ((current-branch (magit-get-current-branch)) - (default (magit-default-rev))) - (magit-read-rev "Switch to" - (unless (string= current-branch default) - default) - (if current-branch - (cons (concat "refs/heads/" current-branch "$") - magit-uninteresting-refs) - magit-uninteresting-refs))))) - (if revision - (when (not (magit-maybe-create-local-tracking-branch revision)) - (magit-save-some-buffers) - (magit-run-git "checkout" (magit-rev-to-git revision)) - (magit-update-vc-modeline default-directory)))) - -(defun magit-read-create-branch-args () - (let* ((cur-branch (magit-get-current-branch)) - (cur-point (magit-default-rev)) - (branch (read-string "Create branch: ")) - (parent (magit-read-rev "Parent" - (cond - ((eq magit-create-branch-behaviour 'at-point) cur-point) - ((eq magit-create-branch-behaviour 'at-head) cur-branch) - (t cur-branch))))) - (list branch parent))) - -(magit-define-command create-branch (branch parent) - "Switch 'HEAD' to new BRANCH at revision PARENT and update working tree. -Fails if working tree or staging area contain uncommitted changes. -\('git checkout -b BRANCH REVISION')." - (interactive (magit-read-create-branch-args)) - (when (and branch (not (string= branch "")) - parent) - (magit-save-some-buffers) - (magit-run-git "checkout" "-b" - branch - (append - magit-custom-options - (magit-rev-to-git parent))) - (magit-update-vc-modeline default-directory))) - -(defun magit-delete-branch (branch &optional force) - "Deletes a branch. -If the branch is the current one, offers to switch to `master' first. -With prefix, forces the removal even if it hasn't been merged. -Works with local or remote branches. -\('git branch [-d|-D] BRANCH' or 'git push :refs/heads/BRANCH')." - (interactive (list (magit-read-rev "Branch to delete" (magit-default-rev 'notrim)) - current-prefix-arg)) - (let* ((remote (magit-remote-part-of-branch branch)) - (is-current (string= branch (magit-get-current-branch))) - (args (list "branch" - (if force "-D" "-d") - branch))) - (cond - (remote - (magit-run-git "push" remote (concat ":refs/heads/" (magit-branch-no-remote branch)))) - (is-current - (when (y-or-n-p "Cannot delete current branch. Switch to master first? ") - (progn - (magit-checkout "master") - (apply 'magit-run-git args)) - (message "The current branch was not deleted."))) - (t - (apply 'magit-run-git args))))) - -(defun magit-move-branch (old new &optional force) - "Renames or moves a branch. -With prefix, forces the move even if NEW already exists. -\('git branch [-m|-M] OLD NEW')." - (interactive (list (magit-read-rev "Old name" (magit-default-rev)) - (read-string "New name: ") - current-prefix-arg)) - (magit-run-git "branch" (if force - "-M" - "-m") - (magit-rev-to-git old) new)) - -(defun magit-guess-branch () - (magit-section-case (item info) - ((branch) - (magit-section-info (magit-current-section))) - ((wazzup commit) - (magit-section-info (magit-section-parent item))) - ((commit) (magit-name-rev (substring info 0 magit-sha1-abbrev-length))) - ((wazzup) info))) - -;;; Remotes - -(defun magit-add-remote (remote url) - "Adds a remote and fetches it. -\('git remote add REMOTE URL')." - (interactive (list (read-string "Add remote: ") - (read-string "URL: "))) - (magit-run-git "remote" "add" "-f" remote url)) - -(defun magit-remove-remote (remote) - "Deletes a remote. -\('git remote rm REMOTE')." - (interactive (list (magit-read-remote "Remote to delete"))) - (magit-run-git "remote" "rm" remote)) - -(defun magit-rename-remote (old new) - "Renames a remote. -\('git remote rename OLD NEW')." - (interactive (list (magit-read-remote "Old name") - (read-string "New name: "))) - (magit-run-git "remote" "rename" old new)) - -(defun magit-guess-remote () - (magit-section-case (item info) - ((branch) - (magit-section-info (magit-section-parent item))) - ((remote) - info) - (t - (if (string= info ".") - info - (magit-get-current-remote))))) - -;;; Merging - -(defun magit-merge (revision) - "Merge REVISION into the current 'HEAD'; leave changes uncommitted. -With a prefix-arg, the merge will be squashed. -\('git merge --no-commit [--squash|--no-ff] REVISION')." - (interactive - (list (magit-read-rev "Merge" (magit-default-rev)))) - (if revision - (apply 'magit-run-git - "merge" - (magit-rev-to-git revision) - magit-custom-options))) - -;;; Rebasing - -(defun magit-rebase-info () - "Returns a list indicating the state of an in-progress rebase, -if any." - (let ((git-dir (magit-git-dir))) - (cond ((file-exists-p (concat git-dir "rebase-merge")) - (list - ;; The commit we're rebasing onto, i.e. git rebase -i - (magit-name-rev (car (magit-file-lines (concat git-dir "rebase-merge/onto")))) - - ;; How many commits we've gone through - (length (magit-file-lines (concat git-dir "rebase-merge/done"))) - - ;; How many commits we have in total, without the comments - ;; at the end of git-rebase-todo.backup - (let ((todo-lines-with-comments (magit-file-lines (concat git-dir "rebase-merge/git-rebase-todo.backup")))) - (loop for i in todo-lines-with-comments - until (string= "" i) - count i)))) - ((and (file-exists-p (concat git-dir "rebase-apply")) - (file-exists-p (concat git-dir "rebase-apply/onto"))) - ;; we might be here because a non-interactive rebase failed: the - ;; patches didn't apply cleanly - (list - ;; The commit we're rebasing onto, i.e. git rebase -i - (magit-name-rev (car (magit-file-lines (concat git-dir "rebase-apply/onto")))) - - ;; How many commits we've gone through - (- (string-to-number (car (magit-file-lines (concat git-dir "rebase-apply/next")))) 1) - - ;; How many commits we have in total - (string-to-number (car (magit-file-lines (concat git-dir "rebase-apply/last")))) - )) - (t nil)))) - -(defun magit-rebase-step () - (interactive) - (let ((info (magit-rebase-info))) - (if (not info) - (let* ((current-branch (magit-get-current-branch)) - (rev (magit-read-rev "Rebase to" - (magit-format-ref (magit-remote-branch-for current-branch t)) - (if current-branch - (cons (concat "refs/heads/" current-branch) - magit-uninteresting-refs) - magit-uninteresting-refs)))) - (if rev - (magit-run-git "rebase" (magit-rev-to-git rev)))) - (let ((cursor-in-echo-area t) - (message-log-max nil)) - (message "Rebase in progress. [A]bort, [S]kip, or [C]ontinue? ") - (let ((reply (read-event))) - (case reply - ((?A ?a) - (magit-run-git-async "rebase" "--abort")) - ((?S ?s) - (magit-run-git-async "rebase" "--skip")) - ((?C ?c) - (magit-run-git-async "rebase" "--continue")))))))) - -;;; Resetting - -(magit-define-command reset-head (revision &optional hard) - "Switch 'HEAD' to REVISION, keeping prior working tree and staging area. -Any differences from REVISION become new changes to be committed. -With prefix argument, all uncommitted changes in working tree -and staging area are lost. -\('git reset [--soft|--hard] REVISION')." - (interactive (list (magit-read-rev (format "%s head to" - (if current-prefix-arg - "Hard reset" - "Reset")) - (or (magit-default-rev) - "HEAD^")) - current-prefix-arg)) - (when revision - (magit-run-git "reset" (if hard "--hard" "--soft") - (magit-rev-to-git revision)) - (magit-update-vc-modeline default-directory))) - -(magit-define-command reset-head-hard (revision) - "Switch 'HEAD' to REVISION, losing all changes. -Uncomitted changes in both working tree and staging area are lost. -\('git reset --hard REVISION')." - (interactive (list (magit-read-rev (format "Hard reset head to") - (or (magit-default-rev) - "HEAD")))) - (magit-reset-head revision t)) - -(magit-define-command reset-working-tree (&optional arg) - "Revert working tree and clear changes from staging area. -\('git reset --hard HEAD'). - -With a prefix arg, also remove untracked files. With two prefix args, remove ignored files as well." - (interactive "p") - (let ((include-untracked (>= arg 4)) - (include-ignored (>= arg 16))) - (when (yes-or-no-p (format "Discard all uncommitted changes%s%s? " - (if include-untracked - ", untracked files" - "") - (if include-ignored - ", ignored files" - ""))) - (magit-reset-head-hard "HEAD") - (if include-untracked - (magit-run-git "clean" "-fd" (if include-ignored - "-x" - "")))))) - -;;; Rewriting - -(defun magit-read-rewrite-info () - (when (file-exists-p (concat (magit-git-dir) "magit-rewrite-info")) - (with-temp-buffer - (insert-file-contents (concat (magit-git-dir) "magit-rewrite-info")) - (goto-char (point-min)) - (read (current-buffer))))) - -(defun magit-write-rewrite-info (info) - (with-temp-file (concat (magit-git-dir) "magit-rewrite-info") - (prin1 info (current-buffer)) - (princ "\n" (current-buffer)))) - -(magit-define-inserter pending-commits () - (let* ((info (magit-read-rewrite-info)) - (pending (cdr (assq 'pending info)))) - (when pending - (magit-with-section 'pending nil - (insert (propertize "Pending commits:\n" - 'face 'magit-section-title)) - (dolist (p pending) - (let* ((commit (car p)) - (properties (cdr p)) - (used (plist-get properties 'used))) - (magit-with-section commit 'commit - (magit-set-section-info commit) - (insert (magit-git-string - "log" "--max-count=1" - (if used - "--pretty=format:. %s" - "--pretty=format:* %s") - commit "--") - "\n"))))) - (insert "\n")))) - -(defun magit-rewrite-set-commit-property (commit prop value) - (let* ((info (magit-read-rewrite-info)) - (pending (cdr (assq 'pending info))) - (p (assoc commit pending))) - (when p - (setf (cdr p) (plist-put (cdr p) prop value)) - (magit-write-rewrite-info info) - (magit-need-refresh)))) - -(defun magit-rewrite-set-used () - (interactive) - (magit-section-action (item info) - ((pending commit) - (magit-rewrite-set-commit-property info 'used t)))) - -(defun magit-rewrite-set-unused () - (interactive) - (magit-section-action (item info) - ((pending commit) - (magit-rewrite-set-commit-property info 'used nil)))) - -(magit-define-inserter pending-changes () - (let* ((info (magit-read-rewrite-info)) - (orig (cadr (assq 'orig info)))) - (when orig - (let ((magit-hide-diffs t)) - (magit-git-section 'pending-changes - "Pending changes" - 'magit-wash-diffs - "diff" (magit-diff-U-arg) "-R" orig))))) - -(defun magit-rewrite-start (from &optional onto) - (interactive (list (magit-read-rev "Rewrite from" (magit-default-rev)))) - (or (magit-everything-clean-p) - (error "You have uncommitted changes")) - (or (not (magit-read-rewrite-info)) - (error "Rewrite in progress")) - (let* ((orig (magit-rev-parse "HEAD")) - (base - (if - (or - (eq magit-rewrite-inclusive t) - (and - (eq magit-rewrite-inclusive 'ask) - (y-or-n-p "Include selected revision in rewrite? "))) - (or - (car (magit-commit-parents from)) - (error "Can't rewrite a parentless commit.")) - from)) - (pending (magit-git-lines "rev-list" (concat base "..")))) - (magit-write-rewrite-info `((orig ,orig) - (pending ,@(mapcar #'list pending)))) - (magit-run-git "reset" "--hard" base))) - -(defun magit-rewrite-stop (&optional noconfirm) - (interactive) - (let* ((info (magit-read-rewrite-info))) - (or info - (error "No rewrite in progress")) - (when (or noconfirm - (yes-or-no-p "Stop rewrite? ")) - (magit-write-rewrite-info nil) - (magit-refresh)))) - -(defun magit-rewrite-abort () - (interactive) - (let* ((info (magit-read-rewrite-info)) - (orig (cadr (assq 'orig info)))) - (or info - (error "No rewrite in progress")) - (or (magit-everything-clean-p) - (error "You have uncommitted changes")) - (when (yes-or-no-p "Abort rewrite? ") - (magit-write-rewrite-info nil) - (magit-run-git "reset" "--hard" orig)))) - -(defun magit-rewrite-finish () - (interactive) - (magit-with-refresh - (magit-rewrite-finish-step t))) - -(defun magit-rewrite-finish-step (first-p) - (let ((info (magit-read-rewrite-info))) - (or info - (error "No rewrite in progress")) - (let* ((pending (cdr (assq 'pending info))) - (first-unused - (let ((rpend (reverse pending))) - (while (and rpend (plist-get (cdr (car rpend)) 'used)) - (setq rpend (cdr rpend))) - (car rpend))) - (commit (car first-unused))) - (cond ((not first-unused) - (magit-rewrite-stop t)) - ((magit-apply-commit commit t (not first-p)) - (magit-rewrite-set-commit-property commit 'used t) - (magit-rewrite-finish-step nil)))))) - -;;; Updating, pull, and push - -(magit-define-command fetch (remote) - "Fetch from REMOTE." - (interactive (list (magit-read-remote))) - (apply 'magit-run-git-async "fetch" remote magit-custom-options)) - -(magit-define-command fetch-current () - "Run fetch for default remote. - -If there is no default remote, ask for one." - (interactive) - (magit-fetch (or (magit-get-current-remote) - (magit-read-remote)))) - -(magit-define-command remote-update () - "Update all remotes." - (interactive) - (apply 'magit-run-git-async "remote" "update" magit-custom-options)) - -(magit-define-command pull () - "Run git pull against the current remote." - (interactive) - (let* ((branch (magit-get-current-branch)) - (branch-remote (magit-get-remote branch)) - (config-branch (and branch (magit-get "branch" branch "merge"))) - (merge-branch (or (and config-branch (not current-prefix-arg)) - (magit-read-remote-branch - branch-remote (format "Pull from: "))))) - (when (and branch (not config-branch)) - (magit-set branch-remote "branch" branch "remote") - (magit-set (format "refs/heads/%s" merge-branch) - "branch" branch "merge")) - (apply 'magit-run-git-async "pull" "-v" magit-custom-options))) - -(eval-when-compile (require 'eshell)) - -(defun magit-parse-arguments (command) - (require 'eshell) - (with-temp-buffer - (insert command) - (mapcar 'eval (eshell-parse-arguments (point-min) (point-max))))) - -(defun magit-shell-command (command) - "Perform arbitrary shell COMMAND." - (interactive "sCommand: ") - (let ((args (magit-parse-arguments command)) - (magit-process-popup-time 0)) - (magit-run* args nil nil nil t))) - -(defvar magit-git-command-history nil) - -(defun magit-git-command (command) - "Perform arbitrary Git COMMAND. - -Similar to `magit-shell-command', but involves slightly less -typing and automatically refreshes the status buffer." - (interactive - (list (read-string "Run git like this: " nil 'magit-git-command-history))) - (require 'pcomplete) - (let ((args (magit-parse-arguments command)) - (magit-process-popup-time 0)) - (magit-with-refresh - (magit-run* (append (cons magit-git-executable - magit-git-standard-options) - args) - nil nil nil t)))) - -(magit-define-command push-tags () - "Push tags." - (interactive) - (magit-run-git-async "push" "--tags")) - -(magit-define-command push () - "Push the current branch to a remote repository. - -With no prefix argument, ask `magit-get-remote' what remote to -use for this branch. - -With a prefix arg \(e.g., \\[universal-argument] \\[magit-push]), \ -ask user instead. - -With \\[universal-argument] \\[universal-argument] as prefix, \ -also prompt user for the remote branch; -otherwise, try to use the branch..merge git-config(1) -option, falling back to something hairy if that is unset." - (interactive) - (let* ((branch (or (magit-get-current-branch) - (error "Don't push a detached head. That's gross"))) - (branch-remote (magit-get-remote branch)) - (push-remote (if (or current-prefix-arg - (not branch-remote)) - (magit-read-remote (format "Push %s to remote" - branch) - branch-remote) - branch-remote)) - (ref-branch (or (and (>= (prefix-numeric-value current-prefix-arg) 16) - (magit-read-remote-branch - push-remote (format "Push %s as branch" branch))) - (magit-get "branch" branch "merge")))) - (if (and (not ref-branch) - (eq magit-set-upstream-on-push 'refuse)) - (error "Not pushing since no upstream has been set.") - (let ((set-upstream-on-push (and (not ref-branch) - (or (eq magit-set-upstream-on-push 'dontask) - (and (eq magit-set-upstream-on-push t) - (yes-or-no-p "Set upstream while pushing? ")))))) - (if (and (not branch-remote) - (not current-prefix-arg)) - (magit-set push-remote "branch" branch "remote")) - (apply 'magit-run-git-async "push" "-v" push-remote - (if ref-branch - (format "%s:%s" branch ref-branch) - branch) - (if set-upstream-on-push - (cons "--set-upstream" magit-custom-options) - magit-custom-options)) - ;; Although git will automatically set up the remote, - ;; it doesn't set up the branch to merge (at least as of Git 1.6.6.1), - ;; so we have to do that manually. - (unless ref-branch - (magit-set (concat "refs/heads/" branch) "branch" branch "merge")))))) - -;;; Log edit mode - -(defvar magit-log-edit-buffer-name "*magit-edit-log*" - "Buffer name for composing commit messages.") - -(defvar magit-log-edit-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-c") 'magit-log-edit-commit) - (define-key map (kbd "C-x #") 'magit-log-edit-commit) - (define-key map (kbd "C-c C-a") 'magit-log-edit-toggle-amending) - (define-key map (kbd "C-c C-s") 'magit-log-edit-toggle-signoff) - (define-key map (kbd "C-c C-t") 'magit-log-edit-toggle-author) - (define-key map (kbd "C-c C-e") 'magit-log-edit-toggle-allow-empty) - (define-key map (kbd "M-p") 'log-edit-previous-comment) - (define-key map (kbd "M-n") 'log-edit-next-comment) - (define-key map (kbd "C-c C-k") 'magit-log-edit-cancel-log-message) - (define-key map (kbd "C-c C-]") 'magit-log-edit-cancel-log-message) - (define-key map (kbd "C-x C-s") (lambda () - (interactive) - (message "Not saved. Use C-c C-c to finalize this commit message."))) - map)) - -(defvar magit-pre-log-edit-window-configuration nil) - -(define-derived-mode magit-log-edit-mode text-mode "Magit Log Edit" - ;; Recognize changelog-style paragraphs - (set (make-local-variable 'paragraph-start) - (concat paragraph-start "\\|*\\|("))) - -(defun magit-log-edit-cleanup () - (save-excursion - (goto-char (point-min)) - (goto-char (point-min)) - (if (re-search-forward "[ \t\n]*\\'" nil t) - (replace-match "\n" nil nil)))) - -(defun magit-log-edit-append (str) - (with-current-buffer (get-buffer-create magit-log-edit-buffer-name) - (goto-char (point-max)) - (insert str "\n"))) - -(defconst magit-log-header-end "-- End of Magit header --\n") - -(defun magit-log-edit-get-fields () - (let ((buf (get-buffer magit-log-edit-buffer-name)) - (result nil)) - (if buf - (with-current-buffer buf - (goto-char (point-min)) - (while (looking-at "^\\([A-Za-z0-9-_]+\\): *\\(.+\\)?$") - (setq result (acons (intern (downcase (match-string 1))) - (read (or (match-string 2) "nil")) - result)) - (forward-line)) - (if (not (looking-at (regexp-quote magit-log-header-end))) - (setq result nil)))) - (nreverse result))) - -(defun magit-log-edit-set-fields (fields) - (let ((buf (get-buffer-create magit-log-edit-buffer-name))) - (with-current-buffer buf - (goto-char (point-min)) - (if (search-forward-regexp (format "^\\([A-Za-z0-9-_]+:.*\n\\)*%s" - (regexp-quote magit-log-header-end)) - nil t) - (delete-region (match-beginning 0) (match-end 0))) - (goto-char (point-min)) - (when fields - (while fields - (insert (capitalize (symbol-name (caar fields))) ": " - (prin1-to-string (cdar fields)) "\n") - (setq fields (cdr fields))) - (insert magit-log-header-end))))) - -(defun magit-log-edit-set-field (name value) - (let* ((fields (magit-log-edit-get-fields)) - (cell (assq name fields))) - (cond (cell - (if value - (rplacd cell value) - (setq fields (delq cell fields)))) - (t - (if value - (setq fields (append fields (list (cons name value))))))) - (magit-log-edit-set-fields fields))) - -(defun magit-log-edit-get-field (name) - (cdr (assq name (magit-log-edit-get-fields)))) - -(defun magit-log-edit-toggle-field (name default) - "Toggle the log-edit field named NAME. -If it's currently unset, set it to DEFAULT (t or nil). - -Return nil if the field is toggled off, and non-nil if it's -toggled on. When it's toggled on for the first time, return -'first." - (let* ((fields (magit-log-edit-get-fields)) - (cell (assq name fields)) yesp) - (if cell - (progn - (setq yesp (equal (cdr cell) "yes")) - (rplacd cell (if yesp "no" "yes"))) - (setq fields (acons name (if default "yes" "no") fields)) - (setq yesp (if default 'first))) - (magit-log-edit-set-fields fields) - yesp)) - -(defun magit-log-edit-toggle-input (name default) - "Toggle the log-edit input named NAME. -If it's currently unset, set it to DEFAULT (a string). If it is -set remove it. - -Return nil if the input is toggled off, and its valud if it's -toggled on." - (let* ((fields (magit-log-edit-get-fields)) - (cell (assq name fields)) - result) - (if cell - (progn - (setq fields (assq-delete-all name fields) - result (cdr cell))) - (setq fields (acons name default fields))) - (magit-log-edit-set-fields fields) - result)) - -(defun magit-log-edit-setup-author-env (author) - "Set GIT_AUTHOR_* variables from AUTHOR spec. -If AUTHOR is nil, honor default values from -environment (potentially empty)." - (when author - ;; XXX - this is a bit strict, probably. - (or (string-match "\\(.*\\) <\\(.*\\)>\\(?:,\\s-*\\(.+\\)\\)?" author) - (error "Can't parse author string")) - ;; Shucks, setenv destroys the match data. - (let ((name (match-string 1 author)) - (email (match-string 2 author)) - (date (match-string 3 author))) - (make-local-variable 'process-environment) - (setenv "GIT_AUTHOR_NAME" name) - (setenv "GIT_AUTHOR_EMAIL" email) - (if date - (setenv "GIT_AUTHOR_DATE" date))))) - -(defun magit-log-edit-push-to-comment-ring (comment) - (when (or (ring-empty-p log-edit-comment-ring) - (not (equal comment (ring-ref log-edit-comment-ring 0)))) - (ring-insert log-edit-comment-ring comment))) - -(defun magit-log-edit-commit () - "Finish edits and create new commit object. -\('git commit ...')" - (interactive) - (let* ((fields (magit-log-edit-get-fields)) - (amend (equal (cdr (assq 'amend fields)) "yes")) - (allow-empty (equal (cdr (assq 'allow-empty fields)) "yes")) - (commit-all (equal (cdr (assq 'commit-all fields)) "yes")) - (sign-off-field (assq 'sign-off fields)) - (sign-off (if sign-off-field - (equal (cdr sign-off-field) "yes") - magit-commit-signoff)) - (tag-rev (cdr (assq 'tag-rev fields))) - (tag-name (cdr (assq 'tag-name fields))) - (author (cdr (assq 'author fields))) - (tag-options (cdr (assq 'tag-options fields)))) - - (unless (or (magit-anything-staged-p) - allow-empty - amend - tag-name - (file-exists-p (concat (magit-git-dir) "MERGE_HEAD")) - (and commit-all - (not (magit-everything-clean-p)))) - (error "Refusing to create empty commit. Maybe you want to amend (%s) or allow-empty (%s)?" - (key-description (car (where-is-internal - 'magit-log-edit-toggle-amending))) - (key-description (car (where-is-internal - 'magit-log-edit-toggle-allow-empty))))) - - (magit-log-edit-push-to-comment-ring (buffer-string)) - (magit-log-edit-setup-author-env author) - (magit-log-edit-set-fields nil) - (magit-log-edit-cleanup) - (if (= (buffer-size) 0) - (insert "(Empty description)\n")) - (let ((env process-environment) - (commit-buf (current-buffer))) - (with-current-buffer (magit-find-status-buffer default-directory) - (let ((process-environment env)) - (cond (tag-name - (apply #'magit-run-git-with-input commit-buf - "tag" (append tag-options (list tag-name "-a" "-F" "-" tag-rev)))) - (t - (apply #'magit-run-async-with-input commit-buf - magit-git-executable - (append magit-git-standard-options - '("commit") - magit-custom-options - '("-F" "-") - (if (and commit-all (not allow-empty)) '("--all") '()) - (if amend '("--amend") '()) - (if allow-empty '("--allow-empty")) - (if sign-off '("--signoff") '())))))))) - ;; shouldn't we kill that buffer altogether? - (erase-buffer) - (let ((magit-buf magit-buffer-internal)) - (bury-buffer) - (set-buffer magit-buf)) - (when (file-exists-p (concat (magit-git-dir) "MERGE_MSG")) - (delete-file (concat (magit-git-dir) "MERGE_MSG"))) - ;; potentially the local environment has been altered with settings that - ;; were specific to this commit. Let's revert it - (kill-local-variable 'process-environment) - (magit-update-vc-modeline default-directory) - (when magit-pre-log-edit-window-configuration - (set-window-configuration magit-pre-log-edit-window-configuration) - (setq magit-pre-log-edit-window-configuration nil)))) - -(defun magit-log-edit-cancel-log-message () - "Abort edits and erase commit message being composed." - (interactive) - (when (or (not magit-log-edit-confirm-cancellation) - (yes-or-no-p - "Really cancel editing the log (any changes will be lost)?")) - (erase-buffer) - (bury-buffer) - (when magit-pre-log-edit-window-configuration - (set-window-configuration magit-pre-log-edit-window-configuration) - (setq magit-pre-log-edit-window-configuration nil)))) - -(defun magit-log-edit-toggle-amending () - "Toggle whether this will be an amendment to the previous commit. -\(i.e., whether eventual commit does 'git commit --amend')" - (interactive) - (when (eq (magit-log-edit-toggle-field 'amend t) 'first) - (magit-log-edit-append - (magit-trim-line (magit-format-commit "HEAD" "%s%n%n%b"))))) - -(defun magit-log-edit-toggle-signoff () - "Toggle whether this commit will include a signoff. -\(i.e., whether eventual commit does 'git commit --signoff')" - (interactive) - (magit-log-edit-toggle-field 'sign-off (not magit-commit-signoff))) - -(defun magit-log-edit-toggle-author () - "Toggle whether this commit will include an author. -\(i.e., whether eventual commit is run with GIT_AUTHOR_NAME and -GIT_AUTHOR_EMAIL set)" - (interactive) - (magit-log-edit-toggle-input 'author (format "%s <%s>" - (or (magit-get "user" "name") "Author Name") - (or (magit-get "user" "email") "author@email")))) - -(defun magit-log-edit-toggle-allow-empty () - "Toggle whether this commit is allowed to be empty. -This means that the eventual commit does 'git commit --allow-empty'." - (interactive) - (magit-log-edit-toggle-field 'allow-empty t)) - -(defun magit-pop-to-log-edit (operation) - (let ((dir default-directory) - (magit-buf (current-buffer)) - (buf (get-buffer-create magit-log-edit-buffer-name))) - (setq magit-pre-log-edit-window-configuration - (current-window-configuration)) - (pop-to-buffer buf) - (setq default-directory dir) - (when (file-exists-p (concat (magit-git-dir) "MERGE_MSG")) - (insert-file-contents (concat (magit-git-dir) "MERGE_MSG"))) - (magit-log-edit-mode) - (make-local-variable 'magit-buffer-internal) - (setq magit-buffer-internal magit-buf) - (message "Type C-c C-c to %s (C-c C-k to cancel)." operation))) - -(defun magit-log-edit (&optional arg) - "Brings up a buffer to allow editing of commit messages. - -Giving a simple prefix arg will amend a previous commit, while -a double prefix arg will allow creating an empty one. - -If there is a rebase in progress, offer the user the option to -continue it. - -\\{magit-log-edit-mode-map}" - (interactive "P") - ;; If repository is dirty there is no point in trying to - ;; suggest to continue the rebase. Git will rebuke you and exit with - ;; error code, so suggest it only if theres absolutely nothing else - ;; to do and rebase is ongoing. - (if (and (magit-everything-clean-p) - (magit-rebase-info) - (y-or-n-p "Rebase in progress. Continue it? ")) - (magit-run-git-async "rebase" "--continue") - - ;; If there's nothing staged, set commit flag to `nil', thus - ;; avoiding unnescessary popping up of the log edit buffer in case - ;; when user chose to forgo commiting all unstaged changes - (let ((amend-p (= (prefix-numeric-value arg) 4)) - (empty-p (= (prefix-numeric-value arg) 16))) - (when (and magit-commit-all-when-nothing-staged - (not (magit-everything-clean-p)) - (not (magit-anything-staged-p))) - (cond ((eq magit-commit-all-when-nothing-staged 'ask-stage) - (when (y-or-n-p "Nothing staged. Stage everything now? ") - (magit-stage-all))) - ((not (magit-log-edit-get-field 'commit-all)) - (when (or (eq magit-commit-all-when-nothing-staged t) - (y-or-n-p - "Nothing staged. Commit all unstaged changes? ")) - (magit-log-edit-set-field 'commit-all "yes"))))) - (when amend-p - (magit-log-edit-toggle-amending)) - (when empty-p - (magit-log-edit-toggle-allow-empty)) - (let ((author-email (or (getenv "GIT_AUTHOR_EMAIL") "")) - (author-name (or (getenv "GIT_AUTHOR_NAME") "")) - (author-date (or (getenv "GIT_AUTHOR_DATE") ""))) - (if (not (string= author-email "")) - (magit-log-edit-set-field 'author (format "%s <%s>%s" - (if (string= "" author-name) author-email author-name) - author-email - (if (string= "" author-date) "" (format ", %s" author-date)))))) - (magit-pop-to-log-edit "commit")))) - -(defun magit-add-log () - (interactive) - (cond ((magit-rebase-info) - (if (y-or-n-p "Rebase in progress. Continue it? ") - (magit-run-git-async "rebase" "--continue"))) - (t - (let ((section (magit-current-section))) - (let ((fun (if (eq (magit-section-type section) 'hunk) - (save-window-excursion - (save-excursion - (magit-visit-item) - (add-log-current-defun))) - nil)) - (file (magit-diff-item-file - (cond ((eq (magit-section-type section) 'hunk) - (magit-hunk-item-diff section)) - ((eq (magit-section-type section) 'diff) - section) - (t - (error "No change at point")))))) - (magit-log-edit nil) - (goto-char (point-min)) - (cond ((not (search-forward-regexp - (format "^\\* %s" (regexp-quote file)) nil t)) - ;; No entry for file, create it. - (goto-char (point-max)) - (insert (format "\n* %s" file)) - (if fun - (insert (format " (%s)" fun))) - (insert ": ")) - (fun - ;; found entry for file, look for fun - (let ((limit (or (save-excursion - (and (search-forward-regexp "^\\* " - nil t) - (match-beginning 0))) - (point-max)))) - (cond ((search-forward-regexp (format "(.*\\<%s\\>.*):" - (regexp-quote fun)) - limit t) - ;; found it, goto end of current entry - (if (search-forward-regexp "^(" limit t) - (backward-char 2) - (goto-char limit))) - (t - ;; not found, insert new entry - (goto-char limit) - (if (bolp) - (open-line 1) - (newline)) - (insert (format "(%s): " fun)))))) - (t - ;; found entry for file, look for beginning it - (when (looking-at ":") - (forward-char 2))))))))) - -;;; Tags - -(magit-define-command tag (name rev) - "Create a new lightweight tag with the given NAME at REV. -\('git tag NAME')." - (interactive - (list - (read-string "Tag name: ") - (magit-read-rev "Place tag on: " (or (magit-default-rev) "HEAD")))) - (apply #'magit-run-git "tag" (append magit-custom-options (list name rev)))) - -(magit-define-command annotated-tag (name rev) - "Start composing an annotated tag with the given NAME. -Tag will point to the current 'HEAD'." - (interactive - (list - (read-string "Tag name: ") - (magit-read-rev "Place tag on: " (or (magit-default-rev) "HEAD")))) - (magit-log-edit-set-field 'tag-name name) - (magit-log-edit-set-field 'tag-rev rev) - (magit-log-edit-set-field 'tag-options magit-custom-options) - (magit-pop-to-log-edit "tag")) - -;;; Stashing - -(defun magit-wash-stash () - (if (search-forward-regexp "stash@{\\(.*?\\)}" (line-end-position) t) - (let ((stash (match-string-no-properties 0)) - (name (match-string-no-properties 1))) - (delete-region (match-beginning 0) (match-end 0)) - (goto-char (match-beginning 0)) - (fixup-whitespace) - (goto-char (line-beginning-position)) - (insert name) - (goto-char (line-beginning-position)) - (magit-with-section stash 'stash - (magit-set-section-info stash) - (forward-line))) - (forward-line)) - t) - -(defun magit-wash-stashes () - (let ((magit-old-top-section nil)) - (magit-wash-sequence #'magit-wash-stash))) - -(magit-define-inserter stashes () - (magit-git-section 'stashes - "Stashes:" 'magit-wash-stashes - "stash" "list")) - -(magit-define-command stash (description) - "Create new stash of working tree and staging area named DESCRIPTION. -Working tree and staging area revert to the current 'HEAD'. -With prefix argument, changes in staging area are kept. -\('git stash save [--keep-index] DESCRIPTION')" - (interactive "sStash description: ") - (apply 'magit-run-git `("stash" "save" ,@magit-custom-options "--" ,description))) - -(magit-define-command stash-snapshot () - "Create new stash of working tree and staging area; keep changes in place. -\('git stash save \"Snapshot...\"; git stash apply stash@{0}')" - (interactive) - (magit-with-refresh - (apply 'magit-run-git `("stash" "save" ,@magit-custom-options - ,(format-time-string "Snapshot taken at %Y-%m-%d %H:%M:%S" - (current-time)))) - (magit-run-git "stash" "apply" "stash@{0}"))) - -(defvar magit-currently-shown-stash nil) - -(define-derived-mode magit-stash-mode magit-mode "Magit Stash" - "Mode for looking at a git stash. - -\\{magit-stash-mode-map}" - :group 'magit) - -(defvar magit-stash-buffer-name "*magit-stash*" - "Buffer name for displaying a stash.") - -(defun magit-show-stash (stash &optional scroll) - (when (magit-section-p stash) - (setq stash (magit-section-info stash))) - (let ((dir default-directory) - (buf (get-buffer-create magit-stash-buffer-name)) - (stash-id (magit-git-string "rev-list" "-1" stash))) - (cond ((and (equal magit-currently-shown-stash stash-id) - (with-current-buffer buf - (> (length (buffer-string)) 1))) - (let ((win (get-buffer-window buf))) - (cond ((not win) - (display-buffer buf)) - (scroll - (with-selected-window win - (funcall scroll)))))) - (t - (setq magit-currently-shown-stash stash-id) - (display-buffer buf) - (with-current-buffer buf - (set-buffer buf) - (goto-char (point-min)) - (let* ((range (cons (concat stash "^2^") stash)) - (magit-current-diff-range range) - (args (magit-rev-range-to-git range))) - (magit-mode-init dir 'magit-diff-mode #'magit-refresh-diff-buffer - range args))))))) -;;; Commits - -(defun magit-commit-at-point (&optional nil-ok-p) - (let* ((section (magit-current-section)) - (commit (if (and section - (eq (magit-section-type section) 'commit)) - (magit-section-info section) - (get-text-property (point) 'revision)))) - (if nil-ok-p - commit - (or commit - (error "No commit at point"))))) - -(defun magit-apply-commit (commit &optional docommit noerase revert) - (let* ((parent-id (magit-choose-parent-id commit "cherry-pick")) - (success (magit-run* `(,magit-git-executable - ,@magit-git-standard-options - ,(if revert "revert" "cherry-pick") - ,@(if parent-id - (list "-m" (number-to-string parent-id))) - ,@(if (not docommit) (list "--no-commit")) - ,commit) - nil noerase))) - (when (and (not docommit) success) - (cond (revert - (magit-log-edit-append - (magit-format-commit commit "Reverting \"%s\""))) - (t - (magit-log-edit-append - (magit-format-commit commit "%s%n%n%b")) - (magit-log-edit-set-field - 'author - (magit-format-commit commit "%an <%ae>, %ai"))))) - success)) - -(defun magit-apply-item () - (interactive) - (magit-section-action (item info "apply") - ((pending commit) - (magit-apply-commit info) - (magit-rewrite-set-commit-property info 'used t)) - ((commit) - (magit-apply-commit info)) - ((unstaged *) - (error "Change is already in your working tree")) - ((staged *) - (error "Change is already in your working tree")) - ((hunk) - (magit-apply-hunk-item item)) - ((diff) - (magit-apply-diff-item item)) - ((stash) - (magit-run-git "stash" "apply" info)))) - -(defun magit-cherry-pick-item () - (interactive) - (magit-section-action (item info "cherry-pick") - ((pending commit) - (magit-apply-commit info t) - (magit-rewrite-set-commit-property info 'used t)) - ((commit) - (magit-apply-commit info t)) - ((stash) - (magit-run-git "stash" "pop" info)))) - -(defmacro magit-with-revert-confirmation (&rest body) - `(when (or (not magit-revert-item-confirm) - (yes-or-no-p "Really revert this item? ")) - ,@body)) - -(defun magit-revert-item () - (interactive) - (magit-section-action (item info "revert") - ((pending commit) - (magit-with-revert-confirmation - (magit-apply-commit info nil nil t) - (magit-rewrite-set-commit-property info 'used nil))) - ((commit) - (magit-with-revert-confirmation - (magit-apply-commit info nil nil t))) - ;; Reverting unstaged changes cannot be undone - ((unstaged *) - (magit-discard-item)) - ((hunk) - (magit-with-revert-confirmation - (magit-apply-hunk-item-reverse item))) - ((diff) - (magit-with-revert-confirmation - (magit-apply-diff-item item "--reverse"))))) - -(defun magit-log-show-more-entries (&optional arg) - "Grow the number of log entries shown. - -With no prefix optional ARG, show twice as many log entries. -With a numerical prefix ARG, add this number to the number of shown log entries. -With a non numeric prefix ARG, show all entries" - (interactive "P") - (make-local-variable 'magit-log-cutoff-length) - (cond - ((numberp arg) - (setq magit-log-cutoff-length (+ magit-log-cutoff-length arg))) - (arg - (setq magit-log-cutoff-length magit-log-infinite-length)) - (t (setq magit-log-cutoff-length (* magit-log-cutoff-length 2)))) - (let ((old-point (point))) - (magit-refresh) - (goto-char old-point))) - -(defun magit-refresh-log-buffer (range style args) - (magit-configure-have-graph) - (magit-configure-have-decorate) - (magit-configure-have-abbrev) - (setq magit-current-range range) - (magit-create-log-buffer-sections - (apply #'magit-git-section nil - (magit-rev-range-describe range "Commits") - (apply-partially 'magit-wash-log style) - `("log" - ,(format "--max-count=%s" magit-log-cutoff-length) - ,"--abbrev-commit" - ,(format "--abbrev=%s" magit-sha1-abbrev-length) - ,@(cond ((eq style 'long) (list "--stat" "-z")) - ((eq style 'oneline) (list "--pretty=oneline")) - (t nil)) - ,@(if magit-have-decorate (list "--decorate=full")) - ,@(if magit-have-graph (list "--graph")) - ,@args - "--")))) - -(define-derived-mode magit-log-mode magit-mode "Magit Log" - "Mode for looking at git log. - -\\{magit-log-mode-map}" - :group 'magit) - -(defvar magit-log-buffer-name "*magit-log*" - "Buffer name for display of log entries.") - -(magit-define-command log-ranged () - (interactive) - (magit-log t)) -(define-obsolete-function-alias 'magit-display-log-ranged 'magit-log-ranged) - -(magit-define-command log (&optional ask-for-range &rest extra-args) - (interactive) - (let* ((log-range (if ask-for-range - (magit-read-rev-range "Log" "HEAD") - "HEAD")) - (topdir (magit-get-top-dir default-directory)) - (args (nconc (list (magit-rev-range-to-git log-range)) - magit-custom-options - extra-args))) - (magit-buffer-switch magit-log-buffer-name) - (magit-mode-init topdir 'magit-log-mode #'magit-refresh-log-buffer log-range - 'oneline args))) - -(define-obsolete-function-alias 'magit-display-log 'magit-log) - -(magit-define-command log-long-ranged () - (interactive) - (magit-log-long t)) - -(magit-define-command log-long (&optional ranged) - (interactive) - (let* ((range (if ranged - (magit-read-rev-range "Long log" "HEAD") - "HEAD")) - (topdir (magit-get-top-dir default-directory)) - (args (append (list (magit-rev-range-to-git range)) - magit-custom-options))) - (magit-buffer-switch magit-log-buffer-name) - (magit-mode-init topdir 'magit-log-mode #'magit-refresh-log-buffer range - 'long args))) - -;;; Reflog - -(defvar magit-reflog-head nil - "The HEAD of the reflog in the current buffer. -This is only non-nil in reflog buffers.") -(make-variable-buffer-local 'magit-reflog-head) - -(defun magit-refresh-reflog-buffer (head args) - (setq magit-reflog-head head) - (magit-create-log-buffer-sections - (apply #'magit-git-section - 'reflog (format "Local history of head %s" head) 'magit-wash-log "log" - (append magit-git-log-options - (list - "--walk-reflogs" - (format "--max-count=%s" magit-log-cutoff-length) - args))))) - -(define-derived-mode magit-reflog-mode magit-log-mode "Magit Reflog" - "Mode for looking at git reflog. - -\\{magit-reflog-mode-map}" - :group 'magit) - -(magit-define-command reflog (&optional ask-for-range) - (interactive) - (let ((at (or (if ask-for-range - (magit-read-rev "Reflog of" (or (magit-guess-branch) "HEAD"))) - "HEAD"))) - (let* ((topdir (magit-get-top-dir default-directory)) - (args (magit-rev-to-git at))) - (magit-buffer-switch "*magit-reflog*") - (magit-mode-init topdir 'magit-reflog-mode - #'magit-refresh-reflog-buffer at args)))) - -(magit-define-command reflog-ranged () - (interactive) - (magit-reflog t)) - -;;; Diffing - -(defvar magit-ediff-buffers nil - "List of buffers that may be killed by `magit-ediff-restore'.") - -(defvar magit-ediff-windows nil - "The window configuration that will be restored when Ediff is finished.") - -(defun magit-ediff() - "View the current DIFF section in ediff." - (interactive) - (let ((diff (magit-current-section))) - (when (magit-section-hidden diff) - ;; Range is not set until the first time the diff is visible. - ;; This somewhat hackish code makes sure it's been visible at least once. - (magit-toggle-section) - (magit-toggle-section) - (setq diff (magit-current-section))) - (if (eq 'hunk (magit-section-type diff)) - (setq diff (magit-section-parent diff))) - (unless (eq 'diff (magit-section-type diff)) - (error "No diff at this location")) - (let* ((type (magit-diff-item-kind diff)) - (file1 (magit-diff-item-file diff)) - (file2 (magit-diff-item-file2 diff)) - (range (magit-diff-item-range diff))) - (cond - ((memq type '(new deleted typechange)) - (message "Why ediff a %s file?" type)) - ((and (eq type 'unmerged) - (eq (cdr range) 'working)) - (magit-interactive-resolve file1)) - ((consp (car range)) - (magit-ediff* (magit-show (caar range) file2) - (magit-show (cdar range) file2) - (magit-show (cdr range) file1))) - (t - (magit-ediff* (magit-show (car range) file2) - (magit-show (cdr range) file1))))))) - -(defun magit-ediff* (a b &optional c) - (setq magit-ediff-buffers (list a b c)) - (setq magit-ediff-windows (current-window-configuration)) - (add-hook 'ediff-quit-hook 'magit-ediff-restore 'append) - (if c - (ediff-buffers3 a b c) - (ediff-buffers a b))) - -(defun magit-ediff-restore() - "Kill any buffers in `magit-ediff-buffers' that are not visiting files and -restore the window state that was saved before ediff was called." - (dolist (buffer magit-ediff-buffers) - (if (and (null (buffer-file-name buffer)) - (buffer-live-p buffer)) - (kill-buffer buffer))) - (setq magit-ediff-buffers nil) - (set-window-configuration magit-ediff-windows) - (remove-hook 'ediff-quit-hook 'magit-ediff-restore)) - -(defun magit-refresh-diff-buffer (range args) - (let ((magit-current-diff-range (cond - ((stringp range) - (cons range 'working)) - ((null (cdr range)) - (cons (car range) 'working)) - (t - range)))) - (setq magit-current-range range) - (magit-create-buffer-sections - (magit-git-section 'diffbuf - (magit-rev-range-describe range "Changes") - 'magit-wash-diffs - "diff" (magit-diff-U-arg) args "--")))) - -(define-derived-mode magit-diff-mode magit-mode "Magit Diff" - "Mode for looking at a git diff. - -\\{magit-diff-mode-map}" - :group 'magit) - -(magit-define-command diff (range) - (interactive (list (magit-read-rev-range "Diff"))) - (if range - (let* ((dir default-directory) - (args (magit-rev-range-to-git range)) - (buf (get-buffer-create "*magit-diff*"))) - (display-buffer buf) - (with-current-buffer buf - (magit-mode-init dir 'magit-diff-mode #'magit-refresh-diff-buffer range args))))) - -(magit-define-command diff-working-tree (rev) - (interactive (list (magit-read-rev "Diff with" (magit-default-rev)))) - (magit-diff (or rev "HEAD"))) - -(defun magit-diff-with-mark () - (interactive) - (magit-diff (cons (magit-marked-commit) - (magit-commit-at-point)))) - -;;; Wazzup - -(defvar magit-wazzup-head nil - "The integration head for the current wazzup buffer. -This is only non-nil in wazzup buffers.") -(make-variable-buffer-local 'magit-wazzup-head) - -(defvar magit-wazzup-all-p nil - "Non-nil if the current wazzup buffer displays excluded branches. -This is only meaningful in wazzup buffers.") -(make-variable-buffer-local 'magit-wazzup-all-p) - -(defun magit-wazzup-toggle-ignore (branch edit) - (let ((ignore-file (concat (magit-git-dir) "info/wazzup-exclude"))) - (if edit - (setq branch (read-string "Branch to ignore for wazzup: " branch))) - (let ((ignored (magit-file-lines ignore-file))) - (cond ((member branch ignored) - (when (or (not edit) - (y-or-n-p "Branch %s is already ignored. Unignore? ")) - (setq ignored (delete branch ignored)))) - (t - (setq ignored (append ignored (list branch))))) - (magit-write-file-lines ignore-file ignored) - (magit-need-refresh)))) - -(defun magit-refresh-wazzup-buffer (head all) - (setq magit-wazzup-head head) - (setq magit-wazzup-all-p all) - (let ((branch-desc (or head "(detached) HEAD"))) - (unless head (setq head "HEAD")) - (magit-create-buffer-sections - (magit-with-section 'wazzupbuf nil - (insert (format "Wazzup, %s\n\n" branch-desc)) - (let* ((excluded (magit-file-lines (concat (magit-git-dir) "info/wazzup-exclude"))) - (all-branches (magit-list-interesting-refs)) - (branches (if all all-branches - (delq nil (mapcar - (lambda (b) - (and (not - (member (cdr b) excluded)) - b)) - all-branches)))) - (reported (make-hash-table :test #'equal))) - (dolist (branch branches) - (let* ((name (car branch)) - (ref (cdr branch)) - (hash (magit-rev-parse ref)) - (reported-branch (gethash hash reported))) - (unless (or (and reported-branch - (string= (file-name-nondirectory ref) - reported-branch)) - (not (magit-git-string "merge-base" head ref))) - (puthash hash (file-name-nondirectory ref) reported) - (let* ((n (length (magit-git-lines "log" "--pretty=oneline" - (concat head ".." ref)))) - (section - (let ((magit-section-hidden-default t)) - (magit-git-section - (cons ref 'wazzup) - (format "%s unmerged commits in %s%s" - n name - (if (member ref excluded) - " (normally ignored)" - "")) - 'magit-wash-log - "log" - (format "--max-count=%s" magit-log-cutoff-length) - "--abbrev-commit" - (format "--abbrev=%s" magit-sha1-abbrev-length) - "--graph" - "--pretty=oneline" - (format "%s..%s" head ref) - "--")))) - (magit-set-section-info ref section)))))))))) - -(define-derived-mode magit-wazzup-mode magit-mode "Magit Wazzup" - "Mode for looking at commits that could be merged from other branches. - -\\{magit-wazzup-mode-map}" - :group 'magit) - -(defun magit-wazzup (&optional all) - (interactive "P") - (let ((topdir (magit-get-top-dir default-directory)) - (current-branch (magit-get-current-branch))) - (magit-buffer-switch "*magit-wazzup*") - (magit-mode-init topdir 'magit-wazzup-mode - #'magit-refresh-wazzup-buffer - current-branch all))) - -(defun magit-filename (filename) - "Return the path of FILENAME relative to its git repository. - -If FILENAME is absolute, return a path relative to the git -repository containing it. Otherwise, return a path relative to -the current git repository." - (let ((topdir (expand-file-name - (magit-get-top-dir (or (file-name-directory filename) - default-directory)))) - (file (file-truename filename))) - (when (and (not (string= topdir "")) - ;; FILE must start with the git repository path - (zerop (string-match-p (concat "\\`" topdir) file))) - (substring file (length topdir))))) - -;; This variable is used to keep track of the current file in the -;; *magit-log* buffer when this one is dedicated to showing the log of -;; just 1 file. -(defvar magit-file-log-file nil) -(make-variable-buffer-local 'magit-file-log-file) - -(defun magit-refresh-file-log-buffer (file range style) - "Refresh the current file-log buffer by calling git. - -FILE is the path of the file whose log must be displayed. - -`magit-current-range' will be set to the value of RANGE. - -STYLE controls the display. It is either `'long', `'oneline', or something else. - " - (magit-configure-have-graph) - (magit-configure-have-decorate) - (magit-configure-have-abbrev) - (setq magit-current-range range) - (setq magit-file-log-file file) - (magit-create-log-buffer-sections - (apply #'magit-git-section nil - (magit-rev-range-describe range (format "Commits for file %s" file)) - (apply-partially 'magit-wash-log style) - `("log" - ,(format "--max-count=%s" magit-log-cutoff-length) - ,"--abbrev-commit" - ,(format "--abbrev=%s" magit-sha1-abbrev-length) - ,@(cond ((eq style 'long) (list "--stat" "-z")) - ((eq style 'oneline) (list "--pretty=oneline")) - (t nil)) - ,@(if magit-have-decorate (list "--decorate=full")) - ,@(if magit-have-graph (list "--graph")) - "--" - ,file)))) - -(defun magit-file-log (&optional all) - "Display the log for the currently visited file or another one. - -With a prefix argument or if no file is currently visited, ask -for the file whose log must be displayed." - (interactive "P") - (let ((topdir (magit-get-top-dir default-directory)) - (current-file (magit-filename - (if (or current-prefix-arg (not buffer-file-name)) - (magit-read-file-from-rev (magit-get-current-branch)) - buffer-file-name))) - (range "HEAD")) - (magit-buffer-switch "*magit-log*") - (magit-mode-init topdir 'magit-log-mode - #'magit-refresh-file-log-buffer - current-file range 'oneline))) - -(defun magit-show-file-revision () - "Open a new buffer showing the current file in the revision at point." - (interactive) - (flet ((magit-show-file-from-diff (item) - (switch-to-buffer-other-window - (magit-show (cdr (magit-diff-item-range item)) - (magit-diff-item-file item))))) - (magit-section-action (item info "show") - ((commit) - (let ((current-file (or magit-file-log-file - (magit-read-file-from-rev info)))) - (switch-to-buffer-other-window - (magit-show info current-file)))) - ((hunk) (magit-show-file-from-diff (magit-hunk-item-diff item))) - ((diff) (magit-show-file-from-diff item))))) - -;;; Miscellaneous - -(defun magit-ignore-modifiable-file (file edit) - "Prompt the user for the filename to be added to git ignore. -\\ -The minibuffer's future history (accessible with \\[next-history-element]) -contains predefined values (such as wildcards) that might -be of interest. -The history and default value are derived from the filename FILE. -If EDIT argument is negative, the prompt proposes wildcard by default. -" - (let* ((just-extension (concat "*." (file-name-extension file))) - (full-extension (concat (file-name-directory file) just-extension)) - (just-file (file-name-nondirectory file)) - ;; change the order in history depending on the negativity of - ;; EDIT. - (history (if (< (prefix-numeric-value edit) 0) - (list full-extension just-extension file just-file) - (list file full-extension just-extension just-file)))) - (read-string - (format "File to ignore [%s]: " (car history)) - nil nil history))) - -(defun magit-ignore-file (file edit local) - "Add FILE to the list of files to ignore. -\\ -If EDIT is non-`nil', prompt the user for the filename to -be added to git ignore. In this case, the minibuffer's -future history (accessible with \\[next-history-element]) contains predefined -values (such as wildcards) that might be of interest. - -If LOCAL is nil, the `.gitignore' file is updated. -Otherwise, it is `.git/info/exclude'." - (let* ((local-ignore-dir (concat (magit-git-dir) "info/")) - (ignore-file (if local - (concat local-ignore-dir "exclude") - ".gitignore"))) - (if edit - (setq file (magit-ignore-modifiable-file file edit))) - (if (and local (not (file-exists-p local-ignore-dir))) - (make-directory local-ignore-dir t)) - (with-temp-buffer - (when (file-exists-p ignore-file) - (insert-file-contents ignore-file)) - (goto-char (point-max)) - (unless (bolp) - (insert "\n")) - (insert file "\n") - (write-region nil nil ignore-file)) - (magit-need-refresh))) - -(defun magit-ignore-item () - "Add FILE to the `.gitignore' list of files to ignore. -\\ -With a prefix argument, prompt the user for the filename to -be added. In this case, the minibuffer's future history -\(accessible with \\[next-history-element]) contains predefined values (such as -wildcards) that might be of interest. If prefix argument is -negative, the prompt proposes wildcard by default." - (interactive) - (magit-section-action (item info "ignore") - ((untracked file) - (magit-ignore-file (concat "/" info) current-prefix-arg nil)) - ((wazzup) - (magit-wazzup-toggle-ignore info current-prefix-arg)))) - -(defun magit-ignore-item-locally () - "Add FILE to the `.git/info/exclude' list of files to ignore. -\\ -With a prefix argument, prompt the user for the filename to -be added. In this case, the minibuffer's future history -(accessible with \\[next-history-element]) contains predefined values (such as -wildcards) that might be of interest. If prefix argument is -negative, the prompt proposes wildcard by default." - (interactive) - (magit-section-action (item info "ignore") - ((untracked file) - (magit-ignore-file (concat "/" info) current-prefix-arg t)))) - -(defun magit-discard-diff (diff stagedp) - (let ((kind (magit-diff-item-kind diff)) - (file (magit-diff-item-file diff))) - (cond ((eq kind 'deleted) - (when (yes-or-no-p (format "Resurrect %s? " file)) - (magit-run-git "reset" "-q" "--" file) - (magit-run-git "checkout" "--" file))) - ((eq kind 'new) - (if (yes-or-no-p (format "Delete %s? " file)) - (magit-run-git "rm" "-f" "--" file))) - (t - (if (yes-or-no-p (format "Discard changes to %s? " file)) - (if stagedp - (magit-run-git "checkout" "HEAD" "--" file) - (magit-run-git "checkout" "--" file))))))) - -(defun magit-discard-item () - (interactive) - (magit-section-action (item info "discard") - ((untracked file) - (when (yes-or-no-p (format "Delete %s? " info)) - (if (and (file-directory-p info) - (not (file-symlink-p info))) - (magit-delete-directory info 'recursive) - (delete-file info)) - (magit-refresh-buffer))) - ((untracked) - (if (yes-or-no-p "Delete all untracked files and directories? ") - (magit-run-git "clean" "-df"))) - ((unstaged diff hunk) - (when (yes-or-no-p (if (magit-use-region-p) - "Discard changes in region? " - "Discard hunk? ")) - (magit-apply-hunk-item-reverse item))) - ((staged diff hunk) - (if (magit-file-uptodate-p (magit-diff-item-file - (magit-hunk-item-diff item))) - (when (yes-or-no-p (if (magit-use-region-p) - "Discard changes in region? " - "Discard hunk? ")) - (magit-apply-hunk-item-reverse item "--index")) - (error "Can't discard this hunk. Please unstage it first"))) - ((unstaged diff) - (magit-discard-diff item nil)) - ((staged diff) - (if (magit-file-uptodate-p (magit-diff-item-file item)) - (magit-discard-diff item t) - (error "Can't discard staged changes to this file. Please unstage it first"))) - ((diff diff) - (save-excursion - (magit-goto-parent-section) - (magit-discard-item))) - ((diff diff hunk) - (save-excursion - (magit-goto-parent-section) - (magit-goto-parent-section) - (magit-discard-item))) - ((hunk) - (error "Can't discard this hunk")) - ((diff) - (error "Can't discard this diff")) - ((stash) - (when (yes-or-no-p "Discard stash? ") - (magit-run-git "stash" "drop" info))) - ((branch) - (when (yes-or-no-p (if current-prefix-arg - "Force delete branch?" - "Delete branch? ")) - (magit-delete-branch info current-prefix-arg))) - ((remote) - (when (yes-or-no-p "Remove remote? ") - (magit-remove-remote info))))) - -(defun magit-move-item () - (interactive) - (magit-section-action (item info "move") - ((branch) - (call-interactively 'magit-move-branch)) - ((remote) - (call-interactively 'magit-rename-remote)))) - -(defmacro magit-visiting-file-item (&rest body) - `(let ((marker (save-window-excursion - (magit-visit-file-item) - (set-marker (make-marker) (point))))) - (save-excursion - (with-current-buffer (marker-buffer marker) - (goto-char marker) - ,@body)))) - -(defun magit-add-change-log-entry-no-option (&optional other-window) - "Add a change log entry for current change. -With a prefix argument, edit in other window. -The name of the change log file is set by variable change-log-default-name." - (interactive "P") - (if other-window - (magit-visiting-file-item (add-change-log-entry-other-window)) - (magit-visiting-file-item (add-change-log-entry)))) - -(defun magit-add-change-log-entry-other-window () - (interactive) - (magit-visiting-file-item (call-interactively 'add-change-log-entry-other-window))) - -(eval-after-load 'dired-x - '(defun magit-dired-jump (&optional other-window) - "Visit current item. -With a prefix argument, visit in other window." - (interactive "P") - (require 'dired-x) - (magit-section-action (item info "dired-jump") - ((untracked file) - (dired-jump other-window (file-truename info))) - ((diff) - (dired-jump other-window (file-truename (magit-diff-item-file item)))) - ((hunk) - (dired-jump other-window - (file-truename (magit-diff-item-file - (magit-hunk-item-diff item)))))))) - -(defun magit-visit-file-item (&optional other-window) - "Visit current file associated with item. -With a prefix argument, visit in other window." - (interactive "P") - (magit-section-action (item info "visit-file") - ((untracked file) - (funcall - (if other-window 'find-file-other-window 'find-file) - info)) - ((diff) - (let ((file (magit-diff-item-file item))) - (cond ((not (file-exists-p file)) - (error "Can't visit deleted file: %s" file)) - ((file-directory-p file) - (magit-status file)) - (t - (funcall - (if other-window 'find-file-other-window 'find-file) - file))))) - ((hunk) - (let ((file (magit-diff-item-file (magit-hunk-item-diff item))) - (line (magit-hunk-item-target-line item))) - (if (not (file-exists-p file)) - (error "Can't visit deleted file: %s" file)) - (funcall - (if other-window 'find-file-other-window 'find-file) - file) - (goto-char (point-min)) - (forward-line (1- line)))))) - -(defun magit-visit-item (&optional other-window) - "Visit current item. -With a prefix argument, visit in other window." - (interactive "P") - (magit-section-action (item info "visit") - ((untracked file) - (call-interactively 'magit-visit-file-item)) - ((diff) - (call-interactively 'magit-visit-file-item)) - ((hunk) - (call-interactively 'magit-visit-file-item)) - ((commit) - (magit-show-commit info nil nil 'select)) - ((stash) - (magit-show-stash info) - (pop-to-buffer magit-stash-buffer-name)) - ((branch) - (magit-checkout info)) - ((longer) - (magit-log-show-more-entries ())))) - -(defun magit-show-item-or-scroll-up () - (interactive) - (magit-section-action (item info) - ((commit) - (magit-show-commit info #'scroll-up)) - ((stash) - (magit-show-stash info #'scroll-up)) - (t - (scroll-up)))) - -(defun magit-show-item-or-scroll-down () - (interactive) - (magit-section-action (item info) - ((commit) - (magit-show-commit info #'scroll-down)) - ((stash) - (magit-show-stash info #'scroll-down)) - (t - (scroll-down)))) - -(defun magit-mark-item (&optional unmark) - (interactive "P") - (if unmark - (magit-set-marked-commit nil) - (magit-section-action (item info "mark") - ((commit) - (magit-set-marked-commit (if (eq magit-marked-commit info) - nil - info)))))) - -(defun magit-describe-item () - (interactive) - (let ((section (magit-current-section))) - (message "Section: %s %s-%s %S %S %S" - (magit-section-type section) - (magit-section-beginning section) - (magit-section-end section) - (magit-section-title section) - (magit-section-info section) - (magit-section-context-type section)))) - -(defun magit-copy-item-as-kill () - "Copy sha1 of commit at point into kill ring." - (interactive) - (magit-section-action (item info "copy") - ((commit) - (kill-new info) - (message "%s" info)))) - -(eval-when-compile (require 'server)) - -(defun magit-server-running-p () - "Test whether server is running (works with < 23 as well). - -Return values: - nil the server is definitely not running. - t the server seems to be running. - something else we cannot determine whether it's running without using - commands which may have to wait for a long time." - (require 'server) - (if (functionp 'server-running-p) - (server-running-p) - (condition-case nil - (if server-use-tcp - (with-temp-buffer - (insert-file-contents-literally (expand-file-name server-name server-auth-dir)) - (or (and (looking-at "127\\.0\\.0\\.1:[0-9]+ \\([0-9]+\\)") - (assq 'comm - (process-attributes - (string-to-number (match-string 1)))) - t) - :other)) - (delete-process - (make-network-process - :name "server-client-test" :family 'local :server nil :noquery t - :service (expand-file-name server-name server-socket-dir))) - t) - (file-error nil)))) - -(defun magit-interactive-rebase () - "Start a git rebase -i session, old school-style." - (interactive) - (unless (magit-server-running-p) - (server-start)) - (let* ((section (get-text-property (point) 'magit-section)) - (commit (and (member 'commit (magit-section-context-type section)) - (magit-section-info section))) - (old-editor (getenv "GIT_EDITOR"))) - (setenv "GIT_EDITOR" (concat (locate-file "emacsclient" exec-path) - " -s " server-name)) - (unwind-protect - (magit-run-git-async "rebase" "-i" - (or (and commit (concat commit "^")) - (magit-read-rev "Interactively rebase to" (magit-guess-branch)))) - (if old-editor - (setenv "GIT_EDITOR" old-editor))))) - -(define-derived-mode magit-branch-manager-mode magit-mode "Magit Branch" - "Magit Branches") - -(defun magit-quit-window (&optional kill-buffer) - "Bury the buffer and delete its window. With a prefix argument, kill the -buffer instead." - (interactive "P") - (quit-window kill-buffer (selected-window))) - -(defun magit--branch-name-at-point () - "Get the branch name in the line at point." - (let ((branch (magit-section-info (magit-current-section)))) - (or branch (error "No branch at point")))) - -(defun magit--branches-for-remote-repo (remote) - "Return a list of remote branch names for REMOTE. -These are the branch names with the remote name stripped." - (remq nil - (mapcar (lambda (line) - (save-match-data - (if (and (not (string-match-p " -> " line)) - (string-match (concat "^ +" remote "/\\([^ $]+\\)") - line)) - (match-string 1 line)))) - (magit-git-lines "branch" "-r")))) - -(defvar magit-branches-buffer-name "*magit-branches*") - -(defun magit--is-branch-at-point-remote () - "Return non-nil if the branch at point is a remote tracking branch" - (magit-remote-part-of-branch (magit--branch-name-at-point))) - -(defun magit-remote-part-of-branch (branch) - (when (string-match-p "^\\(?:refs/\\)?remotes\\/" branch) - (loop for remote in (magit-git-lines "remote") - when (string-match-p (format "^\\(?:refs/\\)?remotes\\/%s\\/" (regexp-quote remote)) branch) return remote))) - -(defun magit-branch-no-remote (branch) - (let ((remote (magit-remote-part-of-branch branch))) - (if remote - (progn - ;; This has to match if remote is non-nil - (assert (string-match (format "^\\(?:refs/\\)?remotes\\/%s\\/\\(.*\\)" (regexp-quote remote)) branch) - 'show-args "Unexpected string-match failure: %s %s") - (match-string 1 branch)) - branch))) - -(defun magit-wash-branch-line (&optional remote-name) - (looking-at (concat - "^\\([ *] \\)" ; 1: current branch marker - "\\(.+?\\) +" ; 2: branch name - - "\\(?:" - - "\\([0-9a-fA-F]+\\)" ; 3: sha1 - " " - "\\(?:\\[" - "\\([^:\n]+?\\)" ; 4: tracking (non-greedy + to avoid matching \n) - "\\(?:: \\)?" - "\\(?:ahead \\([0-9]+\\)\\)?" ; 5: ahead - "\\(?:, \\)?" - "\\(?:behind \\([0-9]+\\)\\)?" ; 6: behind - "\\] \\)?" - "\\(?:.*\\)" ; message - - "\\|" ; or - - "-> " ; the pointer to - "\\(.+\\)" ; 7: a ref - - "\\)\n")) - - (let* ((current-string (match-string 1)) - (branch (match-string 2)) - (sha1 (match-string 3)) - (tracking (match-string 4)) - (ahead (match-string 5)) - (behind (match-string 6)) - (other-ref (match-string 7)) - (current (string-match-p "^\\*" current-string))) - - ; the current line is deleted before being reconstructed - (delete-region (point) - (line-beginning-position 2)) - - (magit-with-section branch 'branch - (magit-set-section-info branch) - (insert-before-markers - ; sha1 - (propertize (or sha1 - (make-string magit-sha1-abbrev-length ? )) - 'face 'magit-log-sha1) - " " - ; current marker - (if current - "# " - " ") - ; branch name - (apply 'propertize (magit-branch-no-remote branch) - (if current - '(face magit-branch))) - ; other ref that this branch is pointing to - (if other-ref - (concat " -> " (substring other-ref (+ 1 (length remote-name)))) - "") - ; tracking information - (if (and tracking - (equal (magit-remote-branch-for branch t) - (concat "refs/remotes/" tracking))) - (concat " [" - ; getting rid of the tracking branch name if it is the same as the branch name - (let* ((tracking-remote (magit-get "branch" branch "remote")) - (tracking-branch (substring tracking (+ 1 (length tracking-remote))))) - (propertize (if (string= branch tracking-branch) - (concat "@ " tracking-remote) - (concat tracking-branch " @ " tracking-remote)) - 'face 'magit-log-head-label-remote)) - ; ahead/behind information - (if (or ahead - behind) - ": " - "") - (if ahead - (concat "ahead " - (propertize ahead - 'face (if current - 'magit-branch)) - (if behind - ", " - "")) - "") - (if behind - (concat "behind " - (propertize behind - 'face 'magit-log-head-label-remote)) - "") - "]") - "") - "\n")))) - -(defun magit-wash-remote-branches-group (group) - (let* ((remote-name (first group)) - (url (magit-get "remote" remote-name "url")) - (push-url (magit-get "remote" remote-name "pushurl")) - (urls (concat url (if push-url - (concat ", "push-url) - ""))) - (marker (second group))) - - (magit-with-section (concat "remote:" remote-name) 'remote - (magit-set-section-info remote-name) - (insert-before-markers (propertize (format "%s (%s):" remote-name urls) 'face 'magit-section-title) "\n") - (magit-wash-branches-between-point-and-marker marker remote-name)) - (insert-before-markers "\n"))) - -(defun magit-wash-branches-between-point-and-marker (marker &optional remote-name) - (save-restriction - (narrow-to-region (point) marker) - (magit-wash-sequence - (if remote-name - (apply-partially 'magit-wash-branch-line remote-name) - #'magit-wash-branch-line)))) - -(defun magit-wash-branches () - ; get the names of the remotes - (let* ((remotes (magit-git-lines "remote")) - ; get the location of remotes in the buffer - (markers - (append (mapcar (lambda (remote) - (save-excursion - (when (search-forward-regexp - (concat "^ remotes\\/" remote) nil t) - (beginning-of-line) - (point-marker)))) - remotes) - (list (save-excursion - (goto-char (point-max)) - (point-marker))))) - ; list of remote elements to display in the buffer - (remote-groups (loop for remote in remotes - for end-markers on (cdr markers) - for marker = (loop for x in end-markers thereis x) - collect (list remote marker)))) - - ; actual displaying of information - (magit-with-section "local" nil - (insert-before-markers (propertize "Local:" 'face 'magit-section-title) "\n") - (magit-set-section-info ".") - (magit-wash-branches-between-point-and-marker - (loop for x in markers thereis x))) - - (insert-before-markers "\n") - - (mapc 'magit-wash-remote-branches-group remote-groups) - - ; make sure markers point to nil so that they can be garbage collected - (mapc (lambda (marker) - (when marker - (set-marker marker nil))) - markers))) - -(defun magit-refresh-branch-manager () - (magit-create-buffer-sections - (magit-git-section "branches" nil 'magit-wash-branches - "branch" - "-vva" - (format "--abbrev=%s" magit-sha1-abbrev-length)))) - -(magit-define-command branch-manager () - (interactive) - (let ((topdir (magit-get-top-dir default-directory))) - (magit-buffer-switch magit-branches-buffer-name) - (magit-mode-init topdir 'magit-branch-manager-mode #'magit-refresh-branch-manager))) - -(defun magit-change-what-branch-tracks () - "Change which remote branch the current branch tracks." - (interactive) - (if (magit--is-branch-at-point-remote) - (error "Cannot modify a remote branch")) - (let* ((local-branch (magit--branch-name-at-point)) - (new-tracked (magit-read-rev "Change tracked branch to" - nil - (lambda (ref) - (not (string-match-p "refs/remotes/" - ref))))) - new-remote new-branch) - (unless (string= (or new-tracked "") "") - (cond (;; Match refs that are unknown in the local repository if - ;; `magit-remote-ref-format' is set to - ;; `name-then-remote'. Can be useful if you want to - ;; create a new branch in a remote repository. - (string-match "^\\([^ ]+\\) +(\\(.+\\))$" ; 1: branch name; 2: remote name - new-tracked) - (setq new-remote (match-string 2 new-tracked) - new-branch (concat "refs/heads/" (match-string 1 new-tracked)))) - ((string-match "^\\(?:refs/remotes/\\)?\\([^/]+\\)/\\(.+\\)" ; 1: remote name; 2: branch name - new-tracked) - (setq new-remote (match-string 1 new-tracked) - new-branch (concat "refs/heads/" (match-string 2 new-tracked)))) - (t (error "Cannot parse the remote and branch name")))) - (magit-set new-remote "branch" local-branch "remote") - (magit-set new-branch "branch" local-branch "merge") - (magit-branch-manager) - (if (string= (magit-get-current-branch) local-branch) - (magit-refresh-buffer (magit-find-status-buffer default-directory))))) - -(defvar magit-ediff-file) - -(defun magit-interactive-resolve (file) - (require 'ediff) - (let ((merge-status (magit-git-string "ls-files" "-u" "--" file)) - (base-buffer (generate-new-buffer (concat file ".base"))) - (our-buffer (generate-new-buffer (concat file ".current"))) - (their-buffer (generate-new-buffer (concat file ".merged"))) - (windows (current-window-configuration))) - (if (null merge-status) - (error "Cannot resolve %s" file)) - (with-current-buffer base-buffer - (if (string-match "^[0-9]+ [0-9a-f]+ 1" merge-status) - (insert (magit-git-output `("cat-file" "blob" ,(concat ":1:" file)))))) - (with-current-buffer our-buffer - (if (string-match "^[0-9]+ [0-9a-f]+ 2" merge-status) - (insert (magit-git-output `("cat-file" "blob" ,(concat ":2:" file))))) - (let ((buffer-file-name file)) - (normal-mode))) - (with-current-buffer their-buffer - (if (string-match "^[0-9]+ [0-9a-f]+ 3" merge-status) - (insert (magit-git-output `("cat-file" "blob" ,(concat ":3:" file))))) - (let ((buffer-file-name file)) - (normal-mode))) - ;; We have now created the 3 buffer with ours, theirs and the ancestor files - (with-current-buffer (ediff-merge-buffers-with-ancestor our-buffer their-buffer base-buffer) - (make-local-variable 'magit-ediff-file) - (setq magit-ediff-file file) - (make-local-variable 'magit-ediff-windows) - (setq magit-ediff-windows windows) - (make-local-variable 'ediff-quit-hook) - (add-hook 'ediff-quit-hook - (lambda () - (let ((buffer-A ediff-buffer-A) - (buffer-B ediff-buffer-B) - (buffer-C ediff-buffer-C) - (buffer-Ancestor ediff-ancestor-buffer) - (file magit-ediff-file) - (file-buffer) - (windows magit-ediff-windows)) - (ediff-cleanup-mess) - (find-file file) - (setq file-buffer (current-buffer)) - (erase-buffer) - (insert-buffer-substring buffer-C) - (kill-buffer buffer-A) - (kill-buffer buffer-B) - (kill-buffer buffer-C) - (when (bufferp buffer-Ancestor) (kill-buffer buffer-Ancestor)) - (set-window-configuration windows) - (magit-save-some-buffers - "Conflict resolution finished; you may save the buffer" - (lambda () (eq (current-buffer) file-buffer))))))))) - -(defun magit-interactive-resolve-item () - (interactive) - (magit-section-action (item info "resolv") - ((diff) - (magit-interactive-resolve (cadr info))))) - -(defun magit-submodule-update (&optional init) - "Update the submodule of the current git repository - -With a prefix arg, do a submodule update --init" - (interactive "P") - (let ((default-directory (magit-get-top-dir default-directory))) - (apply #'magit-run-git-async "submodule" "update" (if init '("--init") ())))) - -(defun magit-submodule-update-init () - "Update and init the submodule of the current git repository." - (interactive) - (magit-submodule-update t)) - -(defun magit-submodule-init () - "Initialize the submodules" - (interactive) - (let ((default-directory (magit-get-top-dir default-directory))) - (magit-run-git-async "submodule" "init"))) - -(defun magit-submodule-sync () - "Synchronizes submodules' remote URL configuration" - (interactive) - (let ((default-directory (magit-get-top-dir default-directory))) - (magit-run-git-async "submodule" "sync"))) - -(defun magit-run-git-gui () - "Run `git gui' for the current git repository" - (interactive) - (let* ((default-directory (magit-get-top-dir default-directory))) - (magit-start-process "Git Gui" nil magit-git-executable "gui"))) - -(defun magit-run-gitk () - "Run `gitk --all' for the current git repository" - (interactive) - (let ((default-directory (magit-get-top-dir default-directory))) - (cond - ((eq system-type 'windows-nt) - ;; Gitk is a shell script, and Windows doesn't know how to - ;; "execute" it. The Windows version of Git comes with an - ;; implementation of "sh" and everything else it needs, but - ;; Windows users might not have added the directory where it's - ;; installed to their path - (let ((git-bin-dir (file-name-directory magit-gitk-executable)) - (exec-path exec-path) - (process-environment process-environment)) - (when git-bin-dir - ;; Adding it onto the end so that anything the user - ;; specified will get tried first. Emacs looks in - ;; exec-path; PATH is the environment variable inherited by - ;; the process. I need to change both. - (setq exec-path (append exec-path (list git-bin-dir))) - (push (format "PATH=%s;%s" - (getenv "PATH") - (replace-regexp-in-string "/" "\\\\" git-bin-dir)) - process-environment)) - (magit-start-process "Gitk" nil "sh" magit-gitk-executable "--all"))) - (t - (magit-start-process "Gitk" nil magit-gitk-executable "--all"))))) - -(defun magit-load-config-extensions () - "Try to load magit extensions that are defined at git config -layer. This can be added to `magit-mode-hook' for example" - (dolist (ext (magit-get-all "magit.extension")) - (let ((sym (intern (format "magit-%s-mode" ext)))) - (when (and (fboundp sym) - (not (eq sym 'magit-wip-save-mode))) - (funcall sym 1))))) - -(provide 'magit) - -;; rest of magit core -(require 'magit-key-mode) -(require 'magit-bisect) - -;;; magit.el ends here diff --git a/elpa/magit-1.2.0/magit.info b/elpa/magit-1.2.0/magit.info deleted file mode 100644 index deda92f0..00000000 --- a/elpa/magit-1.2.0/magit.info +++ /dev/null @@ -1,1359 +0,0 @@ -This is magit.info, produced by makeinfo version 4.8 from magit.texi. - -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* Magit: (magit). Using Git from Emacs with Magit. -END-INFO-DIR-ENTRY - - Copyright (C) 2008, 2009, 2010, 2011 Magit contributors. (See the -header of magit.el for the lengthy list of Magit contributors.) - - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU Free Documentation License, - Version 1.2 or any later version published by the Free Software - Foundation; with no Invariant Sections, with no Front-Cover Texts, - and with no Back-Cover Texts. - - -File: magit.info, Node: Top, Next: Introduction, Up: (dir) - -Magit User Manual -***************** - -Magit is an interface to the version control system Git, implemented as -an extension to Emacs. Magit supports GNU Emacs version 22 or later. -It may work with other emacsen, but Magit developers do not intend to -investigate and fix bugs that only appear in unsupported versions. -Patches to fix bugs in other emacsen or volunteers to maintain -compatibility are still welcome. - -* Menu: - -* Introduction:: -* Acknowledgments:: -* Sections:: -* Status:: -* Untracked files:: -* Staging and Committing:: -* History:: -* Reflogs:: -* Commit Buffer:: -* Diffing:: -* Tagging:: -* Resetting:: -* Stashing:: -* Branching:: -* The Branch Manager:: -* Wazzup:: -* Merging:: -* Rebasing:: -* Interactive Rebasing:: -* Rewriting:: -* Pushing and Pulling:: -* Bisecting:: -* Submodules:: -* Using Magit Extensions:: -* Using Git Directly:: -* Customization:: -* Frequently Asked Questions:: - - -File: magit.info, Node: Introduction, Next: Acknowledgments, Prev: Top, Up: Top - -1 Introduction -************** - -With Magit, you can inspect and modify your Git repositories with -Emacs. You can review and commit the changes you have made to the -tracked files, for example, and you can browse the history of past -changes. There is support for cherry picking, reverting, merging, -rebasing, and other common Git operations. - - Magit is not a complete interface to Git; it just aims to make the -most common Git operations convenient. Thus, Magit will likely not -save you from learning Git itself. - - This manual provides a tour of all Magit features. It does not give -an introduction to version control in general, or to Git in particular. - - The main entry point to Magit is `M-x magit-status', which will put -you in Magit's status buffer. You will be using it frequently, so it -is probably a good idea to bind `magit-status' to a key of your choice. - - In addition to the status buffer, Magit will also create buffers that -show lists of commits, buffers with diffs, and other kinds of buffers. -All these buffers are in `magit-mode' and have the same key bindings. -Not all commands make sense in all contexts, but a given key will -always do the same thing in all Magit buffers. - - Naturally, Magit runs the `git' command to do most of the work. The -`*magit-process*' buffer contains the transcript of the most recent -command. You can switch to it with `$'. - - -File: magit.info, Node: Acknowledgments, Next: Sections, Prev: Introduction, Up: Top - -2 Acknowledgments -***************** - -Marius Vollmer started the whole project. Thanks ! - - From day one of the first Magit announcement, John Wiegley has -contributed numerous fixes, UI improvements, and new features. Thanks! - - Linh Dang and Christian Neukirchen also contributed from day one. -Thanks! - - Phil Hagelberg joined a few days later. Thanks! - - Alex Ott contributed support for git svn. Thanks! - - Marcin Bachry contributed bug fixes and support for decorated logs. -Thanks! - - Alexey Voinov fixed bugs. Thanks! - - Rémi Vanicat helped with Tramp support. Thanks! - - -File: magit.info, Node: Sections, Next: Status, Prev: Acknowledgments, Up: Top - -3 Sections -********** - -All Magit buffers are structured into nested 'sections'. These -sections can be hidden and shown individually. When a section is -hidden, only its first line is shown and all its children are -completely invisible. - - The most fine-grained way to control the visibility of sections is -the `TAB' key. It will to toggle the current section (the section that -contains point) between being hidden and being shown. - - Typing `S-TAB' toggles the visibility of the children of the current -section. When all of them are shown, they will all be hidden. -Otherwise, when some or all are hidden, they will all be shown. - - The digit keys `1', `2', `3', and `4' control the visibility of -sections based on levels. Hitting `2', for example, will show sections -on levels one and two, and will hide sections on level 3. However, -only sections that are a parent or child of the current section are -affected. - - For example, when the current section is on level 3 and you hit `1', -the grand-parent of the current section (which is on level one) will be -shown, and the parent of the current section (level 2) will be hidden. -The visibility of no other section will be changed. - - This sounds a bit complicated, but you'll figure it out. - - Using `M-1', `M-2', `M-3', and `M-4' is similar to the unmodified -digits, but now all sections on the respective level are affected, -regardless of whether or not they are related to the current section. - - For example, `M-1' will only show the first lines of the top-level -sections and will hide everything else. Typing `M-4' on the other hand -will show everything. - - Because of the way the status buffer is set up, some changes to -section visibility are more common than others. Files are on level 2 -and diff hunks are on level 4. Thus, you can type `2' to collapse the -diff of the current file, and `M-2' to collapse all files. This -returns the status buffer to its default setup and is a quick way to -unclutter it after drilling down into the modified files. - - Because `2' and `M-2' are so common in the status buffer, they are -bound to additional, more mnemonic keys: `M-h' (hide) and `M-H' (hide -all). Likewise `4' and `M-4' are also available as `M-s' (show) and -`M-S' (show all). - - In other buffers than the status buffer, `M-h', `M-H', `M-s', and -`M-S' might work on different levels than on 2 and 4, but they keep -their general meaning: `M-H' hides all detail, and `M-S' shows -everything. - - -File: magit.info, Node: Status, Next: Untracked files, Prev: Sections, Up: Top - -4 Status -******** - -Running `M-x magit-status' displays the main interface of Magit, the -status buffer. You can have multiple status buffers active at the same -time, each associated with its own Git repository. - - When invoking `M-x magit-status' from within a Git repository, it -will switch to the status buffer of that repository. Otherwise, it -will prompt for a directory. With a prefix argument, it will always -prompt. - - You can set `magit-repo-dirs' to customize how `magit-status' asks -for the repository to work on. When `magit-repo-dirs' is nil, -`magit-status' will simply ask for a directory. - - If you specify a directory that is not a Git repository, `M-x -magit-status' will offer to initialize it as one. - - When `magit-repo-dirs' is not nil, it is treated as a list of -directory names, and `magit-status' will find all Git repositories in -those directories and offer them for completion. (Magit will only look -`magit-repo-dirs-depth' levels deep, however.) - - With two prefix arguments, `magit-status' will always prompt for a -raw directory. - - Thus, you would normally set `magit-repo-dirs' to the places where -you keep most of your Git repositories and switch between them with -`C-u M-x magit-status'. If you want to go to a repository outside of -your normal working areas, or if you want to create a new repository, -you would use `C-u C-u M-x magit-status'. - - You need to explicitly refresh the status buffer when you have made -changes to the repository from outside of Emacs. You can type `g' in -the status buffer itself, or just use `M-x magit-status' instead of -`C-x b' when switching to it. You also need to refresh the status -buffer in this way after saving a file in Emacs. - - The header at the top of the status buffer shows a short summary of -the repository state: where it is located, which branch is checked out, -etc. Below the header are a number of sections that show details about -the working tree and the staging area. You can hide and show them as -described in the previous section. - - The first section shows _Untracked files_, if there are any. See -*Note Untracked files:: for more details. - - The next two sections show your local changes. They are explained -fully in the next chapter, *Note Staging and Committing::. - - If the current branch is associated with a remote tracking branch, -the status buffer shows the differences between the current branch and -the tracking branch. See *Note Pushing and Pulling:: for more -information. - - During a history rewriting session, the status buffer shows the -_Pending changes_ and _Pending commits_ sections. See *Note -Rewriting:: for more details. - - -File: magit.info, Node: Untracked files, Next: Staging and Committing, Prev: Status, Up: Top - -5 Untracked files -***************** - -Untracked files are shown in the _Untracked files_ section. - - You can add an untracked file to the staging area with `s'. If -point is on the _Untracked files_ section title when you hit `s', all -untracked files are staged. - - Typing `C-u S' anywhere will also stage all untracked files, -together with all changes to the tracked files. - - You can instruct Git to ignore them by typing `i'. This will add -the filename to the `.gitignore' file. Typing `C-u i' will ask you for -the name of the file to ignore. This is useful to ignore whole -directories, for example. In this case, the minibuffer's future history -(accessible with `M-n') contains predefined values (such as wildcards) -that might be of interest. If prefix argument is negative (for example -after typing `C-- i'), the prompt proposes wildcard by default. The -`I' command is similar to `i' but will add the file to -`.git/info/exclude' instead. - - To delete an untracked file forever, use `k'. If point is on the -_Untracked files_ section title when you hit `k', all untracked files -are deleted. - - -File: magit.info, Node: Staging and Committing, Next: History, Prev: Untracked files, Up: Top - -6 Staging and Committing -************************ - -Comitting with Git is a two step process: first you add the changes you -want to commit to a 'staging area', and then you commit them to the -repository. This allows you to only commit a subset of your local -changes. - - Magit allows you to ignore the staging area if you wish. As long as -your staging area is unused, Magit will show your uncomitted changes in -a section named _Changes_. - - When the staging area is in use, Magit uses two sections: _Unstaged -changes_ and _Staged changes_. The _Staged changes_ section shows the -changes that will be included in the next commit, while the _Unstaged -changes_ section shows the changes that will be left out. - - To move an unstaged hunk into the staging area, move point into the -hunk and type `s'. Likewise, to unstage a hunk, move point into it and -type `u'. If point is in a diff header when you type `s' or `u', all -hunks belonging to that diff are moved at the same time. - - If the region is active when you type `s' or `u', only the changes -in the region are staged or unstaged. (This works line by line: if the -beginning of a line is in the region it is included in the changes, -otherwise it is not.) - - To change the size of the hunks, you can type `+' or `-' to increase -and decrease, respectively. Typing `0' will reset the hunk size to the -default. - - Typing `C-u s' will ask you for a name of a file to be staged, for -example to stage files that are hidden. - - To move all hunks of all diffs into the staging area in one go, type -`S'. To unstage everything, type `U'. - - Typing `C-u S' will stage all untracked files in addition to the -changes to tracked files. - - You can discard uncommitted changes by moving point into a hunk and -typing `k'. The changes to discard are selected as with `s' and `u'. - - Before committing, you should write a short description of the -changes. - - Type `c' to pop up a buffer where you can write your change -description. Once you are happy with the description, type `C-c C-c' -in that buffer to perform the commit. - - If you want to write changes in a `ChangeLog' file, you can use `C-x -4 a' on a diff hunk. - - Typing `c' when the staging area is unused is a special situation. -Normally, the next commit would be empty, but you can configure Magit -to do something more useful by customizing the -`magit-commit-all-when-nothing-staged' variable. One choice is to -instruct the subsequent `C-c C-c' to commit all changes. Another -choice is stage everything at the time of hitting `c'. - - You can type `C-c C-a' in the buffer with the change description to -toggle a flag that determines whether the next commit will _amend_ the -current commit in HEAD. - - Typing `C-c C-s' will toggle the `--signoff' option. The default is -determined by the `magit-commit-signoff' customization variable. - - Typing `C-c C-e' will toggle the `--allow-empty' option. This -allows you to make commits that serve as notes, without including any -changes. - - Typing `C-c C-t' will toggle the option to specify the name and -email address for the commit's author. The default is determined by -the `user.name' and `user.email' git configuration settings. - - If you change your mind and don't want to go ahead with your commit -while you are in the `*magit-log-edit*' buffer, you can just switch to -another buffer, continue editing there, staging and unstaging things -until you are happy, and then return to the `*magit-log-edit*' buffer, -maybe via `C-x b', or by hitting `c' again in a Magit buffer. - - If you want to erase the `*magit-log-edit*' buffer and bury it, you -can hit `C-c C-k' in it. - - Typing `C' will also pop up the change description buffer, but in -addition, it will try to insert a ChangeLog-style entry for the change -that point is in. - - -File: magit.info, Node: History, Next: Reflogs, Prev: Staging and Committing, Up: Top - -7 History -********* - -To show the repository history of your current head, type `l l'. A new -buffer will be shown that displays the history in a terse form. The -first paragraph of each commit message is displayed, next to a -representation of the relationships between commits. - - To show the repository history between two branches or between any -two points of the history, type `l r l'. You will be prompted to enter -references for starting point and ending point of the history range; you -can use auto-completion to specify them. A typical use case for ranged -history log display would be `l r l master RET new-feature RET' that -will display commits on the new-feature branch that are not in master; -these commits can then be inspected and cherry-picked, for example. - - More thorough filtering can be done by supplying `l' with one or -more suffix arguments, as displayed in its popup. `=g' ('Grep') for -example, limits the output to commits of which the log message matches -a specific string/regex. - - Typing `l L' (or `l C-u L') will show the log in a more verbose form. - - Magit will show only `magit-log-cutoff-length' entries. `e' will -show twice as many entries. `C-u e' will show all entries, and given a -numeric prefix argument, `e' will add this number of entries. - - You can move point to a commit and then cause various things to -happen with it. (The following commands work in any list of commits, -such as the one shown in the _Unpushed commits_ section.) - - Typing `RET' will pop up more information about the current commit -and move point into the new buffer. *Note Commit Buffer::. Typing -`SPC' and `DEL' will also show the information, but will scroll the new -buffer up or down (respectively) when typed again. - - Typing `a' will apply the current commit to your current branch. -This is useful when you are browsing the history of some other branch -and you want to `cherry-pick' some changes from it. A typical -situation is applying selected bug fixes from the development version -of a program to a release branch. The cherry-picked changes will not -be committed automatically; you need to do that explicitly. - - Typing `A' will cherry-pick the current commit and will also commit -the changes automatically when there have not been any conflicts. - - Typing `v' will revert the current commit. Thus, it will apply the -changes made by that commit in reverse. This is obviously useful to -cleanly undo changes that turned out to be wrong. As with `a', you -need to commit the changes explicitly. - - Typing `C-w' will copy the sha1 of the current commit into the kill -ring. - - Typing `=' will show the differences from the current commit to the -"marked" commit. - - You can mark the current commit by typing `.'. When the current -commit is already marked, typing `.' will unmark it. To unmark the -marked commit no matter where point is, use `C-u .'. - - Some commands, such as `=', will use the current commit and the -marked commit as implicit arguments. Other commands will offer the -marked commit as a default when prompting for their arguments. - - -File: magit.info, Node: Reflogs, Next: Commit Buffer, Prev: History, Up: Top - -8 Reflogs -********* - -You can use `l h' and `l H' to browse your _reflog_, the local history -of changes made to your repository heads. Typing `H' will ask for a -head, while `l h' will show the reflog of `HEAD'. - - The resulting buffer is just like the buffer produced by `l l' and -`l L' that shows the commit history. - - -File: magit.info, Node: Commit Buffer, Next: Diffing, Prev: Reflogs, Up: Top - -9 Commit Buffer -*************** - -When you view a commit (perhaps by selecting it in the log buffer, -*Note History::), the "commit buffer" is displayed, showing you -information about the commit and letting you interact with it. - - By placing your cursor within the diff or hunk and typing `a', you -can apply the same patch to your working copy. This is useful when you -want to copy a change from another branch, but don't necessarily want -to cherry-pick the whole commit. - - By typing `v' you can apply the patch in reverse, removing all the -lines that were added and adding all the lines that were removed. This -is a convenient way to remove a change after determining that it -introduced a bug. - - If the commit message refers to any other commits in the repository -by their unique hash, the hash will be highlighted and you will be able -to visit the referenced commit either by clicking on it or by moving -your cursor onto it and pressing `RET'. - - The commit buffer maintains a history of the commits it has shown. -After visiting a referenced commit you can type `C-c C-b' to get back -to where you came from. To go forward in the history, type `C-c C-f'. -There are also `[back]' and `[forward]' buttons at the bottom of the -buffer. - - -File: magit.info, Node: Diffing, Next: Tagging, Prev: Commit Buffer, Up: Top - -10 Diffing -********** - -Magit typically shows diffs in the "unified" format. - - In any buffer that shows a diff, you can type `e' anywhere within -the diff to show the two versions of the file in Ediff. If the diff is -of a file in the status buffer that needs to be merged, you will be -able to use Ediff as an interactive merge tool. Otherwise, Ediff will -simply show the two versions of the file. - - To show the changes from your working tree to another revision, type -`d'. To show the changes between two arbitrary revisions, type `D'. - - You can use `a' within the diff output to apply the changes to your -working tree. As usual when point is in a diff header for a file, all -changes for that file are applied, and when it is in a hunk, only that -hunk is. When the region is active, the applied changes are restricted -to that region. - - Typing `v' will apply the selected changes in reverse. - - -File: magit.info, Node: Tagging, Next: Resetting, Prev: Diffing, Up: Top - -11 Tagging -********** - -Typing `t t' will make a lighweight tag. Typing `t a' will make an -annotated tag. It will put you in the normal `*magit-log-edit' buffer -for writing commit messages, but typing `C-c C-c' in it will make the -tag instead. This is controlled by the `Tag' field that will be added -to the `*magit-log-edit*' buffer. You can edit it, if you like. - - -File: magit.info, Node: Resetting, Next: Stashing, Prev: Tagging, Up: Top - -12 Resetting -************ - -Once you have added a commit to your local repository, you can not -change that commit anymore in any way. But you can reset your current -head to an earlier commit and start over. - - If you have published your history already, rewriting it in this way -can be confusing and should be avoided. However, rewriting your local -history is fine and it is often cleaner to fix mistakes this way than -by reverting commits (with `v', for example). - - Typing `x' will ask for a revision and reset your current head to -it. No changes will be made to your working tree and staging area. -Thus, the _Staged changes_ section in the status buffer will show the -changes that you have removed from your commit history. You can commit -the changes again as if you had just made them, thus rewriting history. - - Typing `x' while point is in a line that describes a commit will -offer this commit as the default revision to reset to. Thus, you can -move point to one of the commits in the _Unpushed commits_ section and -hit `x RET' to reset your current head to it. - - Type `X' to reset your working tree and staging area to the most -recently committed state. This will discard your local modifications, -so be careful. - - You can give a prefix to `x' if you want to reset both the current -head and your working tree to a given commit. This is the same as -first using an unprefixed `x' to reset only the head, and then using -`X'. - - -File: magit.info, Node: Stashing, Next: Branching, Prev: Resetting, Up: Top - -13 Stashing -*********** - -You can create a new stash with `z z'. Your stashes will be listed in -the status buffer, and you can apply them with `a' and pop them with -`A'. To drop a stash, use `k'. - - With a prefix argument, both `a' and `A' will attempt to reinstate -the index as well as the working tree from the stash. - - Typing `z -k z' will create a stash just like `z z', but will leave -the changes in your working tree and index. This makes it easier to, -for example, test multiple variations of the same change. - - If you just want to make quick snapshots in between edits, you can -use `z s', which automatically enters a timestamp as description, and -keeps your working tree and index intact by default. - - You can visit and show stashes in the usual way: Typing `SPC' and -`DEL' will pop up a buffer with the description of the stash and scroll -it, typing `RET' will move point into that buffer. Using `C-u RET' will -move point into that buffer in other window. - - -File: magit.info, Node: Branching, Next: The Branch Manager, Prev: Stashing, Up: Top - -14 Branching -************ - -The current branch is indicated in the header of the status buffer. -You can switch to a different branch by typing `b b'. This will -immediately checkout the branch into your working copy, so you -shouldn't have any local modifications when switching branches. - - If you try to switch to a remote branch, Magit will offer to create a -local tracking branch for it instead. This way, you can easily start -working on new branches that have appeared in a remote repository. - - Typing `b b' while point is at a commit description will offer that -commit as the default to switch to. This will result in a detached -head. - - Typing `b m' will let you rename a branch. Unless a branch with the -same name already exists, obviously... - - To create a new branch and switch to it immediately, type `b n'. - - To delete a branch, type `b d'. If you're currently on that branch, -Magit will offer to switch to the 'master' branch. - - Deleting a branch is only possible if it's already fully merged into -HEAD or its upstream branch. Unless you type `b D', that is. Here be -dragons... - - Typing `b v' will list the local and remote branches in a new buffer -called `*magit-branches*' from which you can work with them. See *Note -The Branch Manager:: for more details. - - -File: magit.info, Node: The Branch Manager, Next: Wazzup, Prev: Branching, Up: Top - -15 The Branch Manager -********************* - -The Branch Manager is a separate buffer called `*magit-branches*' with -its own local key map. The buffer contains both local and remote -branches. The current local branch is marked by a "*" in front of the -name. - - To check out a branch, move your cursor to the desired branch and -press `RET'. - - Typing `k' will delete the branch in the current line, and `C-u k' -deletes it even if it hasn't been merged into the current local branch. -Deleting works for both local and remote branches. - - By typing `T' on a local branch, you can change which remote branch -it's set to track. - - -File: magit.info, Node: Wazzup, Next: Merging, Prev: The Branch Manager, Up: Top - -16 Wazzup -********* - -Typing `w' will show a summary of how your other branches relate to the -current branch. - - For each branch, you will get a section that lists the commits in -that branch that are not in the current branch. The sections are -initially collapsed; you need to explicitly open them with `TAB' (or -similar) to show the lists of commits. - - When point is on a _N unmerged commits in ..._ title, the -corresponding branch will be offered as the default for a merge. - - Hitting `i' on a branch title will ignore this branch in the wazzup -view. You can use `C-u w' to show all branches, including the ignored -ones. Hitting `i' on an already ignored branch in that view will -unignore it. - - -File: magit.info, Node: Merging, Next: Rebasing, Prev: Wazzup, Up: Top - -17 Merging -********** - -Magit offers two ways to merge branches: manual and automatic. A -manual merge will apply all changes to your working tree and staging -area, but will not commit them, while an automatic merge will go ahead -and commit them immediately. - - Type `m m' to initiate merge. - - After initiating a merge, the header of the status buffer might -remind you that the next commit will be a merge commit (with more than -one parent). If you want to abort a manual merge, just do a hard reset -to HEAD with `X'. - - Merges can fail if the two branches you want to merge introduce -conflicting changes. In that case, the automatic merge stops before the -commit, essentially falling back to a manual merge. You need to resolve -the conflicts for example with `e' and stage the resolved files, for -example with `S'. - - You can not stage individual hunks one by one as you resolve them, -you can only stage whole files once all conflicts in them have been -resolved. - - -File: magit.info, Node: Rebasing, Next: Interactive Rebasing, Prev: Merging, Up: Top - -18 Rebasing -*********** - -Typing `R' in the status buffer will initiate a rebase or, if one is -already in progress, ask you how to continue. - - When a rebase is stopped in the middle because of a conflict, the -header of the status buffer will indicate how far along you are in the -series of commits that are being replayed. When that happens, you -should resolve the conflicts and stage everything and hit `R c' to -continue the rebase. Alternatively, hitting `c' or `C' while in the -middle of a rebase will also ask you whether to continue the rebase. - - Of course, you can initiate a rebase in any number of ways, by -configuring `git pull' to rebase instead of merge, for example. Such a -rebase can be finished with `R' as well. - - -File: magit.info, Node: Interactive Rebasing, Next: Rewriting, Prev: Rebasing, Up: Top - -19 Interactive Rebasing -*********************** - -Typing `E' in the status buffer will initiate an interactive rebase. -This is equivalent to running `git rebase --interactive' at the command -line. The `git-rebase-todo' file will be opened in an Emacs buffer for -you to edit. This file is opened using `emacsclient', so just edit this -file as you normally would, then call the `server-edit' function -(typically bound to `C-x #') to tell Emacs you are finished editing, -and the rebase will proceed as usual. - - If you have loaded `rebase-mode.el' (which is included in the Magit -distribution), the `git-rebase-todo' buffer will be in `rebase-mode'. -This mode disables normal text editing but instead provides single-key -commands (shown in the buffer) to perform all the edits that you would -normally do manually, including changing the operation to be performed -each commit ("pick", "squash", etc.), deleting (commenting out) commits -from the list, and reordering commits. You can finish editing the -buffer and proceed with the rebase by pressing `C-c C-c', which is -bound to `server-edit' in this mode, and you can abort the rebase with -`C-c C-k', just like when editing a commit message in Magit. - - -File: magit.info, Node: Rewriting, Next: Pushing and Pulling, Prev: Interactive Rebasing, Up: Top - -20 Rewriting -************ - -As hinted at earlier, you can rewrite your commit history. For -example, you can reset the current head to an earlier commit with `x'. -This leaves the working tree unchanged, and the status buffer will show -all the changes that have been made since that new value of the current -head. You can commit these changes again, possibly splitting them into -multiple commits as you go along. - - Amending your last commit is a common special case of rewriting -history like this. - - Another common way to rewrite history is to reset the head to an -earlier commit, and then to cherry pick the previous commits in a -different order. You could pick them from the reflog, for example. - - Magit has several commands that can simplify the book keeping -associated with rewriting. These commands all start with the `r' -prefix key. - - Typing `r b' will start a rewrite operation. You will be prompted -for a _base_ commit. This commit and all subsequent commits up until -the current head are then put in a list of _Pending commits_, after -which the current head will be reset to the _parent_ of the base -commit. This can be configured to behave like `git rebase', i.e. -exclude the selected base commit from the rewrite operation, with the -`magit-rewrite-inclusive' variable. - - You would then typically use `a' and `A' to cherry pick commits from -the list of pending commits in the desired order, until all have been -applied. Magit shows which commits have been applied by changing their -marker from `*' to `.'. - - Using `A' will immediately commit the commit (as usual). If you -want to combine multiple previous commits into a single new one, use -`a' to apply them all to your working tree, and then commit them -together. - - Magit has no explicit support for rewriting merge commits. It will -happily include merge commits in the list of pending commits, but there -is no way of replaying them automatically. You have to redo the merge -explicitly. - - You can also use `v' to revert a commit when you have changed your -mind. This will change the `.' mark back to `*'. - - Once you are done with the rewrite, type `r s' to remove the book -keeping information from the status buffer. - - If you rather wish to start over, type `r a'. This will abort the -rewriting, resetting the current head back to the value it had before -the rewrite was started with `r b'. - - Typing `r f' will _finish_ the rewrite: it will apply all unused -commits one after the other, as if you would us `A' with all of them. - - You can change the `*' and `.' marks of a pending commit explicitly -with `r *' and `r .'. - - In addition to a list of pending commits, the status buffer will show -the _Pending changes_. This section shows the diff between the -original head and the current head. You can use it to review the -changes that you still need to rewrite, and you can apply hunks from -it, like from any other diff. - - -File: magit.info, Node: Pushing and Pulling, Next: Bisecting, Prev: Rewriting, Up: Top - -21 Pushing and Pulling -********************** - -Magit will run `git push' when you type `P P'. If you give a prefix -argument to `P P', you will be prompted for the repository to push to. -When no default remote repository has been configured yet for the -current branch, you will be prompted as well. Typing `P P' will only -push the current branch to the remote. In other words, it will run -`git push '. The branch will be created in the remote -if it doesn't exist already. The local branch will be configured so -that it pulls from the new remote branch. If you give a double prefix -argument to `P P', you will be prompted in addition for the target -branch to push to. In other words, it will run `git push -:'. - - Typing `f f' will run `git fetch'. It will prompt for the name of -the remote to update if there is no default one. Typing `f o' will -always prompt for the remote. Typing `F F' will run `git pull'. When -you don't have a default branch configured to be pulled into the -current one, you will be asked for it. - - If there is a default remote repository for the current branch, Magit -will show that repository in the status buffer header. - - In this case, the status buffer will also have a _Unpushed commits_ -section that shows the commits on your current head that are not in the -branch named `/'. This section works just like the -history buffer: you can see details about a commit with `RET', compare -two of them with `.' and `=', and you can reset your current head to -one of them with `x', for example. If you want to push the changes then -type `P P'. - - When the remote branch has changes that are not in the current -branch, Magit shows them in a section called _Unpulled changes_. Typing -`F F' will fetch and merge them into the current branch. - - -File: magit.info, Node: Submodules, Next: Using Magit Extensions, Prev: Bisecting, Up: Top - -22 Submodules -************* - -`M u' - Update the submodules, with a prefix argument it will initializing. - -`M i' - Initialize the submodules. - -`M b' - Update and initialize the submodules in one go. - -`M s' - Synchronizes submodules' remote URL configuration setting to the - value specified in .gitmodules. - - -File: magit.info, Node: Bisecting, Next: Submodules, Prev: Pushing and Pulling, Up: Top - -23 Bisecting -************ - -Magit supports bisecting by showing how many revisions and steps are -left to be tested in the status buffer. You can control the bisect -session from both the status and from log buffers with the `B' key menu. - - Typing `B s' will start a bisect session. You will be prompted for -a revision that is known to be bad (defaults to _HEAD_) and for a -revision that is known to be good (defaults to the revision at point if -there is one). git will select a revision for you to test, and Magit -will update its status buffer accordingly. - - You can tell git that the current revision is good with `B g', that -it is bad with `B b' or that git should skip it with `B k'. You can -also tell git to go into full automatic mode by giving it the name of a -script to run for each revision to test with `B u'. - - The current status can be shown as a log with `B l'. It contains the -revisions that have already been tested and your decisions about their -state. - - The revisions left to test can be visualized in gitk with `B v'. - - When you're finished bisecting you have to reset the session with `B -r'. - - -File: magit.info, Node: Using Magit Extensions, Next: Using Git Directly, Prev: Submodules, Up: Top - -24 Magit Extensions -******************* - -* Menu: - -* Activating extensions:: -* Interfacing with Subversion:: -* Interfacing with Topgit:: -* Interfacing with StGit:: -* Developing Extensions:: - - -File: magit.info, Node: Activating extensions, Next: Interfacing with Subversion, Up: Using Magit Extensions - -24.1 Activating extensions -========================== - -Magit comes with a couple of shipped extensions that allow interaction -with `git-svn', `topgit' and `stgit'. See following sections for -specific details on how to use them. - - Extensions can be activated globally or on a per-repository basis. -Since those extensions are implemented as minor modes, one can use for -example `M-x magit-topgit-mode' to toggle the `topgit' extension, -making the corresponding section and commands (un)available. - - In order to do that automatically (and for every repository), one can -use for example: - - (add-hook 'magit-mode-hook 'turn-on-magit-topgit) - - Magit also allows configuring different extensions, based on the git -repository configuration. - - (add-hook 'magit-mode-hook 'magit-load-config-extensions) - - This will read git configuration variables and activate the relevant -extensions. - - For example, after running the following commands, the `topgit' -extension will be loaded for every repository, while the `svn' one will -be loaded only for the current one. - - $ git config --global --add magit.extension topgit - $ git config --add magit.extension svn - - Note the `--add' flag, which means that each extension gets its own -line in the `config' file. - - -File: magit.info, Node: Interfacing with Subversion, Next: Interfacing with Topgit, Prev: Activating extensions, Up: Using Magit Extensions - -24.2 Interfacing with Subversion -================================ - -Typing `N r' runs `git svn rebase', typing `N c' runs `git svn dcommit' -and typing `N f' runs `git svn fetch'. - - `N s' will prompt you for a (numeric, Subversion) revision and then -search for a corresponding Git sha1 for the commit. This is limited to -the path of the remote Subversion repository. With a prefix (`C-u N s' -the user will also be prompted for a branch to search in. - - -File: magit.info, Node: Interfacing with Topgit, Next: Interfacing with StGit, Prev: Interfacing with Subversion, Up: Using Magit Extensions - -24.3 Interfacing with Topgit -============================ - -Topgit (http://repo.or.cz/r/topgit.git) is a patch queue manager that -aims at being close as possible to raw Git, which makes it easy to use -with Magit. In particular, it does not require to use a different set of -commands for "commit", "update",… operations. - - `magit-topgit.el' provides basic integration with Magit, mostly by -providing a "Topics" section. - - Topgit branches can be created the regular way, by using a "t/" -prefix by convention. So, creating a "t/foo" branch will actually -populate the "Topics" section with one more branch after committing -`.topdeps' and `.topmsg'. - - Also, the way we pull (see *Note Pushing and Pulling::) such a -branch is slightly different, since it requires updating the various -dependencies of that branch. This should be mostly transparent, except -in case of conflicts. - - -File: magit.info, Node: Interfacing with StGit, Next: Developing Extensions, Prev: Interfacing with Topgit, Up: Using Magit Extensions - -24.4 Interfacing with StGit -=========================== - -StGit (http://www.procode.org/stgit) is a Python application providing -similar functionality to Quilt (i.e. pushing/popping patches to/from a -stack) on top of Git. These operations are performed using Git commands -and the patches are stored as Git commit objects, allowing easy merging -of the StGit patches into other repositories using standard Git -functionality. - - `magit-stgit.el' provides basic integration with Magit, mostly by -providing a "Series" section, whose patches can be seen as regular -commits through the "visit" action. - - You can change the current patch in a series with the "apply" action, -as well as you can delete them using the "discard" action. - - Additionally, the `magit-stgit-refresh' and `magit-stgit-rebase' -commands let you perform the respective StGit operations. - - -File: magit.info, Node: Developing Extensions, Prev: Interfacing with StGit, Up: Using Magit Extensions - -24.5 Developing Extensions -========================== - -Magit provides a generic mechanism to allow cooperation with Git-related -systems, such as foreign VCS, patch systems,… - - In particular it allows to: - - * Define sections to display specific informations about the current - state of the repository, and place them relatively to existing - sections. - - `magit-define-inserter' automagically defines two hooks called - `magit-before-insert-SECTION-hook' and - `magit-after-insert-SECTION-hook' that allow to generate and place - more sections. - - In the following example, we use the builtin "stashes" section to - place our own "foo" one. - - (magit-define-inserter foo () - (magit-git-section 'foo - "Foo:" 'foo-wash-function - "foo" "arg1" "arg2")) - (add-hook 'magit-after-insert-stashes-hook 'magit-insert-foo) - - * Define new types of objects in those sections. - - The function `foo-wash-function' defined above post-processes each - line of the output of the "git foo arg1 arg2" command, and is able - to associate a type to certain lines. - - A simple implementation could be: - - (defun foo-wash-function () - (let ((foo (buffer-substring (line-beginning-position) (line-end-position)))) - (goto-char (line-beginning-position)) - (magit-with-section foo 'foo - (magit-set-section-info foo) - (forward-line)))) - - In this case, every line of the command output is transformed into - an object of type `'foo'. - - * Alter behavior of generic commands to dispatch them correctly to - the relevant system, optionally making use of the newly defined - types. - - (magit-add-action (item info "discard") - ((foo) - (do-something-meaningful-for-discarding-a-foo))) - - This will alter the behavior of `k', when applied to those objects. - - * Plug a different logic into basic commands, to reflect the - presence of the extension. - - `magit-define-command' automagically defines a - `magit-CMD-command-hook' that can contain a list of functions to - call before the actual core code. Execution stops after the first - hook that returns a non-nil value. This leaves room for extension - logic. - - (add-hook 'magit-create-branch-command-hook 'foo-create-branch) - - The function `foo-create-branch' will be called each time an - attempt is made to create a branch, and can, for example, react to - a certain name convention. - - * Define new commands and associated menu. - - This part is not really specific to extensions, except that menus - take place in the "Extensions" submenu. - - - It is suggested that Magit extensions authors stick to the -convention of making extensions minor modes. This has many advantages, -including the fact that users are able to toggle extensions, and that -it's easy to configure a specific set of extensions for a given -repository. - - Shipped extensions can serve as an example of how to develop new -extensions. - - Basically a `foo' extension should provide a `magit-foo-mode' minor -mode, as well as a `turn-on-magit-foo' function. The main task of the -minor mode is to register/unregister the various hooks that the -extension requires. The registered actions on the other hand can be -left alone and activated globally, since they can be run only on -displayed items, which won't happen when the minor mode is off. - - Don't forget to call `magit-refresh' when the minor mode is toggled -interactively, so that the relevant sections can be shown or hidden. - - -File: magit.info, Node: Using Git Directly, Next: Customization, Prev: Using Magit Extensions, Up: Top - -25 Using Git Directly -********************* - -For situations when Magit doesn't do everything you need, you can run -raw Git commands using `:'. This will prompt for a Git command, run -it, and refresh the status buffer. The output can be viewed by typing -`$'. - - -File: magit.info, Node: Customization, Next: Frequently Asked Questions, Prev: Using Git Directly, Up: Top - -26 Customization -**************** - -The following variables can be used to adapt Magit to your workflow: - -`magit-git-executable' - The name of the Git executable. - -`magit-git-standard-options' - Standard options when running Git. - -`magit-repo-dirs' - Directories containing Git repositories. - - Magit will look into these directories for Git repositories and - offer them as choices for `magit-status'. - -`magit-repo-dirs-depth' - The maximum depth to look for Git repos. - - When looking for a Git repository below the directories in - `magit-repo-dirs', Magit will only descend this many levels deep. - -`magit-save-some-buffers' - Non-nil means that `magit-status' will save modified buffers - before running. Setting this to `t' will ask which buffers to - save, setting it to `'dontask' will save all modified buffers - without asking. - -`magit-save-some-buffers-predicate' - Specifies a predicate function on `magit-save-some-buffers' to - determine which unsaved buffers should be prompted for saving. - -`magit-commit-all-when-nothing-staged' - Determines what `magit-log-edit' does when nothing is staged. - Setting this to `nil' will make it do nothing, setting it to `t' - will arrange things so that the actual commit command will use the - `--all' option, setting it to `'ask' will first ask for - confirmation whether to do this, and setting it to `'ask-stage' - will cause all changes to be staged, after a confirmation. - -`magit-commit-signoff' - When performing `git commit' adds `--signoff'. - -`magit-log-cutoff-length' - The maximum number of commits to show in the `log' and `whazzup' - buffers. - -`magit-log-infinite-length' - Number of log used to show as maximum for - `magit-log-cutoff-length'. - -`magit-log-auto-more' - Insert more log entries automatically when moving past the last - entry. - - Only considered when moving past the last entry with - `magit-goto-next-section'. - -`magit-process-popup-time' - Popup the process buffer if a command takes longer than this many - seconds. - -`magit-revert-item-confirm' - Require acknowledgment before reverting an item. - -`magit-log-edit-confirm-cancellation' - Require acknowledgment before canceling the log edit buffer. - -`magit-remote-ref-format' - What format to use for autocompleting refs, in pariticular for - remotes. - - Autocompletion is used by functions like `magit-checkout', - `magit-interactive-rebase' and others which offer branch name - completion. - - The value `'name-then-remote' means remotes will be of the form - `name (remote)', while the value `'remote-slash-name' means that - they'll be of the form `remote/name'. I.e. something that's listed - as `remotes/upstream/next' by `git branch -l -a' will be - `upstream/next'. - -`magit-process-connection-type' - Connection type used for the git process. - - `nil' mean pipe, it is usually faster and more efficient, and work - on cygwin. `t' mean pty, it enable magit to prompt for passphrase - when needed. - -`magit-completing-read-function' - Function to be called when requesting input from the user. - -`magit-create-branch-behaviour' - Where magit will create a new branch if not supplied a branchname - or ref. - - The value `'at-head' means a new branch will be created at the tip - of your current branch, while the value `'at-point' means magit - will try to find a valid reference at point... - -`magit-status-buffer-switch-function' - Function for `magit-status' to use for switching to the status - buffer. - - The function is given one argument, the status buffer. - -`magit-rewrite-inclusive' - Whether magit includes the selected base commit in a rewrite - operation. - - `t' means both the selected commit as well as any subsequent - commits will be rewritten. This is magit's default behaviour, - equivalent to `git rebase -i ${REV~1}' - - - A'---B'---C'---D' - ^ - - `nil' means the selected commit will be literally used as `base', - so only subsequent commits will be rewritten. This is consistent - with git-rebase, equivalent to `git rebase -i ${REV}', yet more - cumbersome to use from the status buffer. - - - A---B'---C'---D' - ^ - -`magit-topgit-executable' - The name of the TopGit executable. - -`magit-topgit-branch-prefix' - Convention prefix for topic branch creation. - - - -File: magit.info, Node: Frequently Asked Questions, Prev: Customization, Up: Top - -27 Frequently Asked Questions -***************************** - -* Menu: - -* FAQ - Changes:: -* FAQ 1 - Troubleshooting:: -* FAQ 2 - Display issues:: - - -File: magit.info, Node: FAQ - Changes, Next: FAQ 1 - Troubleshooting, Up: Frequently Asked Questions - -27.1 Changes -============ - - * v1.1: Changed the way extensions work. Previously, they were - enabled unconditionally once the library was loaded. Now they are - minor modes that need to be activated explicitly (potentially on a - per-repository basis). See *Note Activating extensions::. - - - -File: magit.info, Node: FAQ 1 - Troubleshooting, Next: FAQ 2 - Display issues, Prev: FAQ - Changes, Up: Frequently Asked Questions - -27.2 Troubleshooting -==================== - -* Menu: - -* FAQ 1-1:: How do I get raw error messages from git? - - -File: magit.info, Node: FAQ 1-1, Up: FAQ 1 - Troubleshooting - -27.2.1 Question 1.1 -------------------- - -How do I get raw error messages from git? - -Answer -...... - -If a command goes wrong, you can hit `$' to access the git process -buffer. There, the entire trace for the latest operation is available. - - -File: magit.info, Node: FAQ 2 - Display issues, Prev: FAQ 1 - Troubleshooting, Up: Frequently Asked Questions - -27.3 Display issues -=================== - -* Menu: - -* FAQ 2-1:: How do I fix international characters display? - - -File: magit.info, Node: FAQ 2-1, Up: FAQ 2 - Display issues - -27.3.1 Question 2.1 -------------------- - -How do I fix international characters display? - -Answer -...... - -Please make sure your Magit buffer uses a compatible coding system. In -the particular case of file names, git itself quotes them by default. -You can disable this with one of the following approaches: - - $ git config core.quotepath false - - or - - (setq magit-git-standard-options (append magit-git-standard-options - '("-c" "core.quotepath=false"))) - - The latter might not work in old versions of git. - - - -Tag Table: -Node: Top639 -Node: Introduction1592 -Node: Acknowledgments3064 -Node: Sections3744 -Node: Status6294 -Node: Untracked files9033 -Node: Staging and Committing10237 -Node: History14135 -Node: Reflogs17315 -Node: Commit Buffer17719 -Node: Diffing19045 -Node: Tagging20032 -Node: Resetting20481 -Node: Stashing22005 -Node: Branching23063 -Node: The Branch Manager24441 -Node: Wazzup25157 -Node: Merging25948 -Node: Rebasing26998 -Node: Interactive Rebasing27824 -Node: Rewriting29116 -Node: Pushing and Pulling32141 -Node: Submodules34068 -Node: Bisecting34488 -Node: Using Magit Extensions35703 -Node: Activating extensions36000 -Node: Interfacing with Subversion37384 -Node: Interfacing with Topgit37982 -Node: Interfacing with StGit39010 -Node: Developing Extensions40008 -Node: Using Git Directly43786 -Node: Customization44157 -Node: Frequently Asked Questions48703 -Node: FAQ - Changes48934 -Node: FAQ 1 - Troubleshooting49342 -Node: FAQ 1-149590 -Node: FAQ 2 - Display issues49894 -Node: FAQ 2-150123 - -End Tag Table diff --git a/elpa/magit-1.2.0/rebase-mode.el b/elpa/magit-1.2.0/rebase-mode.el deleted file mode 100644 index 1ccfb540..00000000 --- a/elpa/magit-1.2.0/rebase-mode.el +++ /dev/null @@ -1,322 +0,0 @@ -;;; rebase-mode -- edit git rebase files. - -;; Copyright (C) 2010 Phil Jackson -;; Copyright (C) 2011 Peter J Weisberg -;; -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see . - -;;; Commentary: - -;; Allows the editing of a git rebase file (which you might get when -;; using 'git rebase -i' or hitting 'E' in Magit). Assumes editing is -;; happening in a server. - -;;; Code: - -(require 'server) - -(defgroup rebase-mode nil - "Customize Rebase Mode" - :group 'faces) - -(defface rebase-mode-killed-action-face - '((((class color)) - :inherit font-lock-comment-face - :strike-through t)) - "Action lines in the rebase TODO list that have been commented out." - :group 'rebase-mode) - -(defface rebase-mode-description-face - '((t :inherit font-lock-comment-face)) - "Face for one-line commit descriptions" - :group 'rebase-mode) - -(defconst rebase-mode-action-line-re - (rx - line-start - (? "#") - (group - (| - (any "presf") - "pick" - "reword" - "edit" - "squash" - "fixup")) - (char space) - (group - (** 4 40 hex-digit)) ;sha1 - (char space) - (group - (* not-newline))) - "Regexp that matches an action line in a rebase buffer.") - -(defconst rebase-mode-exec-line-re - (rx - line-start - (? "#") - (group - (| "x" - "exec")) - (char space) - (group - (* not-newline))) - "Regexp that matches an exec line in a rebase buffer.") - -(defconst rebase-mode-dead-line-re - (rx-to-string `(and line-start - (char ?#) - (or (regexp ,(substring rebase-mode-action-line-re 1)) - (regexp ,(substring rebase-mode-exec-line-re 1)))) t) - "Regexp that matches a commented-out exec or action line in a rebase buffer.") - -(defvar rebase-mode-font-lock-keywords - (list - (list rebase-mode-action-line-re - '(1 font-lock-keyword-face) - '(2 font-lock-builtin-face) - '(3 'rebase-mode-description-face)) - (list rebase-mode-exec-line-re - '(1 font-lock-keyword-face)) - (list (rx line-start (char "#") (* not-newline)) 0 font-lock-comment-face) - (list rebase-mode-dead-line-re 0 ''rebase-mode-killed-action-face t)) - "Font lock keywords for `rebase-mode'.") - -(defvar key-to-action-map - '(("c" . "pick") - ("r" . "reword") - ("e" . "edit") - ("s" . "squash") - ("f" . "fixup")) - "Mapping from key to action.") - -(defvar rebase-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "q") 'server-edit) - (define-key map (kbd "C-c C-c") 'server-edit) - - (define-key map (kbd "a") 'rebase-mode-abort) - (define-key map (kbd "C-c C-k") 'rebase-mode-abort) - - (define-key map (kbd "M-p") 'rebase-mode-move-line-up) - (define-key map (kbd "M-n") 'rebase-mode-move-line-down) - (define-key map (kbd "k") 'rebase-mode-kill-line) - (define-key map (kbd "x") 'rebase-mode-exec) - - (define-key map (kbd "n") 'forward-line) - (define-key map (kbd "p") '(lambda(n) - (interactive "p") - (forward-line (* n -1)))) - (define-key map [remap undo] 'rebase-mode-undo) - map) - "Keymap for rebase-mode. Note this will be added to by the -top-level code which defines the edit functions.") - -(require 'easymenu) -(easy-menu-define rebase-mode-menu rebase-mode-map - "Rebase-mode menu" - '("Rebase" - ["Pick" rebase-mode-pick t] - ["Reword" rebase-mode-reword t] - ["Edit" rebase-mode-edit t] - ["Squash" rebase-mode-squash t] - ["Fixup" rebase-mode-fixup t] - ["Kill" rebase-mode-kill-line t] - ["Move Down" rebase-mode-move-line-down t] - ["Move Up" rebase-mode-move-line-up t] - ["Execute" rebase-mode-exec t] - "---" - ["Abort" rebase-mode-abort t] - ["Done" server-edit t])) - -;; create the functions which edit the action lines themselves (based -;; on `key-to-action-map' above) -(mapc (lambda (key-action) - (let ((fun-name (intern (concat "rebase-mode-" (cdr key-action))))) - ;; define the function - (eval `(defun ,fun-name () - (interactive) - (rebase-mode-edit-line ,(cdr key-action)))) - - ;; bind the function in `rebase-mode-map' - (define-key rebase-mode-map (car key-action) fun-name))) - key-to-action-map) - -(defun rebase-mode-edit-line (change-to) - "Change the keyword at the start of the current action line to -that of CHANGE-TO." - (when (rebase-mode-looking-at-action) - (let ((buffer-read-only nil) - (start (point))) - (goto-char (point-at-bol)) - (delete-region (point) (progn (forward-word 1) (point))) - (insert change-to) - (goto-char start)))) - -(defun rebase-mode-looking-at-action () - "Return non-nil if looking at an action line." - (save-excursion - (goto-char (point-at-bol)) - (looking-at rebase-mode-action-line-re))) - -(defun rebase-mode-looking-at-action-or-exec () - "Return non-nil if looking at an action line or exec line." - (save-excursion - (goto-char (point-at-bol)) - (or (looking-at rebase-mode-action-line-re) - (looking-at rebase-mode-exec-line-re)))) - -(defun rebase-mode-looking-at-exec () - "Return non-nil if cursor is on an exec line." - (string-match rebase-mode-exec-line-re (thing-at-point 'line))) - -(defun rebase-mode-looking-at-killed-exec () - "Return non-nil if looking at an exec line that has been commented out" - (let ((line (thing-at-point 'line))) - (and (eq (aref line 0) ?#) - (string-match rebase-mode-exec-line-re line)))) - -(defun rebase-mode-move-line-up () - "Move the current action line up." - (interactive) - (when (rebase-mode-looking-at-action-or-exec) - (let ((buffer-read-only nil) - (col (current-column))) - (transpose-lines 1) - (forward-line -2) - (move-to-column col)))) - -(defun rebase-mode-move-line-down () - "Assuming the next line is also an action line, move the current line down." - (interactive) - ;; if we're on an action and the next line is also an action - (when (and (rebase-mode-looking-at-action-or-exec) - (save-excursion - (forward-line) - (rebase-mode-looking-at-action-or-exec))) - (let ((buffer-read-only nil) - (col (current-column))) - (forward-line 1) - (transpose-lines 1) - (forward-line -1) - (move-to-column col)))) - -(defun rebase-mode-abort () - "Abort this rebase (by emptying the buffer, saving and closing -server connection)." - (interactive) - (when (or (not (buffer-modified-p)) - (y-or-n-p "Abort this rebase? ")) - (let ((buffer-read-only nil)) - (delete-region (point-min) (point-max)) - (save-buffer) - (server-edit)))) - -(defun rebase-mode-kill-line () - "Kill the current action line." - (interactive) - (when (and (not (eq (char-after (point-at-bol)) ?#)) - (rebase-mode-looking-at-action-or-exec)) - (beginning-of-line) - (let ((buffer-read-only nil)) - (insert "#")) - (forward-line))) - -(defun rebase-mode-exec (edit) - "Prompt the user for a shell command to be executed, and add it to -the todo list. - -If the cursor is on a commented-out exec line, uncomment the -current line instead of prompting. - -When the prefix argument EDIT is non-nil and the cursor is on an -exec line, edit that line instead of inserting a new one. If the -exec line was commented out, also uncomment it." - (interactive "P") - (cond - ((and edit (rebase-mode-looking-at-exec)) - (let ((new-line (rebase-mode-read-exec-line - (match-string-no-properties 2 (thing-at-point 'line)))) - (inhibit-read-only t)) - (delete-region (point-at-bol) (point-at-eol)) - (if (not (equal "" new-line)) - (insert "exec " new-line) - (delete-char -1) - (forward-line)) - (move-beginning-of-line nil))) - ((rebase-mode-looking-at-killed-exec) - (save-excursion - (beginning-of-line) - (let ((buffer-read-only nil)) - (delete-char 1)))) - (t - (let ((inhibit-read-only t) - (line (rebase-mode-read-exec-line))) - (unless (equal "" line) - (move-end-of-line nil) - (newline) - (insert (concat "exec " line)))) - (move-beginning-of-line nil)))) - -(defun rebase-mode-read-exec-line (&optional initial-line) - (read-shell-command "Execute: " initial-line)) - -(defun rebase-mode-undo (&optional arg) - "A thin wrapper around `undo', which allows undoing in -read-only buffers." - (interactive "P") - (let ((inhibit-read-only t)) - (undo arg))) - -;;;###autoload -(define-derived-mode rebase-mode special-mode "Rebase" - "Major mode for editing of a Git rebase file. - -Rebase files are generated when you run 'git rebase -i' or run -`magit-interactive-rebase'. They describe how Git should perform -the rebase. See the documentation for git-rebase (e.g., by -running 'man git-rebase' at the command line) for details." - (setq font-lock-defaults '(rebase-mode-font-lock-keywords t t))) - -(defun rebase-mode-show-keybindings () - "Modify the \"Commands:\" section of the comment Git generates -at the bottom of the file so that in place of the one-letter -abbreviation for the command, it shows the command's keybinding. -By default, this is the same except for the \"pick\" command." - (save-excursion - (goto-char (point-min)) - (while (search-forward-regexp "^# \\(.\\), \\([[:alpha:]]+\\) = " nil t) - (let ((start (match-beginning 1)) - (end (match-end 1)) - (command (intern (concat "rebase-mode-" (match-string 2))))) - (when (fboundp command) - (let ((overlay (make-overlay start end))) - (overlay-put overlay - 'display - (key-description (where-is-internal command nil t))))))))) - -(add-hook 'rebase-mode-hook 'rebase-mode-show-keybindings t) - -(defun rebase-mode-disable-before-save-hook () - (set (make-local-variable 'before-save-hook) nil)) - -(add-hook 'rebase-mode-hook 'rebase-mode-disable-before-save-hook) - -;;;###autoload -(add-to-list 'auto-mode-alist - '("git-rebase-todo" . rebase-mode)) - -(provide 'rebase-mode) - -;;; rebase-mode.el ends here diff --git a/elpa/magit-20190122.503/magit-bookmark.el b/elpa/magit-20190122.503/magit-bookmark.el deleted file mode 100644 index 2d76f861..00000000 --- a/elpa/magit-20190122.503/magit-bookmark.el +++ /dev/null @@ -1,371 +0,0 @@ -;;; magit-bookmark.el --- bookmark support for Magit -*- lexical-binding: t -*- - -;; Copyright (C) 2010-2019 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Yuri Khan -;; Maintainer: Jonas Bernoulli - -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see http://www.gnu.org/licenses. - -;;; Commentary: - -;; Support for bookmarks for most Magit buffers. - -;;; Code: - -(eval-when-compile - (require 'subr-x)) - -(require 'magit) -(require 'bookmark) - -;;; Supporting primitives - -(defun magit-bookmark--jump (bookmark fn &rest args) - "Handle a Magit BOOKMARK. - -This function will: - -1. Bind `default-directory' to the repository root directory - stored in the `filename' bookmark property. -2. Invoke the function FN with ARGS as arguments. This needs to - restore the buffer. -3. Restore the expanded/collapsed status of top level sections - and the point position." - (declare (indent 2)) - (let* ((default-directory (bookmark-get-filename bookmark))) - (if default-directory - (apply fn args) - (signal 'bookmark-error-no-filename (list 'stringp default-directory))) - (when (derived-mode-p 'magit-mode) - (when-let ((hidden-sections (bookmark-prop-get bookmark - 'magit-hidden-sections))) - (dolist (child (oref magit-root-section children)) - (if (member (cons (oref child type) - (oref child value)) - hidden-sections) - (magit-section-hide child) - (magit-section-show child))))) - (--when-let (bookmark-get-position bookmark) - (goto-char it)) - (--when-let (bookmark-get-front-context-string bookmark) - (when (search-forward it (point-max) t) - (goto-char (match-beginning 0)))) - (--when-let (bookmark-get-rear-context-string bookmark) - (when (search-backward it (point-min) t) - (goto-char (match-end 0)))) - nil)) - -(defun magit-bookmark--make-record (mode handler &optional make-props) - "Create a Magit bookmark. - -MODE specifies the expected major mode of current buffer. - -HANDLER should be a function that will be used to restore this -buffer. - -MAKE-PROPS should be either nil or a function that will be called -with `magit-refresh-args' as the argument list, and may return an -alist whose every element has the form (PROP . VALUE) and -specifies additional properties to store in the bookmark." - (declare (indent 1)) - (unless (eq major-mode mode) - (user-error "Not in a %s buffer" mode)) - (let ((bookmark (bookmark-make-record-default 'no-file))) - (bookmark-prop-set bookmark 'handler handler) - (bookmark-set-filename bookmark (magit-toplevel)) - (when (derived-mode-p 'magit-mode) - (bookmark-prop-set - bookmark 'magit-hidden-sections - (--map (cons (oref it type) - (oref it value)) - (--filter (oref it hidden) - (oref magit-root-section children))))) - (when make-props - (pcase-dolist (`(,prop . ,value) (apply make-props magit-refresh-args)) - (bookmark-prop-set bookmark prop value))) - bookmark)) - -;;; Status - -;;;###autoload -(defun magit-bookmark--status-jump (bookmark) - "Handle a Magit status BOOKMARK." - (magit-bookmark--jump bookmark - (lambda () (magit-status-internal default-directory)))) - -;;;###autoload -(defun magit-bookmark--status-make-record () - "Create a Magit status bookmark." - (magit-bookmark--make-record 'magit-status-mode - #'magit-bookmark--status-jump)) - -;;; Refs - -;;;###autoload -(defun magit-bookmark--refs-jump (bookmark) - "Handle a Magit refs BOOKMARK." - (magit-bookmark--jump bookmark #'magit-show-refs - (bookmark-prop-get bookmark 'magit-refs) - (bookmark-prop-get bookmark 'magit-args))) - -;;;###autoload -(defun magit-bookmark--refs-make-record () - "Create a Magit refs bookmark." - (magit-bookmark--make-record 'magit-refs-mode - #'magit-bookmark--refs-jump - (lambda (refs args) - `((magit-refs . ,refs) - (magit-args . ,args))))) - -;;; Log - -;;;###autoload -(defun magit-bookmark--log-jump (bookmark) - "Handle a Magit log BOOKMARK." - (magit-bookmark--jump bookmark #'magit-log-other - (bookmark-prop-get bookmark 'magit-revs) - (bookmark-prop-get bookmark 'magit-args) - (bookmark-prop-get bookmark 'magit-files))) - -(defun magit-bookmark--log-make-name (buffer-name revs _args files) - "Generate the default name for a log bookmark." - (concat - buffer-name " " (mapconcat #'identity revs " ") - (and files - (concat " touching " (mapconcat #'identity files " "))))) - -;;;###autoload -(defun magit-bookmark--log-make-record () - "Create a Magit log bookmark." - (magit-bookmark--make-record 'magit-log-mode - #'magit-bookmark--log-jump - (lambda (revs args files) - `((defaults . (,(magit-bookmark--log-make-name - (buffer-name) revs args files))) - (magit-revs . ,revs) - (magit-args . ,args) - (magit-files . ,files))))) - -;;; Reflog - -;;;###autoload -(defun magit-bookmark--reflog-jump (bookmark) - "Handle a Magit reflog BOOKMARK." - (magit-bookmark--jump bookmark - (lambda () - (let ((magit-reflog-arguments (bookmark-prop-get bookmark 'magit-args))) - (magit-git-reflog (bookmark-prop-get bookmark 'magit-ref) - magit-reflog-arguments))))) - -(defun magit-bookmark--reflog-make-name (buffer-name ref) - "Generate the default name for a reflog bookmark." - (concat buffer-name " " ref)) - -;;;###autoload -(defun magit-bookmark--reflog-make-record () - "Create a Magit reflog bookmark." - (magit-bookmark--make-record 'magit-reflog-mode - #'magit-bookmark--reflog-jump - (lambda (ref args) - `((defaults . (,(magit-bookmark--reflog-make-name (buffer-name) ref))) - (magit-ref . ,ref) - (magit-args . ,args))))) - -;;; Stashes - -;;;###autoload -(defun magit-bookmark--stashes-jump (bookmark) - "Handle a Magit stash list BOOKMARK." - (magit-bookmark--jump bookmark #'magit-stash-list)) - -;;;###autoload -(defun magit-bookmark--stashes-make-record () - "Create a Magit stash list bookmark." - (magit-bookmark--make-record 'magit-stashes-mode - #'magit-bookmark--stashes-jump)) - -;;; Cherry - -;;;###autoload -(defun magit-bookmark--cherry-jump (bookmark) - "Handle a Magit cherry BOOKMARK." - (magit-bookmark--jump bookmark #'magit-cherry - (bookmark-prop-get bookmark 'magit-head) - (bookmark-prop-get bookmark 'magit-upstream))) - -(defun magit-bookmark--cherry-make-name (buffer-name head upstream) - "Generate the default name for a cherry bookmark." - (concat buffer-name " " head " upstream " upstream)) - -;;;###autoload -(defun magit-bookmark--cherry-make-record () - "Create a Magit cherry bookmark." - (magit-bookmark--make-record 'magit-cherry-mode - #'magit-bookmark--cherry-jump - (lambda (upstream head) - `((defaults . (,(magit-bookmark--cherry-make-name - (buffer-name) head upstream))) - (magit-head . ,head) - (magit-upstream . ,upstream))))) - -;;; Diff - -;;;###autoload -(defun magit-bookmark--diff-jump (bookmark) - "Handle a Magit diff BOOKMARK." - (magit-bookmark--jump bookmark #'magit-diff-setup - (bookmark-prop-get bookmark 'magit-rev-or-range) - (bookmark-prop-get bookmark 'magit-const) - (bookmark-prop-get bookmark 'magit-args) - (bookmark-prop-get bookmark 'magit-files))) - -(defun magit-bookmark--resolve (rev-or-range) - "Return REV-OR-RANGE with ref names resolved to commit hashes." - (pcase (magit-git-lines "rev-parse" rev-or-range) - (`(,rev) - (magit-rev-abbrev rev)) - ((and `(,rev1 ,rev2) - (guard (/= ?^ (aref rev1 0))) - (guard (= ?^ (aref rev2 0)))) - (concat (magit-rev-abbrev (substring rev2 1)) - ".." - (magit-rev-abbrev rev1))) - ((and `(,rev1 ,rev2 ,rev3) - (guard (/= ?^ (aref rev1 0))) - (guard (/= ?^ (aref rev2 0))) - (guard (= ?^ (aref rev3 0)))) - (ignore rev3) - (concat (magit-rev-abbrev rev1) - "..." - (magit-rev-abbrev rev2))) - (_ - rev-or-range))) - -(defun magit-bookmark--diff-make-name - (buffer-name rev-or-range const _args files) - "Generate a default name for a diff bookmark." - (if (member "--no-index" const) - (apply #'format "*magit-diff %s %s" files) - (concat buffer-name " " - (cond (rev-or-range) - ((member "--cached" const) "staged") - (t "unstaged")) - (when files - (concat " in " (mapconcat #'identity files ", ")))))) - -;;;###autoload -(defun magit-bookmark--diff-make-record () - "Create a Magit diff bookmark." - (magit-bookmark--make-record 'magit-diff-mode - #'magit-bookmark--diff-jump - (lambda (rev-or-range const args files) - (let ((resolved (magit-bookmark--resolve rev-or-range))) - `((defaults . (,(magit-bookmark--diff-make-name - (buffer-name) resolved const args files))) - (magit-rev-or-range . ,resolved) - (magit-const . ,const) - (magit-args . ,args) - (magit-files . ,files)))))) - -;;; Revision - -;;;###autoload -(defun magit-bookmark--revision-jump (bookmark) - "Handle a Magit revision BOOKMARK." - (magit-bookmark--jump bookmark #'magit-show-commit - (bookmark-prop-get bookmark 'magit-rev) - (bookmark-prop-get bookmark 'args) - (bookmark-prop-get bookmark 'files))) - -(defun magit-bookmark--revision-make-name (buffer-name rev _args files) - "Generate a default name for a revision bookmark." - (let ((subject (magit-rev-format "%s" rev))) - (concat buffer-name " " - (magit-rev-abbrev rev) - (cond (files (concat " " (mapconcat #'identity files " "))) - (subject (concat " " subject)))))) - -;;;###autoload -(defun magit-bookmark--revision-make-record () - "Create a Magit revision bookmark." - ;; magit-refresh-args stores the revision in relative form. - ;; For bookmarks, the exact hash is more appropriate. - (magit-bookmark--make-record 'magit-revision-mode - #'magit-bookmark--revision-jump - (lambda (_rev _ args files) - `((defaults . (,(magit-bookmark--revision-make-name - (buffer-name) magit-buffer-revision-hash - args files))) - (magit-rev . ,magit-buffer-revision-hash) - (magit-args . ,args) - (magit-files . ,files))))) - -;;; Stash - -;;;###autoload -(defun magit-bookmark--stash-jump (bookmark) - "Handle a Magit stash BOOKMARK." - (magit-bookmark--jump bookmark #'magit-stash-show - (bookmark-prop-get bookmark 'magit-stash) - (bookmark-prop-get bookmark 'magit-args) - (bookmark-prop-get bookmark 'magit-files))) - -(defun magit-bookmark--stash-make-name (buffer-name stash _args files) - "Generate the default name for a stash bookmark." - (concat buffer-name " " stash " " - (if files - (mapconcat #'identity files " ") - (magit-rev-format "%s" stash)))) - -;;;###autoload -(defun magit-bookmark--stash-make-record () - "Create a Magit stash bookmark." - (magit-bookmark--make-record 'magit-stash-mode - #'magit-bookmark--stash-jump - (lambda (stash _ args files) - `((defaults . (,(magit-bookmark--stash-make-name - (buffer-name) - (magit-rev-abbrev magit-buffer-revision-hash) - args files))) - (magit-stash . ,magit-buffer-revision-hash) - (magit-args . ,args) - (magit-files . ,files) - (magit-hidden-sections - . ,(--map `(,(oref it type) - . ,(replace-regexp-in-string (regexp-quote stash) - magit-buffer-revision-hash - (oref it value))) - (--filter (oref it hidden) - (oref magit-root-section children)))))))) - -;;; Submodules - -;;;###autoload -(defun magit-bookmark--submodules-jump (bookmark) - "Handle a Magit submodule list BOOKMARK." - (magit-bookmark--jump bookmark #'magit-list-submodules)) - -;;;###autoload -(defun magit-bookmark--submodules-make-record () - "Create a Magit submodule list bookmark." - (magit-bookmark--make-record 'magit-submodule-list-mode - #'magit-bookmark--submodules-jump)) - -;;; _ -(provide 'magit-bookmark) -;;; magit-bookmark.el ends here diff --git a/elpa/magit-20190122.503/magit-clone.el b/elpa/magit-20190122.503/magit-clone.el deleted file mode 100644 index b099c2e4..00000000 --- a/elpa/magit-20190122.503/magit-clone.el +++ /dev/null @@ -1,104 +0,0 @@ -;;; magit-clone.el --- clone a repository -*- lexical-binding: t -*- - -;; Copyright (C) 2008-2019 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see http://www.gnu.org/licenses. - -;;; Commentary: - -;; This library implements clone commands. - -;;; Code: - -(require 'magit) - -;;; Options - -(defcustom magit-clone-set-remote-head nil - "Whether cloning creates the symbolic-ref `/HEAD'." - :package-version '(magit . "2.4.2") - :group 'magit-commands - :type 'boolean) - -(defcustom magit-clone-set-remote.pushDefault 'ask - "Whether to set the value of `remote.pushDefault' after cloning. - -If t, then set without asking. If nil, then don't set. If -`ask', then ask." - :package-version '(magit . "2.4.0") - :group 'magit-commands - :type '(choice (const :tag "set" t) - (const :tag "ask" ask) - (const :tag "don't set" nil))) - -(defcustom magit-clone-default-directory nil - "Default directory to use when `magit-clone' reads destination. -If nil (the default), then use the value of `default-directory'. -If a directory, then use that. If a function, then call that -with the remote url as only argument and use the returned value." - :package-version '(magit . "2.90.0") - :group 'magit-commands - :type '(choice (const :tag "value of default-directory") - (directory :tag "constant directory") - (function :tag "function's value"))) - -;;; Commands - -;;;###autoload -(defun magit-clone (repository directory) - "Clone the REPOSITORY to DIRECTORY. -Then show the status buffer for the new repository." - (interactive - (let ((url (magit-read-string-ns "Clone repository"))) - (list url (read-directory-name - "Clone to: " - (if (functionp magit-clone-default-directory) - (funcall magit-clone-default-directory url) - magit-clone-default-directory) - nil nil - (and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" url) - (match-string 1 url)))))) - (run-hooks 'magit-credential-hook) - (setq directory (file-name-as-directory (expand-file-name directory))) - (magit-run-git-async "clone" repository - (magit-convert-filename-for-git directory)) - ;; Don't refresh the buffer we're calling from. - (process-put magit-this-process 'inhibit-refresh t) - (set-process-sentinel - magit-this-process - (lambda (process event) - (when (memq (process-status process) '(exit signal)) - (let ((magit-process-raise-error t)) - (magit-process-sentinel process event))) - (when (and (eq (process-status process) 'exit) - (= (process-exit-status process) 0)) - (let ((default-directory directory)) - (when (or (eq magit-clone-set-remote.pushDefault t) - (and magit-clone-set-remote.pushDefault - (y-or-n-p "Set `remote.pushDefault' to \"origin\"? "))) - (setf (magit-get "remote.pushDefault") "origin")) - (unless magit-clone-set-remote-head - (magit-remote-unset-head "origin"))) - (with-current-buffer (process-get process 'command-buf) - (magit-status-internal directory)))))) - -;;; _ -(provide 'magit-clone) -;;; magit-clone.el ends here diff --git a/elpa/magit-20190122.503/magit-gitignore.el b/elpa/magit-20190122.503/magit-gitignore.el deleted file mode 100644 index d1d96bde..00000000 --- a/elpa/magit-20190122.503/magit-gitignore.el +++ /dev/null @@ -1,98 +0,0 @@ -;;; magit-gitignore.el --- intentionally untracked files -*- lexical-binding: t -*- - -;; Copyright (C) 2008-2019 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see http://www.gnu.org/licenses. - -;;; Commentary: - -;; This library implements gitignore commands. - -;;; Code: - -(eval-when-compile - (require 'subr-x)) - -(require 'magit) - -;;; Commands - -;;;###autoload (autoload 'magit-gitignore-popup "magit-gitignore" nil t) -(magit-define-popup magit-gitignore-popup - "Popup console for gitignore commands." - :man-page "gitignore" - :actions '((?l "ignore locally" magit-gitignore-locally) - (?g "ignore globally" magit-gitignore-globally)) - :max-action-columns 1) - -;;;###autoload -(defun magit-gitignore-globally (file-or-pattern) - "Instruct Git to globally ignore FILE-OR-PATTERN." - (interactive (list (magit-gitignore-read-pattern nil))) - (magit--gitignore file-or-pattern nil)) - -;;;###autoload -(defun magit-gitignore-locally (file-or-pattern) - "Instruct Git to locally ignore FILE-OR-PATTERN." - (interactive (list (magit-gitignore-read-pattern t))) - (magit--gitignore file-or-pattern t)) - -(defun magit--gitignore (file-or-pattern local) - (let ((gitignore - (if local - (magit-git-dir (convert-standard-filename "info/exclude")) - (expand-file-name ".gitignore" (magit-toplevel))))) - (make-directory (file-name-directory gitignore) t) - (with-temp-buffer - (when (file-exists-p gitignore) - (insert-file-contents gitignore)) - (goto-char (point-max)) - (unless (bolp) - (insert "\n")) - (insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" file-or-pattern)) - (insert "\n") - (write-region nil nil gitignore)) - (if local - (magit-refresh) - (magit-run-git "add" ".gitignore")))) - -(defun magit-gitignore-read-pattern (local) - (let* ((default (magit-current-file)) - (choices - (delete-dups - (--mapcat - (cons (concat "/" it) - (when-let ((ext (file-name-extension it))) - (list (concat "/" (file-name-directory "foo") "*." ext) - (concat "*." ext)))) - (magit-untracked-files))))) - (when default - (setq default (concat "/" default)) - (unless (member default choices) - (setq default (concat "*." (file-name-extension default))) - (unless (member default choices) - (setq default nil)))) - (magit-completing-read (concat "File or pattern to ignore" - (and local " locally")) - choices nil nil nil nil default))) - -;;; _ -(provide 'magit-gitignore) -;;; magit-gitignore.el ends here diff --git a/elpa/magit-20190122.503/magit-obsolete.el b/elpa/magit-20190122.503/magit-obsolete.el deleted file mode 100644 index 0cabad4d..00000000 --- a/elpa/magit-20190122.503/magit-obsolete.el +++ /dev/null @@ -1,55 +0,0 @@ -;;; magit-obsolete.el --- obsolete definitions -*- lexical-binding: t -*- - -;; Copyright (C) 2010-2019 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see http://www.gnu.org/licenses. - -;;; Commentary: - -;; This library defines aliases for obsolete variables and functions. - -;;; Code: - -(require 'magit) - -;;; Obsolete since v2.90.0 - -(define-obsolete-function-alias 'magit-reset-head 'magit-reset-mixed "Magit 2.90.0") -(define-obsolete-function-alias 'magit-gitignore 'magit-gitignore-globally "Magit 2.90.0") -(define-obsolete-function-alias 'magit-branch 'magit-branch-create "Magit 2.90.0") -(define-obsolete-function-alias 'magit-tag 'magit-tag-create "Magit 2.90.0") -(define-obsolete-function-alias 'magit-fetch 'magit-fetch-other "Magit 2.90.0") -(define-obsolete-function-alias 'magit-pull 'magit-pull-branch "Magit 2.90.0") -(define-obsolete-function-alias 'magit-rebase 'magit-rebase-branch "Magit 2.90.0") -(define-obsolete-function-alias 'magit-blame 'magit-blame-addition "Magit 2.90.0") -(define-obsolete-function-alias 'magit-revert 'magit-revert-and-commit "Magit 2.90.0") -(define-obsolete-function-alias 'magit-reset 'magit-reset-quickly "Magit 2.90.0") -(define-obsolete-function-alias 'magit-merge 'magit-merge-plain "Magit 2.90.0") -(define-obsolete-function-alias 'magit-stash 'magit-stash-both "Magit 2.90.0") -(define-obsolete-function-alias 'magit-snapshot 'magit-snapshot-both "Magit 2.90.0") -(define-obsolete-function-alias 'magit-push 'magit-push-other "Magit 2.90.0") -(define-obsolete-function-alias 'magit-commit 'magit-commit-create "Magit 2.90.0") -(define-obsolete-function-alias 'magit-log 'magit-log-other "Magit 2.90.0") -(define-obsolete-function-alias 'magit-reflog 'magit-reflog-other "Magit 2.90.0") -(define-obsolete-function-alias 'magit-diff 'magit-diff-range "Magit 2.90.0") - -;;; _ -(provide 'magit-obsolete) -;;; magit-obsolete.el ends here diff --git a/elpa/magit-20190122.503/magit-patch.el b/elpa/magit-20190122.503/magit-patch.el deleted file mode 100644 index 96bd0922..00000000 --- a/elpa/magit-20190122.503/magit-patch.el +++ /dev/null @@ -1,188 +0,0 @@ -;;; magit-patch.el --- creating and applying patches -*- lexical-binding: t -*- - -;; Copyright (C) 2008-2019 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see http://www.gnu.org/licenses. - -;;; Commentary: - -;; This library implements patch commands. - -;;; Code: - -(eval-when-compile - (require 'subr-x)) - -(require 'magit) - -;;; Options - -(defcustom magit-patch-save-arguments '(exclude "--stat") - "Arguments used by `magit-patch-save-arguments' (which see)" - :package-version '(magit . "2.12.0") - :group 'magit-diff - :type '(choice (const :tag "use buffer arguments" buffer) - (cons :tag "use buffer arguments except" - (const :format "" exclude) - (repeat :format "%v%i\n" - (string :tag "Argument"))) - (repeat :tag "use constant arguments" - (string :tag "Argument")))) - -;;; Commands - -;;;###autoload (autoload 'magit-patch-popup "magit-patch" nil t) -(magit-define-popup magit-patch-popup - "Popup console for patch commands." - :man-page "git-format-patch" - :switches '("Switches for formatting patches" - (?l "Add cover letter" "--cover-letter")) - :options '("Options for formatting patches" - (?f "From" "--from=") - (?t "To" "--to=") - (?c "CC" "--cc=") - (?r "In reply to" "--in-reply-to=") - (?P "Subject Prefix" "--subject-prefix=") - (?v "Reroll count" "--reroll-count=") - (?s "Thread style" "--thread=") - (?U "Context lines" "-U") - (?M "Detect renames" "-M") - (?C "Detect copies" "-C") - (?A "Diff algorithm" "--diff-algorithm=" - magit-diff-select-algorithm) - (?o "Output directory" "--output-directory=") - (?F "Limit to files" "-- " magit-read-files)) - :actions '((?p "Format patches" magit-format-patch) - (?r "Request pull" magit-request-pull)) - :default-action 'magit-format-patch) - -;;;###autoload -(defun magit-format-patch (range args files) - "Create patches for the commits in RANGE. -When a single commit is given for RANGE, create a patch for the -changes introduced by that commit (unlike 'git format-patch' -which creates patches for all commits that are reachable from -`HEAD' but not from the specified commit)." - (interactive - (cons (if-let ((revs (magit-region-values 'commit t))) - (concat (car (last revs)) "^.." (car revs)) - (let ((range (magit-read-range-or-commit - "Format range or commit"))) - (if (string-match-p "\\.\\." range) - range - (format "%s~..%s" range range)))) - (magit-popup-export-file-args (magit-patch-arguments)))) - (magit-run-git "format-patch" range args "--" files) - (when (member "--cover-letter" args) - (find-file - (expand-file-name - "0000-cover-letter.patch" - (let ((topdir (magit-toplevel))) - (or (--some (and (string-match "--output-directory=\\(.+\\)" it) - (expand-file-name (match-string 1 it) topdir)) - args) - topdir)))))) - -;;;###autoload -(defun magit-request-pull (url start end) - "Request upstream to pull from you public repository. - -URL is the url of your publically accessible repository. -START is a commit that already is in the upstream repository. -END is the last commit, usually a branch name, which upstream -is asked to pull. START has to be reachable from that commit." - (interactive - (list (magit-get "remote" (magit-read-remote "Remote") "url") - (magit-read-branch-or-commit "Start" (magit-get-upstream-branch)) - (magit-read-branch-or-commit "End"))) - (let ((dir default-directory)) - ;; mu4e changes default-directory - (compose-mail) - (setq default-directory dir)) - (message-goto-body) - (magit-git-insert "request-pull" start url end) - (set-buffer-modified-p nil)) - -;;;###autoload (autoload 'magit-patch-apply-popup "magit-patch" nil t) -(magit-define-popup magit-patch-apply-popup - "Popup console for applying a patch file." - :man-page "git-apply" - :switches '((?i "Also apply to index" "--index") - (?c "Only apply to index" "--cached") - (?3 "Fall back on 3way merge" "--3way")) - :actions '((?a "Apply patch" magit-patch-apply)) - :default-action 'magit-patch-apply) - -;;;###autoload -(defun magit-patch-apply (file &rest args) - "Apply the patch file FILE." - (interactive (list (expand-file-name - (read-file-name "Apply patch: " - default-directory nil nil - (--when-let (magit-file-at-point) - (file-relative-name it)))) - (magit-patch-apply-arguments))) - (magit-run-git "apply" args "--" (magit-convert-filename-for-git file))) - -;;;###autoload -(defun magit-patch-save (file &optional arg) - "Write current diff into patch FILE. - -What arguments are used to create the patch depends on the value -of `magit-patch-save-arguments' and whether a prefix argument is -used. - -If the value is the symbol `buffer', then use the same arguments -as the buffer. With a prefix argument use no arguments. - -If the value is a list beginning with the symbol `exclude', then -use the same arguments as the buffer except for those matched by -entries in the cdr of the list. The comparison is done using -`string-prefix-p'. With a prefix argument use the same arguments -as the buffer. - -If the value is a list of strings (including the empty list), -then use those arguments. With a prefix argument use the same -arguments as the buffer. - -Of course the arguments that are required to actually show the -same differences as those shown in the buffer are always used." - (interactive (list (read-file-name "Write patch file: " default-directory) - current-prefix-arg)) - (unless (derived-mode-p 'magit-diff-mode) - (user-error "Only diff buffers can be saved as patches")) - (pcase-let ((`(,rev ,const ,args ,files) magit-refresh-args)) - (when (derived-mode-p 'magit-revision-mode) - (setq rev (format "%s~..%s" rev rev))) - (cond ((eq magit-patch-save-arguments 'buffer) - (when arg - (setq args nil))) - ((eq (car-safe magit-patch-save-arguments) 'exclude) - (unless arg - (setq args (-difference args (cdr magit-patch-save-arguments))))) - ((not arg) - (setq args magit-patch-save-arguments))) - (with-temp-file file - (magit-git-insert "diff" rev "-p" const args "--" files))) - (magit-refresh)) - -;;; _ -(provide 'magit-patch) -;;; magit-patch.el ends here diff --git a/elpa/magit-20190122.503/magit-pkg.el b/elpa/magit-20190122.503/magit-pkg.el deleted file mode 100644 index 61df63e1..00000000 --- a/elpa/magit-20190122.503/magit-pkg.el +++ /dev/null @@ -1,10 +0,0 @@ -(define-package "magit" "20190122.503" "A Git porcelain inside Emacs." - '((emacs "25.1") - (async "20180527") - (dash "20180910") - (git-commit "20181104") - (magit-popup "20181003") - (with-editor "20181103"))) -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/magit-20190122.503/magit-pull.el b/elpa/magit-20190122.503/magit-pull.el deleted file mode 100644 index 41c49bf0..00000000 --- a/elpa/magit-20190122.503/magit-pull.el +++ /dev/null @@ -1,151 +0,0 @@ -;;; magit-pull.el --- update local objects and refs -*- lexical-binding: t -*- - -;; Copyright (C) 2008-2019 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Magit is free software; you can redistribute it and/or modify it -;; 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. -;; -;; Magit is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with Magit. If not, see http://www.gnu.org/licenses. - -;;; Commentary: - -;; This library implements pull commands. - -;;; Code: - -(require 'magit) - -;;; Commands - -;;;###autoload (autoload 'magit-pull-popup "magit-pull" nil t) -(magit-define-popup magit-pull-popup - "Popup console for pull commands." - :man-page "git-pull" - :variables '("Configure" - (?r "branch.%s.rebase" - magit-cycle-branch*rebase - magit-pull-format-branch*rebase) - (?C "variables..." magit-branch-config-popup)) - :actions '((lambda () - (--if-let (magit-get-current-branch) - (concat - (propertize "Pull into " 'face 'magit-popup-heading) - (propertize it 'face 'magit-branch-local) - (propertize " from" 'face 'magit-popup-heading)) - (propertize "Pull from" 'face 'magit-popup-heading))) - (?p magit-get-push-branch magit-pull-from-pushremote) - (?u magit-get-upstream-branch magit-pull-from-upstream) - (?e "elsewhere" magit-pull-branch)) - :default-action 'magit-pull - :max-action-columns 1) - -;;;###autoload (autoload 'magit-pull-and-fetch-popup "magit-pull" nil t) -(magit-define-popup magit-pull-and-fetch-popup - "Popup console for pull and fetch commands. - -This popup is intended as a replacement for the separate popups -`magit-pull-popup' and `magit-fetch-popup'. To use it, add this -to your init file: - - (with-eval-after-load \\='magit-remote - (define-key magit-mode-map \"f\" \\='magit-pull-and-fetch-popup) - (define-key magit-mode-map \"F\" nil)) - -The combined popup does not offer all commands and arguments -available from the individual popups. Instead of the argument -`--prune' and the command `magit-fetch-all' it uses two commands -`magit-fetch-prune' and `magit-fetch-no-prune'. And the commands -`magit-fetch-from-pushremote' and `magit-fetch-from-upstream' are -missing. To add them use something like: - - (with-eval-after-load \\='magit-remote - (magit-define-popup-action \\='magit-pull-and-fetch-popup ?U - \\='magit-get-upstream-branch - \\='magit-fetch-from-upstream-remote ?F) - (magit-define-popup-action \\='magit-pull-and-fetch-popup ?P - \\='magit-get-push-branch - \\='magit-fetch-from-push-remote ?F))" - :man-page "git-pull" - :variables '("Configure" - (?r "branch.%s.rebase" - magit-cycle-branch*rebase - magit-pull-format-branch*rebase) - (?C "variables..." magit-branch-config-popup)) - :actions '((lambda () - (--if-let (magit-get-current-branch) - (concat - (propertize "Pull into " 'face 'magit-popup-heading) - (propertize it 'face 'magit-branch-local) - (propertize " from" 'face 'magit-popup-heading)) - (propertize "Pull from" 'face 'magit-popup-heading))) - (?p magit-get-push-branch magit-pull-from-pushremote) - (?u magit-get-upstream-branch magit-pull-from-upstream) - (?e "elsewhere" magit-pull-branch) - "Fetch from" - (?f "remotes" magit-fetch-all-no-prune) - (?F "remotes and prune" magit-fetch-all-prune) - "Fetch" - (?o "another branch" magit-fetch-branch) - (?s "explicit refspec" magit-fetch-refspec) - (?m "submodules" magit-fetch-modules)) - :default-action 'magit-fetch - :max-action-columns 1) - -(defun magit-pull-format-branch*rebase () - (magit--format-popup-variable:choices - (format "branch.%s.rebase" (or (magit-get-current-branch) "")) - '("true" "false") - "false" "pull.rebase")) - -(defun magit-git-pull (source args) - (run-hooks 'magit-credential-hook) - (pcase-let ((`(,remote . ,branch) - (magit-split-branch-name source))) - (magit-run-git-with-editor "pull" args remote branch))) - -;;;###autoload -(defun magit-pull-from-pushremote (args) - "Pull from the push-remote of the current branch." - (interactive (list (magit-pull-arguments))) - (--if-let (magit-get-push-branch) - (magit-git-pull it args) - (--if-let (magit-get-current-branch) - (user-error "No push-remote is configured for %s" it) - (user-error "No branch is checked out")))) - -;;;###autoload -(defun magit-pull-from-upstream (args) - "Pull from the upstream of the current branch." - (interactive (list (magit-pull-arguments))) - (--if-let (magit-get-upstream-branch) - (progn (run-hooks 'magit-credential-hook) - (magit-run-git-with-editor - "pull" args (car (magit-split-branch-name it)))) - (--if-let (magit-get-current-branch) - (user-error "No upstream is configured for %s" it) - (user-error "No branch is checked out")))) - -;;;###autoload -(defun magit-pull-branch (source args) - "Pull from a branch read in the minibuffer." - (interactive (list (magit-read-remote-branch "Pull" nil nil nil t) - (magit-pull-arguments))) - (magit-git-pull source args)) - -;;; _ -(provide 'magit-pull) -;;; magit-pull.el ends here diff --git a/elpa/magit-20190122.503/magit.info b/elpa/magit-20190122.503/magit.info deleted file mode 100644 index 1beabf75..00000000 --- a/elpa/magit-20190122.503/magit.info +++ /dev/null @@ -1,187 +0,0 @@ -This is magit.info, produced by makeinfo version 6.5 from magit.texi. - - Copyright (C) 2015-2019 Jonas Bernoulli - - You can redistribute this document and/or modify it under the terms - of the GNU General Public License as published by the Free Software - Foundation, either version 3 of the License, or (at your option) - any later version. - - This document is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* Magit: (magit). Using Git from Emacs with Magit. -END-INFO-DIR-ENTRY - - -Indirect: -magit.info-1: 754 -magit.info-2: 305233 - -Tag Table: -(Indirect) -Node: Top754 -Node: Introduction6307 -Node: Installation11030 -Node: Installing from Melpa11360 -Node: Installing from the Git Repository12433 -Node: Post-Installation Tasks14788 -Node: Getting Started16073 -Node: Interface Concepts21420 -Node: Modes and Buffers21751 -Node: Switching Buffers23500 -Node: Naming Buffers28270 -Node: Quitting Windows31577 -Node: Automatic Refreshing of Magit Buffers33209 -Node: Automatic Saving of File-Visiting Buffers35977 -Node: Automatic Reverting of File-Visiting Buffers37162 -Node: Risk of Reverting Automatically42158 -Node: Sections44541 -Node: Section Movement45482 -Node: Section Visibility49579 -Node: Section Hooks55400 -Node: Section Types and Values57807 -Node: Section Options59110 -Node: Popup Buffers and Prefix Commands59582 -Node: Completion Confirmation and the Selection61963 -Node: Action Confirmation62400 -Node: Completion and Confirmation69746 -Node: The Selection72932 -Node: The hunk-internal region75831 -Node: Support for Completion Frameworks76920 -Node: Additional Completion Options81736 -Node: Running Git82335 -Node: Viewing Git Output82608 -Node: Git Process Status83741 -Node: Running Git Manually84706 -Node: Git Executable87108 -Node: Global Git Arguments89390 -Node: Inspecting90196 -Node: Status Buffer91343 -Node: Status Sections95333 -Node: Status Header Sections100136 -Node: Status Module Sections102766 -Node: Status Options105271 -Node: Repository List107025 -Node: Logging109183 -Node: Refreshing Logs111636 -Node: Log Buffer113021 -Node: Log Margin116816 -Node: Select from Log119456 -Node: Reflog121560 -Node: Cherries123092 -Node: Diffing124819 -Node: Refreshing Diffs127772 -Node: Diff Buffer131263 -Node: Diff Options135847 -Node: Revision Buffer140869 -Node: Ediffing143803 -Node: References Buffer147399 -Node: References Sections157163 -Node: Bisecting158024 -Node: Visiting Blobs159762 -Node: Blaming160272 -Node: Manipulating166083 -Node: Repository Setup166399 -Node: Staging and Unstaging167439 -Node: Staging from File-Visiting Buffers171520 -Node: Applying172688 -Node: Committing174581 -Node: Initiating a Commit175164 -Node: Editing Commit Messages178492 -Node: Branching188888 -Node: The Two Remotes189118 -Node: The Branch Popup191735 -Node: The Branch Config Popup203311 -Node: Auxiliary Branch Commands209252 -Node: Merging210357 -Node: Resolving Conflicts214288 -Node: Rebasing219289 -Node: Editing Rebase Sequences223453 -Node: Information About In-Progress Rebase226483 -Ref: Information About In-Progress Rebase-Footnote-1235232 -Node: Cherry Picking235828 -Node: Reverting240080 -Node: Resetting241454 -Node: Stashing243108 -Node: Transferring247631 -Node: Remotes247869 -Node: The Remote Popup248025 -Node: The Remote Config Popup251493 -Node: Fetching253149 -Node: Pulling254511 -Node: Pushing255354 -Node: Creating and Sending Patches260095 -Node: Applying Patches260932 -Node: Miscellaneous262518 -Node: Tagging262834 -Node: Notes264701 -Node: Submodules267012 -Node: Listing Submodules267226 -Node: Submodule Popup269150 -Node: Subtree271603 -Node: Worktree272843 -Node: Common Commands273806 -Node: Wip Modes275853 -Node: Wip Graph280786 -Node: Legacy Wip Modes283100 -Node: Minor Mode for Buffers Visiting Files285995 -Node: Minor Mode for Buffers Visiting Blobs291411 -Node: Customizing292224 -Node: Per-Repository Configuration293892 -Node: Essential Settings295541 -Node: Safety295865 -Node: Performance297630 -Node: Microsoft Windows Performance305233 -Node: MacOS Performance306424 -Ref: MacOS Performance-Footnote-1307660 -Ref: MacOS Performance-Footnote-2307742 -Ref: MacOS Performance-Footnote-3307802 -Node: Plumbing307968 -Node: Calling Git308791 -Node: Getting a Value from Git310316 -Node: Calling Git for Effect313402 -Node: Section Plumbing319922 -Node: Creating Sections320150 -Node: Section Selection324050 -Node: Matching Sections325849 -Node: Refreshing Buffers331822 -Node: Conventions334964 -Node: Theming Faces335156 -Node: FAQ343271 -Node: FAQ - How to ...?343713 -Node: How to show git's output?344073 -Node: How to install the gitman info manual?344827 -Node: How to show diffs for gpg-encrypted files?345797 -Node: How does branching and pushing work?346393 -Node: Can Magit be used as ediff-version-control-package?346756 -Node: FAQ - Issues and Errors348745 -Node: Magit is slow349677 -Node: I changed several thousand files at once and now Magit is unusable349891 -Node: I am having problems committing350620 -Node: I am using MS Windows and cannot push with Magit351101 -Node: I am using OS X and SOMETHING works in shell but not in Magit351718 -Node: Diffs contain control sequences352524 -Node: Expanding a file to show the diff causes it to disappear353637 -Node: Point is wrong in the COMMIT_EDITMSG buffer354188 -Node: The mode-line information isn't always up-to-date355234 -Node: A branch and tag sharing the same name breaks SOMETHING356316 -Node: My Git hooks work on the command-line but not inside Magit357204 -Node: git-commit-mode isn't used when committing from the command-line358041 -Node: Point ends up inside invisible text when jumping to a file-visiting buffer360308 -Node: Debugging Tools361106 -Node: Keystroke Index362993 -Node: Command Index394860 -Node: Function Index429514 -Node: Variable Index444822 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/magit-20190122.503/AUTHORS.md b/elpa/magit-20190514.1814/AUTHORS.md similarity index 96% rename from elpa/magit-20190122.503/AUTHORS.md rename to elpa/magit-20190514.1814/AUTHORS.md index 3bb6cc95..19187cf6 100644 --- a/elpa/magit-20190122.503/AUTHORS.md +++ b/elpa/magit-20190514.1814/AUTHORS.md @@ -50,6 +50,7 @@ Contributors - Alban Gruin - Aleksey Uimanov - Alexander Gramiak +- Alexander Miller - Alex Branham - Alex Dunn - Alexey Voinov @@ -106,9 +107,12 @@ Contributors - Daniel Hackney - Daniel Kraus - Daniel Mai +- Daniel Martín - Dan LaManna +- Danny Zhu - Dato Simó - David Abrahams +- David Ellison - David Ellison - David Hull - David L. Rager @@ -144,6 +148,7 @@ Contributors - Guillaume Martres - Hannu Koivisto - Hans-Peter Deifel +- Hussein Ait-Lahcen - Ian Eure - Ingo Lohmar - Ioan-Adrian Ratiu @@ -178,6 +183,7 @@ Contributors - Kevin Brubeck Unhammer - Kévin Le Gouguec - Kimberly Wolk +- Knut Olav Bøhmer - Kyle Meyer - Laurent Laffont - Laverne Schrock @@ -296,6 +302,7 @@ Contributors - Teruki Shigitani - Thierry Volpiatto - Thomas A Caswell +- Thomas Fini Hansen - Thomas Frössman - Thomas Jost - Thomas Riccardi @@ -305,8 +312,10 @@ Contributors - Tim Wraight - Ting-Yu Lin - Tom Feist +- Troy Hinckley - Tunc Uzlu - Vineet Naik +- Vitaly Ostashov - Vladimir Panteleev - Wei Huang - Wilfred Hughes @@ -319,3 +328,4 @@ Contributors - Yuichi Higashi - Yuri Khan - Zach Latta +- zakora diff --git a/elpa/magit-20190122.503/LICENSE b/elpa/magit-20190514.1814/LICENSE similarity index 100% rename from elpa/magit-20190122.503/LICENSE rename to elpa/magit-20190514.1814/LICENSE diff --git a/elpa/magit-20190122.503/dir b/elpa/magit-20190514.1814/dir similarity index 100% rename from elpa/magit-20190122.503/dir rename to elpa/magit-20190514.1814/dir diff --git a/elpa/magit-20190122.503/git-rebase.el b/elpa/magit-20190514.1814/git-rebase.el similarity index 62% rename from elpa/magit-20190122.503/git-rebase.el rename to elpa/magit-20190514.1814/git-rebase.el index daffbf9e..14bd9c42 100644 --- a/elpa/magit-20190122.503/git-rebase.el +++ b/elpa/magit-20190514.1814/git-rebase.el @@ -53,6 +53,7 @@ ;; e Edit the commit at point. ;; s Squash the commit at point, into the one above. ;; f Like "s" but don't also edit the commit message. +;; b Break for editing at this point in the sequence. ;; x Add a script to be run with the commit at point ;; being checked out. ;; z Add noop action at point. @@ -61,6 +62,13 @@ ;; RET Show the commit at point in another buffer and ;; select its window. ;; C-/ Undo last change. +;; +;; Commands for --rebase-merges: +;; l Associate label with current HEAD in sequence. +;; MM Merge specified revisions into HEAD. +;; Mt Toggle whether the merge will invoke an editor +;; before committing. +;; t Reset HEAD to the specified label. ;; You should probably also read the `git-rebase' manpage. @@ -113,13 +121,17 @@ "Face for commit hashes." :group 'git-rebase-faces) +(defface git-rebase-label '((t (:inherit magit-refname))) + "Face for labels in label, merge, and reset lines." + :group 'git-rebase-faces) + (defface git-rebase-description nil "Face for commit descriptions." :group 'git-rebase-faces) (defface git-rebase-killed-action '((t (:inherit font-lock-comment-face :strike-through t))) - "Face for commented action and exec lines." + "Face for commented commit action lines." :group 'git-rebase-faces) (defface git-rebase-comment-hash @@ -154,13 +166,18 @@ (define-key map (kbd "c") 'git-rebase-pick) (define-key map (kbd "k") 'git-rebase-kill-line) (define-key map (kbd "C-k") 'git-rebase-kill-line))) + (define-key map (kbd "b") 'git-rebase-break) (define-key map (kbd "e") 'git-rebase-edit) + (define-key map (kbd "l") 'git-rebase-label) + (define-key map (kbd "MM") 'git-rebase-merge) + (define-key map (kbd "Mt") 'git-rebase-merge-toggle-editmsg) (define-key map (kbd "m") 'git-rebase-edit) (define-key map (kbd "f") 'git-rebase-fixup) (define-key map (kbd "q") 'undefined) (define-key map (kbd "r") 'git-rebase-reword) (define-key map (kbd "w") 'git-rebase-reword) (define-key map (kbd "s") 'git-rebase-squash) + (define-key map (kbd "t") 'git-rebase-reset) (define-key map (kbd "x") 'git-rebase-exec) (define-key map (kbd "y") 'git-rebase-insert) (define-key map (kbd "z") 'git-rebase-noop) @@ -241,24 +258,102 @@ (interactive) (git-rebase-set-action "fixup")) -(defvar-local git-rebase-line nil) (defvar-local git-rebase-comment-re nil) +(defvar git-rebase-short-options + '((?b . "break") + (?e . "edit") + (?f . "fixup") + (?l . "label") + (?m . "merge") + (?p . "pick") + (?r . "reword") + (?s . "squash") + (?t . "reset") + (?x . "exec")) + "Alist mapping single key of an action to the full name.") + +(defclass git-rebase-action () + (;; action-type: commit, exec, bare, label, merge + (action-type :initarg :action-type :initform nil) + ;; Examples for each action type: + ;; | action | action options | target | trailer | + ;; |--------+----------------+---------+---------| + ;; | pick | | hash | subject | + ;; | exec | | command | | + ;; | noop | | | | + ;; | reset | | name | subject | + ;; | merge | -C hash | name | subject | + (action :initarg :action :initform nil) + (action-options :initarg :action-options :initform nil) + (target :initarg :target :initform nil) + (trailer :initarg :trailer :initform nil) + (comment-p :initarg :comment-p :initform nil))) + +(defvar git-rebase-line-regexps + `((commit . ,(concat + (regexp-opt '("e" "edit" + "f" "fixup" + "p" "pick" + "r" "reword" + "s" "squash") + "\\(?1:") + " \\(?3:[^ \n]+\\) \\(?4:.*\\)")) + (exec . "\\(?1:x\\|exec\\) \\(?3:.*\\)") + (bare . ,(concat (regexp-opt '("b" "break" "noop") "\\(?1:") + " *$")) + (label . ,(concat (regexp-opt '("l" "label" + "t" "reset") + "\\(?1:") + " \\(?3:[^ \n]+\\) ?\\(?4:.*\\)")) + (merge . ,(concat "\\(?1:m\\|merge\\) " + "\\(?:\\(?2:-[cC] [^ \n]+\\) \\)?" + "\\(?3:[^ \n]+\\)" + " ?\\(?4:.*\\)")))) + +;;;###autoload +(defun git-rebase-current-line () + "Parse current line into a `git-rebase-action' instance. +If the current line isn't recognized as a rebase line, an +instance with all nil values is returned." + (save-excursion + (goto-char (line-beginning-position)) + (if-let ((re-start (concat "^\\(?5:" (regexp-quote comment-start) + "\\)? *")) + (type (-some (lambda (arg) + (let ((case-fold-search nil)) + (and (looking-at (concat re-start (cdr arg))) + (car arg)))) + git-rebase-line-regexps))) + (git-rebase-action + :action-type type + :action (when-let ((action (match-string-no-properties 1))) + (or (cdr (assoc action git-rebase-short-options)) + action)) + :action-options (match-string-no-properties 2) + :target (match-string-no-properties 3) + :trailer (match-string-no-properties 4) + :comment-p (and (match-string 5) t)) + ;; Use default empty class rather than nil to ease handling. + (git-rebase-action)))) + (defun git-rebase-set-action (action) (goto-char (line-beginning-position)) - (if (and (looking-at git-rebase-line) - (not (string-match-p "\\(e\\|exec\\|noop\\)$" (match-string 1)))) - (let ((inhibit-read-only t)) - (replace-match action t t nil 1) - (when git-rebase-auto-advance - (forward-line))) - (ding))) + (with-slots (action-type target trailer) + (git-rebase-current-line) + (if (eq action-type 'commit) + (let ((inhibit-read-only t)) + (magit-delete-line) + (insert (concat action " " target " " trailer "\n")) + (unless git-rebase-auto-advance + (forward-line -1))) + (ding)))) (defun git-rebase-line-p (&optional pos) (save-excursion (when pos (goto-char pos)) - (goto-char (line-beginning-position)) - (looking-at-p git-rebase-line))) + (and (oref (git-rebase-current-line) action-type) + t))) (defun git-rebase-region-bounds () (when (use-region-p) @@ -285,10 +380,19 @@ current line." (save-restriction (narrow-to-region (point-min) - (1+ (save-excursion - (goto-char (point-min)) - (while (re-search-forward git-rebase-line nil t)) - (point)))) + (1- + (if git-rebase-show-instructions + (save-excursion + (goto-char (point-min)) + (while (or (git-rebase-line-p) + ;; The output for --rebase-merges has empty + ;; lines and "Branch" comments interspersed. + (looking-at-p "^$") + (looking-at-p (concat git-rebase-comment-re + " Branch"))) + (forward-line)) + (line-beginning-position)) + (point-max)))) (if (or (and (< n 0) (= beg (point-min))) (and (> n 0) (= end (point-max))) (> end (point-max))) @@ -333,11 +437,11 @@ current line." "Kill the current action line." (interactive) (goto-char (line-beginning-position)) - (when (and (looking-at git-rebase-line) - (not (eq (char-after) (string-to-char comment-start)))) + (unless (oref (git-rebase-current-line) comment-p) (let ((inhibit-read-only t)) (insert comment-start) (insert " ")) + (goto-char (line-beginning-position)) (when git-rebase-auto-advance (forward-line)))) @@ -350,35 +454,135 @@ current line." (insert "pick " it ?\n)) (user-error "Unknown revision"))) +(defun git-rebase-set-noncommit-action (action value-fn arg) + (goto-char (line-beginning-position)) + (pcase-let* ((inhibit-read-only t) + (`(,initial ,trailer ,comment-p) + (and (not arg) + (with-slots ((ln-action action) + target trailer comment-p) + (git-rebase-current-line) + (and (equal ln-action action) + (list target trailer comment-p))))) + (value (funcall value-fn initial))) + (pcase (list value initial comment-p) + (`("" nil ,_) + (ding)) + (`("" ,_ ,_) + (magit-delete-line)) + (_ + (if initial + (magit-delete-line) + (forward-line)) + (insert (concat action " " value + (and (equal value initial) + trailer + (concat " " trailer)) + "\n")) + (unless git-rebase-auto-advance + (forward-line -1)))))) + (defun git-rebase-exec (arg) - "Insert a shell command to be run after the proceeding commit. + "Insert a shell command to be run after the current commit. If there already is such a command on the current line, then edit that instead. With a prefix argument insert a new command even when there already is one on the current line. With empty input remove the command on the current line, if any." (interactive "P") - (let ((inhibit-read-only t) initial command) - (unless arg - (goto-char (line-beginning-position)) - (when (looking-at (concat git-rebase-comment-re "?" - "\\(e\\|exec\\) \\(.*\\)")) - (setq initial (match-string-no-properties 2)))) - (setq command (read-shell-command "Execute: " initial)) - (pcase (list command initial) - (`("" nil) (ding)) - (`("" ,_) - (delete-region (match-beginning 0) (1+ (match-end 0)))) - (`(,_ nil) - (forward-line) - (insert (concat "exec " command "\n")) - (unless git-rebase-auto-advance - (forward-line -1))) - (_ - (replace-match (concat "exec " command) t t) - (if git-rebase-auto-advance - (forward-line) - (goto-char (line-beginning-position))))))) + (git-rebase-set-noncommit-action + "exec" + (lambda (initial) (read-shell-command "Execute: " initial)) + arg)) + +(defun git-rebase-label (arg) + "Add a label after the current commit. +If there already is a label on the current line, then edit that +instead. With a prefix argument, insert a new label even when +there is already a label on the current line. With empty input, +remove the label on the current line, if any." + (interactive "P") + (git-rebase-set-noncommit-action + "label" + (lambda (initial) + (read-from-minibuffer + "Label: " initial magit-minibuffer-local-ns-map)) + arg)) + +(defun git-rebase-buffer-labels () + (let (labels) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^\\(?:l\\|label\\) \\([^ \n]+\\)" nil t) + (push (match-string-no-properties 1) labels))) + (nreverse labels))) + +(defun git-rebase-reset (arg) + "Reset the current HEAD to a label. +If there already is a reset command on the current line, then +edit that instead. With a prefix argument, insert a new reset +line even when point is already on a reset line. With empty +input, remove the reset command on the current line, if any." + (interactive "P") + (git-rebase-set-noncommit-action + "reset" + (lambda (initial) + (or (magit-completing-read "Label" (git-rebase-buffer-labels) + nil t initial) + "")) + arg)) + +(defun git-rebase-merge (arg) + "Add a merge command after the current commit. +If there is already a merge command on the current line, then +replace that command instead. With a prefix argument, insert a +new merge command even when there is already one on the current +line. With empty input, remove the merge command on the current +line, if any." + (interactive "P") + (git-rebase-set-noncommit-action + "merge" + (lambda (_) + (or (magit-completing-read "Merge" (git-rebase-buffer-labels)) + "")) + arg)) + +(defun git-rebase-merge-toggle-editmsg () + "Toggle whether an editor is invoked when performing the merge at point. +When a merge command uses a lower-case -c, the message for the +specified commit will be opened in an editor before creating the +commit. For an upper-case -C, the message will be used as is." + (interactive) + (with-slots (action-type target action-options trailer) + (git-rebase-current-line) + (if (eq action-type 'merge) + (let ((inhibit-read-only t)) + (magit-delete-line) + (insert + (format "merge %s %s %s\n" + (replace-regexp-in-string + "-[cC]" (lambda (c) + (if (equal c "-c") "-C" "-c")) + action-options t t) + target + trailer))) + (ding)))) + +(defun git-rebase-set-bare-action (action arg) + (goto-char (line-beginning-position)) + (with-slots ((ln-action action) comment-p) + (git-rebase-current-line) + (let ((same-action-p (equal action ln-action)) + (inhibit-read-only t)) + (when (or arg + (not ln-action) + (not same-action-p) + (and same-action-p comment-p)) + (unless (or arg (not same-action-p)) + (magit-delete-line)) + (insert action ?\n) + (unless git-rebase-auto-advance + (forward-line -1)))))) (defun git-rebase-noop (&optional arg) "Add noop action at point. @@ -386,24 +590,28 @@ remove the command on the current line, if any." If the current line already contains a noop action, leave it unchanged. If there is a commented noop action present, remove the comment. Otherwise add a new noop action. With a prefix -argument insert a new noop action regardless what is already +argument insert a new noop action regardless of what is already present on the current line. A noop action can be used to make git perform a rebase even if no commits are selected. Without the noop action present, git would see an empty file and therefore do nothing." (interactive "P") - (goto-char (line-beginning-position)) - ;; The extra space at the end is only there to make the action - ;; consistent with the others (action argument). This keeps - ;; the regexp `git-rebase-line' from getting complicated. - (let ((noop-string "noop \n")) - (when (or arg (not (looking-at noop-string))) - (let ((inhibit-read-only t)) - (if (and (not arg) - (looking-at (concat comment-start noop-string))) - (delete-char 1) - (insert noop-string)))))) + (git-rebase-set-bare-action "noop" arg)) + +(defun git-rebase-break (&optional arg) + "Add break action at point. + +If there is a commented break action present, remove the comment. +If the current line already contains a break action, add another +break action only if a prefix argument is given. + +A break action can be used to interrupt the rebase at the +specified point. It is particularly useful for pausing before +the first commit in the sequence. For other cases, the +equivalent behavior can be achieved with `git-rebase-edit'." + (interactive "P") + (git-rebase-set-bare-action "break" arg)) (defun git-rebase-undo (&optional arg) "Undo some previous changes. @@ -416,12 +624,14 @@ Like `undo' but works in read-only buffers." (let ((disable-magit-save-buffers t)) (save-excursion (goto-char (line-beginning-position)) - (--if-let (and (looking-at git-rebase-line) - (match-string 2)) + (--if-let (with-slots (action-type target) (git-rebase-current-line) + (and (eq action-type 'commit) + target)) (pcase scroll (`up (magit-diff-show-or-scroll-up)) (`down (magit-diff-show-or-scroll-down)) - (_ (apply #'magit-show-commit it (magit-diff-arguments)))) + (_ (apply #'magit-show-commit it + (magit-diff-arguments 'magit-revision-mode)))) (ding))))) (defun git-rebase-show-commit () @@ -468,10 +678,6 @@ running 'man git-rebase' at the command line) for details." :group 'git-rebase (setq comment-start (or (magit-get "core.commentChar") "#")) (setq git-rebase-comment-re (concat "^" (regexp-quote comment-start))) - (setq git-rebase-line - (concat "^\\(" (regexp-quote comment-start) "? *" - "\\(?:[fprse]\\|pick\\|reword\\|edit\\|squash\\|fixup\\|exec\\|noop\\)\\) " - "\\(?:\\([^ \n]+\\) \\(.*\\)\\)?")) (setq font-lock-defaults (list (git-rebase-mode-font-lock-keywords) t t)) (unless git-rebase-show-instructions (let ((inhibit-read-only t)) @@ -511,27 +717,40 @@ running 'man git-rebase' at the command line) for details." (defun git-rebase-mode-font-lock-keywords () "Font lock keywords for Git-Rebase mode." - (let ((action-re "\ -\\([efprs]\\|pick\\|reword\\|edit\\|squash\\|fixup\\) \\([^ \n]+\\) \\(.*\\)")) - `((,(concat "^" action-re) - (1 'font-lock-keyword-face) - (2 'git-rebase-hash) - (3 'git-rebase-description)) - ("^\\(exec\\) \\(.*\\)" - (1 'font-lock-keyword-face) - (2 'git-rebase-description)) - ("^\\(noop\\)" - (1 'font-lock-keyword-face)) - (git-rebase-match-comment-line 0 'font-lock-comment-face) - (,(concat git-rebase-comment-re " *" action-re) - 0 'git-rebase-killed-action t) - ("\\[[^[]*\\]" - 0 'magit-keyword t) - (,(format "^%s Rebase \\([^ ]*\\) onto \\([^ ]*\\)" comment-start) - (1 'git-rebase-comment-hash t) - (2 'git-rebase-comment-hash t)) - (,(format "^%s \\(Commands:\\)" comment-start) - (1 'git-rebase-comment-heading t))))) + `((,(concat "^" (cdr (assq 'commit git-rebase-line-regexps))) + (1 'font-lock-keyword-face) + (3 'git-rebase-hash) + (4 'git-rebase-description)) + (,(concat "^" (cdr (assq 'exec git-rebase-line-regexps))) + (1 'font-lock-keyword-face) + (3 'git-rebase-description)) + (,(concat "^" (cdr (assq 'bare git-rebase-line-regexps))) + (1 'font-lock-keyword-face)) + (,(concat "^" (cdr (assq 'label git-rebase-line-regexps))) + (1 'font-lock-keyword-face) + (3 'git-rebase-label) + (4 'font-lock-comment-face)) + ("^\\(m\\(?:erge\\)?\\) -[Cc] \\([^ \n]+\\) \\([^ \n]+\\)\\( #.*\\)?" + (1 'font-lock-keyword-face) + (2 'git-rebase-hash) + (3 'git-rebase-label) + (4 'font-lock-comment-face)) + ("^\\(m\\(?:erge\\)?\\) \\([^ \n]+\\)" + (1 'font-lock-keyword-face) + (2 'git-rebase-label)) + (,(concat git-rebase-comment-re " *" + (cdr (assq 'commit git-rebase-line-regexps))) + 0 'git-rebase-killed-action t) + (git-rebase-match-comment-line 0 'font-lock-comment-face) + ("\\[[^[]*\\]" + 0 'magit-keyword t) + (,(format "^%s Rebase \\([^ ]*\\) onto \\([^ ]*\\)" comment-start) + (1 'git-rebase-comment-hash t) + (2 'git-rebase-comment-hash t)) + (,(format "^%s \\(Commands:\\)" comment-start) + (1 'git-rebase-comment-heading t)) + (,(format "^%s Branch \\(.*\\)" comment-start) + (1 'git-rebase-label t)))) (defun git-rebase-mode-show-keybindings () "Modify the \"Commands:\" section of the comment Git generates @@ -563,7 +782,8 @@ By default, this is the same except for the \"pick\" command." (format "%-8s" (mapconcat #'key-description (--remove (eq (elt it 0) 'menu-bar) - (reverse (where-is-internal cmd))) + (reverse (where-is-internal + cmd git-rebase-mode-map))) ", ")) t t nil 2)))))))) diff --git a/elpa/magit-20190122.503/magit-apply.el b/elpa/magit-20190514.1814/magit-apply.el similarity index 93% rename from elpa/magit-20190122.503/magit-apply.el rename to elpa/magit-20190514.1814/magit-apply.el index 8b7142f7..c1ba69a9 100644 --- a/elpa/magit-20190122.503/magit-apply.el +++ b/elpa/magit-20190514.1814/magit-apply.el @@ -37,15 +37,17 @@ (require 'magit-diff) (require 'magit-wip) +(require 'transient) ; See #3732. + ;; For `magit-apply' -(declare-function magit-am-popup "magit-sequence" (&optional arg)) -(declare-function magit-patch-apply-popup "magit-files" (&optional arg)) +(declare-function magit-am "magit-sequence" ()) +(declare-function magit-patch-apply "magit-files" ()) ;; For `magit-discard-files' (declare-function magit-checkout-stage "magit-merge" (file arg)) (declare-function magit-checkout-read-stage "magit-merge" (file)) (defvar auto-revert-verbose) ;; For `magit-stage-untracked' -(declare-function magit-submodule-add "magit-submodule" +(declare-function magit-submodule-add-1 "magit-submodule" (url &optional path name args)) (declare-function magit-submodule-read-name-for-path "magit-submodule" (path &optional prefer-short)) @@ -129,11 +131,12 @@ so causes the change to be applied to the index as well." (`(,(or `unstaged `staged) ,_) (user-error "Change is already in the working tree")) (`(untracked ,(or `file `files)) - (magit-am-popup)) + (call-interactively 'magit-am)) (`(,_ region) (magit-apply-region it args)) (`(,_ hunk) (magit-apply-hunk it args)) (`(,_ hunks) (magit-apply-hunks it args)) - (`(rebase-sequence file) (magit-patch-apply-popup)) + (`(rebase-sequence file) + (call-interactively 'magit-patch-apply)) (`(,_ file) (magit-apply-diff it args)) (`(,_ files) (magit-apply-diffs it args))))) @@ -228,9 +231,7 @@ so causes the change to be applied to the index as well." (t sections))) (defun magit-apply--diff-ignores-whitespace-p () - (and (cl-intersection (if (derived-mode-p 'magit-diff-mode) - (nth 2 magit-refresh-args) - magit-diff-section-arguments) + (and (cl-intersection magit-buffer-diff-args '("--ignore-space-at-eol" "--ignore-space-change" "--ignore-all-space" @@ -294,7 +295,7 @@ ignored) files." (when (magit-anything-staged-p) (magit-confirm 'stage-all-changes)) (magit-with-toplevel - (magit-stage-1 (if all "--all" "-u")))) + (magit-stage-1 (if all "--all" "-u") magit-buffer-diff-files))) (defun magit-stage-1 (arg &optional files) (magit-wip-commit-before-change files " before stage") @@ -331,7 +332,7 @@ ignored) files." (and (equal (bound-and-true-p borg-user-emacs-directory) topdir) (file-name-nondirectory (directory-file-name repo))))) - (magit-submodule-add + (magit-submodule-add-1 (let ((default-directory (file-name-as-directory (expand-file-name repo)))) (or (magit-get "remote" (magit-get-some-remote) "url") @@ -361,6 +362,8 @@ ignored) files." (magit-diff-scope) (magit-apply--diff-ignores-whitespace-p)) (`(untracked ,_ ,_) (user-error "Cannot unstage untracked changes")) + (`(unstaged file ,_) (magit-unstage-intent (list (oref it value)))) + (`(unstaged files ,_) (magit-unstage-intent (magit-region-values nil t))) (`(unstaged ,_ ,_) (user-error "Already unstaged")) (`(staged region ,_) (magit-apply-region it "--reverse" "--cached")) (`(staged hunk ,_) (magit-apply-hunk it "--reverse" "--cached")) @@ -401,6 +404,12 @@ without requiring confirmation." (magit-run-git "reset" "HEAD" "--" files)) (magit-wip-commit-after-apply files " after unstage")) +(defun magit-unstage-intent (files) + (if-let ((staged (magit-staged-files)) + (intent (--filter (member it staged) files))) + (magit-unstage-1 intent) + (user-error "Already unstaged"))) + ;;;###autoload (defun magit-unstage-all () "Remove all changes from the staging area." @@ -409,7 +418,7 @@ without requiring confirmation." (magit-untracked-files)) (magit-confirm 'unstage-all-changes)) (magit-wip-commit-before-change nil " before unstage") - (magit-run-git "reset" "HEAD" "--") + (magit-run-git "reset" "HEAD" "--" magit-buffer-diff-files) (magit-wip-commit-after-apply nil " after unstage")) ;;;; Discard @@ -546,23 +555,25 @@ without requiring confirmation." files) (let ((delete-by-moving-to-trash magit-delete-by-moving-to-trash)) (dolist (file files) - (if (memq (magit-diff-type) '(unstaged untracked)) - (progn (dired-delete-file file dired-recursive-deletes - magit-delete-by-moving-to-trash) - (dired-clean-up-after-deletion file)) - (pcase (nth 3 (assoc file status)) - (? (delete-file file t) - (magit-call-git "rm" "--cached" "--" file)) - (?M (let ((temp (magit-git-string "checkout-index" "--temp" file))) - (string-match - (format "\\(.+?\\)\t%s" (regexp-quote file)) temp) - (rename-file (match-string 1 temp) - (setq temp (concat file ".~{index}~"))) - (delete-file temp t)) - (magit-call-git "rm" "--cached" "--force" "--" file)) - (?D (magit-call-git "checkout" "--" file) - (delete-file file t) - (magit-call-git "rm" "--cached" "--force" "--" file))))))) + (when (string-match-p "\\`\\\\?~" file) + (error "Refusing to delete %S, too dangerous" file)) + (pcase (nth 3 (assoc file status)) + ((guard (memq (magit-diff-type) '(unstaged untracked))) + (dired-delete-file file dired-recursive-deletes + magit-delete-by-moving-to-trash) + (dired-clean-up-after-deletion file)) + (?\s (delete-file file t) + (magit-call-git "rm" "--cached" "--" file)) + (?M (let ((temp (magit-git-string "checkout-index" "--temp" file))) + (string-match + (format "\\(.+?\\)\t%s" (regexp-quote file)) temp) + (rename-file (match-string 1 temp) + (setq temp (concat file ".~{index}~"))) + (delete-file temp t)) + (magit-call-git "rm" "--cached" "--force" "--" file)) + (?D (magit-call-git "checkout" "--" file) + (delete-file file t) + (magit-call-git "rm" "--cached" "--force" "--" file)))))) (defun magit-discard-files--rename (files status) (magit-confirm 'rename "Undo rename %s" "Undo %i renames" nil @@ -649,10 +660,9 @@ so causes the change to be applied to the index as well." (pcase-let ((`(,binaries ,sections) (let ((bs (magit-binary-files (cond ((derived-mode-p 'magit-revision-mode) - (let ((rev (car magit-refresh-args))) - (format "%s^..%s" rev rev))) + magit-buffer-range) ((derived-mode-p 'magit-diff-mode) - (car magit-refresh-args)) + magit-buffer-range) (t "--cached"))))) (--separate (member (oref it value) bs) diff --git a/elpa/magit-20190122.503/magit-autoloads.el b/elpa/magit-20190514.1814/magit-autoloads.el similarity index 81% rename from elpa/magit-20190122.503/magit-autoloads.el rename to elpa/magit-20190514.1814/magit-autoloads.el index fee5a2ee..cffcb18d 100644 --- a/elpa/magit-20190122.503/magit-autoloads.el +++ b/elpa/magit-20190514.1814/magit-autoloads.el @@ -9,6 +9,13 @@ ;;;### (autoloads nil "git-rebase" "git-rebase.el" (0 0 0 0)) ;;; Generated autoloads from git-rebase.el +(autoload 'git-rebase-current-line "git-rebase" "\ +Parse current line into a `git-rebase-action' instance. +If the current line isn't recognized as a rebase line, an +instance with all nil values is returned. + +\(fn)" nil nil) + (autoload 'git-rebase-mode "git-rebase" "\ Major mode for editing of a Git rebase file. @@ -29,8 +36,8 @@ running 'man git-rebase' at the command line) for details. ;;;### (autoloads nil "magit" "magit.el" (0 0 0 0)) ;;; Generated autoloads from magit.el - (autoload 'magit-dispatch-popup "magit" nil t) - (autoload 'magit-run-popup "magit" nil t) + (autoload 'magit-dispatch "magit" nil t) + (autoload 'magit-run "magit" nil t) (autoload 'magit-git-command "magit" "\ Execute COMMAND asynchronously; display output. @@ -125,7 +132,7 @@ Remove all changes from the staging area. ;;;;;; 0 0 0)) ;;; Generated autoloads from magit-autorevert.el -(defvar magit-auto-revert-mode (and (not global-auto-revert-mode) (not noninteractive)) "\ +(defvar magit-auto-revert-mode (not (or global-auto-revert-mode noninteractive)) "\ Non-nil if Magit-Auto-Revert mode is enabled. See the `magit-auto-revert-mode' command for a description of this minor mode. @@ -153,7 +160,7 @@ See `auto-revert-mode' for more information on Auto-Revert mode. ;;;### (autoloads nil "magit-bisect" "magit-bisect.el" (0 0 0 0)) ;;; Generated autoloads from magit-bisect.el - (autoload 'magit-bisect-popup "magit-bisect" nil t) + (autoload 'magit-bisect "magit-bisect" nil t) (autoload 'magit-bisect-start "magit-bisect" "\ Start a bisect session. @@ -161,7 +168,7 @@ Start a bisect session. Bisecting a bug means to find the commit that introduced it. This command starts such a bisect session by asking for a know good and a bad commit. To move the session forward use the -other actions from the bisect popup (\\\\[magit-bisect-popup]). +other actions from the bisect transient command (\\\\[magit-bisect]). \(fn BAD GOOD)" t nil) @@ -206,30 +213,11 @@ bisect run'. ;;;### (autoloads nil "magit-blame" "magit-blame.el" (0 0 0 0)) ;;; Generated autoloads from magit-blame.el - -(autoload 'magit-blame-echo "magit-blame" "\ -For each line show the revision in which it was added. -Show the information about the chunk at point in the echo area -when moving between chunks. Unlike other blaming commands, do -not turn on `read-only-mode'. - -\(fn)" t nil) - -(autoload 'magit-blame-addition "magit-blame" "\ -For each line show the revision in which it was added. - -\(fn)" t nil) - -(autoload 'magit-blame-removal "magit-blame" "\ -For each line show the revision in which it was removed. - -\(fn)" t nil) - -(autoload 'magit-blame-reverse "magit-blame" "\ -For each line show the last revision in which it still exists. - -\(fn)" t nil) - (autoload 'magit-blame-popup "magit-blame" nil t) + (autoload 'magit-blame-echo "magit-blame" nil t) + (autoload 'magit-blame-addition "magit-blame" nil t) + (autoload 'magit-blame-removal "magit-blame" nil t) + (autoload 'magit-blame-reverse "magit-blame" nil t) + (autoload 'magit-blame "magit-blame" nil t) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-blame" '("magit-"))) @@ -239,113 +227,13 @@ For each line show the last revision in which it still exists. ;;;;;; 0)) ;;; Generated autoloads from magit-bookmark.el -(autoload 'magit-bookmark--status-jump "magit-bookmark" "\ -Handle a Magit status BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--status-make-record "magit-bookmark" "\ -Create a Magit status bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--refs-jump "magit-bookmark" "\ -Handle a Magit refs BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--refs-make-record "magit-bookmark" "\ -Create a Magit refs bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--log-jump "magit-bookmark" "\ -Handle a Magit log BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--log-make-record "magit-bookmark" "\ -Create a Magit log bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--reflog-jump "magit-bookmark" "\ -Handle a Magit reflog BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--reflog-make-record "magit-bookmark" "\ -Create a Magit reflog bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--stashes-jump "magit-bookmark" "\ -Handle a Magit stash list BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--stashes-make-record "magit-bookmark" "\ -Create a Magit stash list bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--cherry-jump "magit-bookmark" "\ -Handle a Magit cherry BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--cherry-make-record "magit-bookmark" "\ -Create a Magit cherry bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--diff-jump "magit-bookmark" "\ -Handle a Magit diff BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--diff-make-record "magit-bookmark" "\ -Create a Magit diff bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--revision-jump "magit-bookmark" "\ -Handle a Magit revision BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--revision-make-record "magit-bookmark" "\ -Create a Magit revision bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--stash-jump "magit-bookmark" "\ -Handle a Magit stash BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--stash-make-record "magit-bookmark" "\ -Create a Magit stash bookmark. - -\(fn)" nil nil) - -(autoload 'magit-bookmark--submodules-jump "magit-bookmark" "\ -Handle a Magit submodule list BOOKMARK. - -\(fn BOOKMARK)" nil nil) - -(autoload 'magit-bookmark--submodules-make-record "magit-bookmark" "\ -Create a Magit submodule list bookmark. - -\(fn)" nil nil) - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-bookmark" '("magit-bookmark--"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-bookmark" '("magit--"))) ;;;*** ;;;### (autoloads nil "magit-branch" "magit-branch.el" (0 0 0 0)) ;;; Generated autoloads from magit-branch.el - (autoload 'magit-branch-popup "magit" nil t) + (autoload 'magit-branch "magit" nil t) (autoload 'magit-checkout "magit-branch" "\ Checkout REVISION, updating the index and the working tree. @@ -361,16 +249,12 @@ changes. (autoload 'magit-branch-create "magit-branch" "\ Create BRANCH at branch or revision START-POINT. -\(git branch [ARGS] BRANCH START-POINT). - -\(fn BRANCH START-POINT &optional ARGS)" t nil) +\(fn BRANCH START-POINT)" t nil) (autoload 'magit-branch-and-checkout "magit-branch" "\ Create and checkout BRANCH at branch or revision START-POINT. -\(git checkout [ARGS] -b BRANCH START-POINT). - -\(fn BRANCH START-POINT &optional ARGS)" t nil) +\(fn BRANCH START-POINT)" t nil) (autoload 'magit-branch-or-checkout "magit-branch" "\ Hybrid between `magit-checkout' and `magit-branch-and-checkout'. @@ -415,9 +299,15 @@ when using `magit-branch-and-checkout'. (autoload 'magit-branch-orphan "magit-branch" "\ Create and checkout an orphan BRANCH with contents from revision START-POINT. -\(git checkout --orphan [ARGS] BRANCH START-POINT). +\(fn BRANCH START-POINT)" t nil) -\(fn BRANCH START-POINT &optional ARGS)" t nil) +(autoload 'magit-branch-spinout "magit-branch" "\ +Create new branch from the unpushed commits. +Like `magit-branch-spinoff' but remain on the current branch. +If there are any uncommitted changes, then behave exactly like +`magit-branch-spinoff'. + +\(fn BRANCH &optional FROM)" t nil) (autoload 'magit-branch-spinoff "magit-branch" "\ Create new branch from the unpushed commits. @@ -449,7 +339,7 @@ matter, all commits between FROM and `HEAD' are moved to the new branch. If FROM is not reachable from `HEAD' or is reachable from the source branch's upstream, then an error is raised. -\(fn BRANCH &optional FROM &rest ARGS)" t nil) +\(fn BRANCH &optional FROM)" t nil) (autoload 'magit-branch-reset "magit-branch" "\ Reset a branch to the tip of another branch or any other commit. @@ -465,7 +355,7 @@ When resetting to another branch and a prefix argument is used, then also set the target branch as the upstream of the branch that is being reset. -\(fn BRANCH TO &optional ARGS SET-UPSTREAM)" t nil) +\(fn BRANCH TO &optional SET-UPSTREAM)" t nil) (autoload 'magit-branch-delete "magit-branch" "\ Delete one or multiple branches. @@ -501,151 +391,65 @@ Rename \"refs/shelved/BRANCH\" to \"refs/heads/BRANCH\", and also rename the respective reflog file. \(fn BRANCH)" t nil) + (autoload 'magit-branch-configure "magit-branch" nil t) -(autoload 'magit-branch-config-popup "magit-branch" "\ -Popup console for setting branch variables. - -\(fn BRANCH)" t nil) - -(autoload 'magit-edit-branch*description "magit-branch" "\ -Edit the description of the current branch. -With a prefix argument edit the description of another branch. - -The description for the branch named NAME is stored in the Git -variable `branch..description'. - -\(fn BRANCH)" t nil) - -(autoload 'magit-set-branch*merge/remote "magit-branch" "\ -Set or unset the upstream of the current branch. -With a prefix argument do so for another branch. - -When the branch in question already has an upstream then simply -unsets it. Invoke this command again to set another upstream. - -Together the Git variables `branch..remote' and -`branch..merge' define the upstream branch of the local -branch named NAME. The value of `branch..remote' is the -name of the upstream remote. The value of `branch..merge' -is the full reference of the upstream branch, on the remote. - -Non-interactively, when UPSTREAM is non-nil, then always set it -as the new upstream, regardless of whether another upstream was -already set. When nil, then always unset. - -\(fn BRANCH UPSTREAM)" t nil) - -(autoload 'magit-cycle-branch*rebase "magit-branch" "\ -Cycle the value of `branch..rebase' for the current branch. -With a prefix argument cycle the value for another branch. - -The Git variables `branch..rebase' controls whether pulling -into the branch named NAME is done by rebasing that branch onto -the fetched branch or by merging that branch. - -When `true' then pulling is done by rebasing. -When `false' then pulling is done by merging. - -When that variable is undefined then the value of `pull.rebase' -is used instead. It defaults to `false'. - -\(fn BRANCH)" t nil) - -(autoload 'magit-cycle-branch*pushRemote "magit-branch" "\ -Cycle the value of `branch..pushRemote' for the current branch. -With a prefix argument cycle the value for another branch. - -The Git variable `branch..pushRemote' specifies the remote -that the branch named NAME is usually pushed to. The value has -to be the name of an existing remote. - -If that variable is undefined, then the value of the Git variable -`remote.pushDefault' is used instead, provided that it is defined, -which by default it is not. - -\(fn BRANCH)" t nil) - -(autoload 'magit-cycle-pull\.rebase "magit-branch" "\ -Cycle the repository-local value of `pull.rebase'. - -The Git variable `pull.rebase' specifies whether pulling is done -by rebasing or by merging. It can be overwritten using the Git -variable `branch..rebase'. - -When `true' then pulling is done by rebasing. -When `false' (the default) then pulling is done by merging. - -\(fn)" t nil) - -(autoload 'magit-cycle-remote\.pushDefault "magit-branch" "\ -Cycle the repository-local value of `remote.pushDefault'. - -The Git variable `remote.pushDefault' specifies the remote that -local branches are usually pushed to. It can be overwritten -using the Git variable `branch..pushRemote'. - -\(fn)" t nil) - -(autoload 'magit-cycle-branch*autoSetupMerge "magit-branch" "\ -Cycle the repository-local value of `branch.autoSetupMerge'. - -The Git variable `branch.autoSetupMerge' under what circumstances -creating a branch (named NAME) should result in the variables -`branch..merge' and `branch..remote' being set -according to the starting point used to create the branch. If -the starting point isn't a branch, then these variables are never -set. - -When `always' then the variables are set regardless of whether -the starting point is a local or a remote branch. +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-branch" '("magit-"))) -When `true' (the default) then the variable are set when the -starting point is a remote branch, but not when it is a local -branch. +;;;*** + +;;;### (autoloads nil "magit-clone" "magit-clone.el" (0 0 0 0)) +;;; Generated autoloads from magit-clone.el + (autoload 'magit-clone "magit-clone" nil t) -When `false' then the variables are never set. +(autoload 'magit-clone-regular "magit-clone" "\ +Create a clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. -\(fn)" t nil) +\(fn REPOSITORY DIRECTORY ARGS)" t nil) -(autoload 'magit-cycle-branch*autoSetupRebase "magit-branch" "\ -Cycle the repository-local value of `branch.autoSetupRebase'. +(autoload 'magit-clone-shallow "magit-clone" "\ +Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +With a prefix argument read the DEPTH of the clone; +otherwise use 1. -The Git variable `branch.autoSetupRebase' specifies whether -creating a branch (named NAME) should result in the variable -`branch..rebase' being set to `true'. +\(fn REPOSITORY DIRECTORY ARGS DEPTH)" t nil) -When `always' then the variable is set regardless of whether the -starting point is a local or a remote branch. +(autoload 'magit-clone-shallow-since "magit-clone" "\ +Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +Exclude commits before DATE, which is read from the +user. -When `local' then the variable are set when the starting point -is a local branch, but not when it is a remote branch. +\(fn REPOSITORY DIRECTORY ARGS DATE)" t nil) -When `remote' then the variable are set when the starting point -is a remote branch, but not when it is a local branch. +(autoload 'magit-clone-shallow-exclude "magit-clone" "\ +Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +Exclude commits reachable from EXCLUDE, which is a +branch or tag read from the user. -When `never' (the default) then the variable is never set. +\(fn REPOSITORY DIRECTORY ARGS EXCLUDE)" t nil) -\(fn)" t nil) +(autoload 'magit-clone-bare "magit-clone" "\ +Create a bare clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-branch" '("magit-"))) +\(fn REPOSITORY DIRECTORY ARGS)" t nil) -;;;*** - -;;;### (autoloads nil "magit-clone" "magit-clone.el" (0 0 0 0)) -;;; Generated autoloads from magit-clone.el - -(autoload 'magit-clone "magit-clone" "\ -Clone the REPOSITORY to DIRECTORY. +(autoload 'magit-clone-mirror "magit-clone" "\ +Create a mirror of REPOSITORY in DIRECTORY. Then show the status buffer for the new repository. -\(fn REPOSITORY DIRECTORY)" t nil) +\(fn REPOSITORY DIRECTORY ARGS)" t nil) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-clone" '("magit-clone-"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-clone" '("magit-clone"))) ;;;*** ;;;### (autoloads nil "magit-commit" "magit-commit.el" (0 0 0 0)) ;;; Generated autoloads from magit-commit.el + (autoload 'magit-commit "magit-commit" nil t) (autoload 'magit-commit-create "magit-commit" "\ Create a new commit on `HEAD'. @@ -734,28 +538,16 @@ that is you) or committer date is available as the previous history element. \(fn DATE)" t nil) - (autoload 'magit-commit-absorb-popup "magit-commit" nil t) + (autoload 'magit-commit-absorb "magit-commit" nil t) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-commit" '("magit-"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-commit" '("magit"))) ;;;*** ;;;### (autoloads nil "magit-diff" "magit-diff.el" (0 0 0 0)) ;;; Generated autoloads from magit-diff.el - -(autoload 'magit-diff-popup "magit-diff" "\ -Popup console for diff commands. - -\(fn ARG)" t nil) - -(autoload 'magit-diff-buffer-file-popup "magit-diff" "\ -Popup console for diff commands. - -This is a variant of `magit-diff-popup' which shows the same popup -but which limits the diff to the file being visited in the current -buffer. - -\(fn)" t nil) + (autoload 'magit-diff "magit-diff" nil t) + (autoload 'magit-diff-refresh "magit-diff" nil t) (autoload 'magit-diff-dwim "magit-diff" "\ Show changes for the thing at point. @@ -813,6 +605,11 @@ be committed. (autoload 'magit-diff-buffer-file "magit-diff" "\ Show diff for the blob or file visited in the current buffer. +When the buffer visits a blob, then show the respective commit. +When the buffer visits a file, then show the differenced between +`HEAD' and the working tree. In both cases limit the diff to +the file or blob. + \(fn)" t nil) (autoload 'magit-diff-paths "magit-diff" "\ @@ -827,13 +624,13 @@ for a revision. \(fn REV &optional ARGS FILES MODULE)" t nil) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-diff" '("magit-"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-diff" '("magit"))) ;;;*** ;;;### (autoloads nil "magit-ediff" "magit-ediff.el" (0 0 0 0)) ;;; Generated autoloads from magit-ediff.el - (autoload 'magit-ediff-popup "magit-ediff" nil t) + (autoload 'magit-ediff "magit-ediff" nil) (autoload 'magit-ediff-resolve "magit-ediff" "\ Resolve outstanding conflicts in FILE using Ediff. @@ -917,7 +714,7 @@ stash that were staged. \(fn STASH)" t nil) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-ediff" '("magit-ediff-"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-ediff" '("magit-ediff"))) ;;;*** @@ -1078,7 +875,7 @@ Neither the blob nor the file buffer are killed when finishing the rebase. If that is undesirable, then it might be better to use `magit-rebase-edit-command' instead of this command. -\(fn)" t nil) +\(fn FILE)" t nil) (autoload 'magit-reshelve-since "magit-extras" "\ Change the author and committer dates of the commits since REV. @@ -1176,17 +973,9 @@ patch application, a cherry-pick, a revert, or a bisect. ;;;### (autoloads nil "magit-fetch" "magit-fetch.el" (0 0 0 0)) ;;; Generated autoloads from magit-fetch.el - (autoload 'magit-fetch-popup "magit-fetch" nil t) - -(autoload 'magit-fetch-from-pushremote "magit-fetch" "\ -Fetch from the push-remote of the current branch. - -\(fn ARGS)" t nil) - -(autoload 'magit-fetch-from-upstream "magit-fetch" "\ -Fetch from the upstream repository of the current branch. - -\(fn ARGS)" t nil) + (autoload 'magit-fetch "magit-fetch" nil t) + (autoload 'magit-fetch-from-pushremote "magit-fetch" nil t) + (autoload 'magit-fetch-from-upstream "magit-fetch" nil t) (autoload 'magit-fetch-other "magit-fetch" "\ Fetch from another repository. @@ -1239,18 +1028,31 @@ prefix argument fetch all remotes. (autoload 'magit-find-file "magit-files" "\ View FILE from REV. -Switch to a buffer visiting blob REV:FILE, -creating one if none already exists. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go +to the line and column corresponding to that location. \(fn REV FILE)" t nil) (autoload 'magit-find-file-other-window "magit-files" "\ View FILE from REV, in another window. -Like `magit-find-file', but create a new window or reuse an -existing one. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go to +the line and column corresponding to that location. + +\(fn REV FILE)" t nil) + +(autoload 'magit-find-file-other-frame "magit-files" "\ +View FILE from REV, in another frame. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go to +the line and column corresponding to that location. \(fn REV FILE)" t nil) - (autoload 'magit-file-popup "magit" nil t) + (autoload 'magit-file-dispatch "magit" nil t) (defvar global-magit-file-mode t "\ Non-nil if Global Magit-File mode is enabled. @@ -1274,6 +1076,13 @@ See `magit-file-mode' for more information on Magit-File mode. \(fn &optional ARG)" t nil) +(autoload 'magit-blob-visit-file "magit-files" "\ +View the file from the worktree corresponding to the current blob. +When visiting a blob or the version from the index, then go to +the same location in the respective file in the working tree. + +\(fn)" t nil) + (autoload 'magit-file-checkout "magit-files" "\ Checkout FILE from REV. @@ -1293,17 +1102,45 @@ Checkout FILE from REV. ;;;### (autoloads nil "magit-gitignore" "magit-gitignore.el" (0 0 ;;;;;; 0 0)) ;;; Generated autoloads from magit-gitignore.el - (autoload 'magit-gitignore-popup "magit-gitignore" nil t) + (autoload 'magit-gitignore "magit-gitignore" nil t) + +(autoload 'magit-gitignore-in-topdir "magit-gitignore" "\ +Add the Git ignore RULE to the top-level \".gitignore\" file. +Since this file is tracked, it is shared with other clones of the +repository. Also stage the file. -(autoload 'magit-gitignore-globally "magit-gitignore" "\ -Instruct Git to globally ignore FILE-OR-PATTERN. +\(fn RULE)" t nil) -\(fn FILE-OR-PATTERN)" t nil) +(autoload 'magit-gitignore-in-subdir "magit-gitignore" "\ +Add the Git ignore RULE to a \".gitignore\" file. +Prompted the user for a directory and add the rule to the +\".gitignore\" file in that directory. Since such files are +tracked, they are shared with other clones of the repository. +Also stage the file. + +\(fn RULE DIRECTORY)" t nil) + +(autoload 'magit-gitignore-in-gitdir "magit-gitignore" "\ +Add the Git ignore RULE to \"$GIT_DIR/info/exclude\". +Rules in that file only affects this clone of the repository. + +\(fn RULE)" t nil) + +(autoload 'magit-gitignore-on-system "magit-gitignore" "\ +Add the Git ignore RULE to the file specified by `core.excludesFile'. +Rules that are defined in that file affect all local repositories. + +\(fn RULE)" t nil) + +(autoload 'magit-skip-worktree "magit-gitignore" "\ +Call \"git update-index --skip-worktree FILE\". + +\(fn FILE)" t nil) -(autoload 'magit-gitignore-locally "magit-gitignore" "\ -Instruct Git to locally ignore FILE-OR-PATTERN. +(autoload 'magit-no-skip-worktree "magit-gitignore" "\ +Call \"git update-index --no-skip-worktree FILE\". -\(fn FILE-OR-PATTERN)" t nil) +\(fn FILE)" t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-gitignore" '("magit-"))) @@ -1429,20 +1266,8 @@ beginning of the line. ;;;### (autoloads nil "magit-log" "magit-log.el" (0 0 0 0)) ;;; Generated autoloads from magit-log.el - -(autoload 'magit-log-popup "magit-log" "\ -Popup console for log commands. - -\(fn ARG)" t nil) - -(autoload 'magit-log-buffer-file-popup "magit-log" "\ -Popup console for log commands. - -This is a variant of `magit-log-popup' which shows the same popup -but which limits the log to the file being visited in the current -buffer. - -\(fn)" t nil) + (autoload 'magit-log "magit-log" nil t) + (autoload 'magit-log-refresh "magit-log" nil t) (autoload 'magit-log-current "magit-log" "\ Show log for the current branch. @@ -1495,28 +1320,17 @@ Show log for the definition at point. (autoload 'magit-log-merged "magit-log" "\ Show log for the merge of COMMIT into BRANCH. + More precisely, find merge commit M that brought COMMIT into -BRANCH, and show the log of the range \"M^..M\". This command -requires git-when-merged, which is available from +BRANCH, and show the log of the range \"M^1..M\". If COMMIT is +directly on BRANCH, then show approximately twenty surrounding +commits instead. + +This command requires git-when-merged, which is available from https://github.com/mhagger/git-when-merged. \(fn COMMIT BRANCH &optional ARGS FILES)" t nil) -(autoload 'magit-reflog-current "magit-log" "\ -Display the reflog of the current branch. - -\(fn ARGS)" t nil) - -(autoload 'magit-reflog-other "magit-log" "\ -Display the reflog of a branch or another ref. - -\(fn REF ARGS)" t nil) - -(autoload 'magit-reflog-head "magit-log" "\ -Display the `HEAD' reflog. - -\(fn ARGS)" t nil) - (autoload 'magit-log-move-to-parent "magit-log" "\ Move to the Nth parent of the current commit. @@ -1527,7 +1341,7 @@ Show commits in a branch that are not merged in the upstream branch. \(fn HEAD UPSTREAM)" t nil) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-log" '("magit-"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-log" '("magit"))) ;;;*** @@ -1540,7 +1354,7 @@ Show commits in a branch that are not merged in the upstream branch. ;;;### (autoloads nil "magit-merge" "magit-merge.el" (0 0 0 0)) ;;; Generated autoloads from magit-merge.el - (autoload 'magit-merge-popup "magit" nil t) + (autoload 'magit-merge "magit" nil t) (autoload 'magit-merge-plain "magit-merge" "\ Merge commit REV into the current branch; using default message. @@ -1629,40 +1443,25 @@ Abort the current merge operation. ;;;### (autoloads nil "magit-notes" "magit-notes.el" (0 0 0 0)) ;;; Generated autoloads from magit-notes.el - (autoload 'magit-notes-popup "magit" nil t) + (autoload 'magit-notes "magit" nil t) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-notes" '("magit-"))) ;;;*** -;;;### (autoloads nil "magit-patch" "magit-patch.el" (0 0 0 0)) -;;; Generated autoloads from magit-patch.el - (autoload 'magit-patch-popup "magit-patch" nil t) - -(autoload 'magit-format-patch "magit-patch" "\ -Create patches for the commits in RANGE. -When a single commit is given for RANGE, create a patch for the -changes introduced by that commit (unlike 'git format-patch' -which creates patches for all commits that are reachable from -`HEAD' but not from the specified commit). - -\(fn RANGE ARGS FILES)" t nil) - -(autoload 'magit-request-pull "magit-patch" "\ -Request upstream to pull from you public repository. - -URL is the url of your publically accessible repository. -START is a commit that already is in the upstream repository. -END is the last commit, usually a branch name, which upstream -is asked to pull. START has to be reachable from that commit. - -\(fn URL START END)" t nil) - (autoload 'magit-patch-apply-popup "magit-patch" nil t) +;;;### (autoloads nil "magit-obsolete" "magit-obsolete.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from magit-obsolete.el -(autoload 'magit-patch-apply "magit-patch" "\ -Apply the patch file FILE. +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-obsolete" '("magit--magit-popup-warning"))) -\(fn FILE &rest ARGS)" t nil) +;;;*** + +;;;### (autoloads nil "magit-patch" "magit-patch.el" (0 0 0 0)) +;;; Generated autoloads from magit-patch.el + (autoload 'magit-patch "magit-patch" nil t) + (autoload 'magit-patch-create "magit-patch" nil t) + (autoload 'magit-patch-apply "magit-patch" nil t) (autoload 'magit-patch-save "magit-patch" "\ Write current diff into patch FILE. @@ -1689,7 +1488,17 @@ same differences as those shown in the buffer are always used. \(fn FILE &optional ARG)" t nil) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-patch" '("magit-patch-save-arguments"))) +(autoload 'magit-request-pull "magit-patch" "\ +Request upstream to pull from you public repository. + +URL is the url of your publically accessible repository. +START is a commit that already is in the upstream repository. +END is the last commit, usually a branch name, which upstream +is asked to pull. START has to be reachable from that commit. + +\(fn URL START END)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-patch" '("magit-"))) ;;;*** @@ -1702,52 +1511,24 @@ same differences as those shown in the buffer are always used. ;;;### (autoloads nil "magit-pull" "magit-pull.el" (0 0 0 0)) ;;; Generated autoloads from magit-pull.el - (autoload 'magit-pull-popup "magit-pull" nil t) - (autoload 'magit-pull-and-fetch-popup "magit-pull" nil t) - -(autoload 'magit-pull-from-pushremote "magit-pull" "\ -Pull from the push-remote of the current branch. - -\(fn ARGS)" t nil) - -(autoload 'magit-pull-from-upstream "magit-pull" "\ -Pull from the upstream of the current branch. - -\(fn ARGS)" t nil) + (autoload 'magit-pull "magit-pull" nil t) + (autoload 'magit-pull-from-pushremote "magit-pull" nil t) + (autoload 'magit-pull-from-upstream "magit-pull" nil t) (autoload 'magit-pull-branch "magit-pull" "\ Pull from a branch read in the minibuffer. \(fn SOURCE ARGS)" t nil) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-pull" '("magit-"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-pull" '("magit-pull"))) ;;;*** ;;;### (autoloads nil "magit-push" "magit-push.el" (0 0 0 0)) ;;; Generated autoloads from magit-push.el - (autoload 'magit-push-popup "magit-push" nil t) - -(autoload 'magit-push-current-to-pushremote "magit-push" "\ -Push the current branch to `branch..pushRemote'. -If that variable is unset, then push to `remote.pushDefault'. - -When `magit-push-current-set-remote-if-missing' is non-nil and -the push-remote is not configured, then read the push-remote from -the user, set it, and then push to it. With a prefix argument -the push-remote can be changed before pushed to it. - -\(fn ARGS &optional PUSH-REMOTE)" t nil) - -(autoload 'magit-push-current-to-upstream "magit-push" "\ -Push the current branch to its upstream branch. - -When `magit-push-current-set-remote-if-missing' is non-nil and -the upstream is not configured, then read the upstream from the -user, set it, and then push to it. With a prefix argument the -upstream can be changed before pushed to it. - -\(fn ARGS &optional UPSTREAM)" t nil) + (autoload 'magit-push "magit-push" nil t) + (autoload 'magit-push-current-to-pushremote "magit-push" nil t) + (autoload 'magit-push-current-to-upstream "magit-push" nil t) (autoload 'magit-push-current "magit-push" "\ Push the current branch to a branch read in the minibuffer. @@ -1799,13 +1580,6 @@ these Git variables: `push.default', `remote.pushDefault', `branch..pushRemote', `branch..remote', `branch..merge', and `remote..push'. -To add this command to the push popup add this to your init file: - - (with-eval-after-load \\='magit-remote - (magit-define-popup-action \\='magit-push-popup ?P - \\='magit-push-implicitly--desc - \\='magit-push-implicitly ?p t)) - The function `magit-push-implicitly--desc' attempts to predict what this command will do. The value it returns is displayed in the popup buffer. @@ -1823,43 +1597,54 @@ these Git variables: `push.default', `remote.pushDefault', `branch..pushRemote', `branch..remote', `branch..merge', and `remote..push'. -To add this command to the push popup add this to your init file: - - (with-eval-after-load \\='magit-remote - (magit-define-popup-action \\='magit-push-popup ?r - \\='magit-push-to-remote--desc - \\='magit-push-to-remote ?p t)) - \(fn REMOTE ARGS)" t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-push" '("magit-"))) ;;;*** -;;;### (autoloads nil "magit-refs" "magit-refs.el" (0 0 0 0)) -;;; Generated autoloads from magit-refs.el +;;;### (autoloads nil "magit-reflog" "magit-reflog.el" (0 0 0 0)) +;;; Generated autoloads from magit-reflog.el -(autoload 'magit-show-refs-popup "magit-refs" "\ -Popup console for `magit-show-refs'. +(autoload 'magit-reflog-current "magit-reflog" "\ +Display the reflog of the current branch. +If `HEAD' is detached, then show the reflog for that instead. -\(fn &optional ARG)" t nil) +\(fn)" t nil) + +(autoload 'magit-reflog-other "magit-reflog" "\ +Display the reflog of a branch or another ref. + +\(fn REF)" t nil) + +(autoload 'magit-reflog-head "magit-reflog" "\ +Display the `HEAD' reflog. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-reflog" '("magit-reflog-"))) + +;;;*** + +;;;### (autoloads nil "magit-refs" "magit-refs.el" (0 0 0 0)) +;;; Generated autoloads from magit-refs.el + (autoload 'magit-show-refs "magit-refs" nil t) (autoload 'magit-show-refs-head "magit-refs" "\ List and compare references in a dedicated buffer. -Refs are compared with `HEAD'. +Compared with `HEAD'. \(fn &optional ARGS)" t nil) (autoload 'magit-show-refs-current "magit-refs" "\ List and compare references in a dedicated buffer. -Refs are compared with the current branch or `HEAD' if -it is detached. +Compare with the current branch or `HEAD' if it is detached. \(fn &optional ARGS)" t nil) -(autoload 'magit-show-refs "magit-refs" "\ +(autoload 'magit-show-refs-other "magit-refs" "\ List and compare references in a dedicated buffer. -Refs are compared with a branch read from the user. +Compared with a branch read from the user. \(fn &optional REF ARGS)" t nil) @@ -1869,7 +1654,7 @@ Refs are compared with a branch read from the user. ;;;### (autoloads nil "magit-remote" "magit-remote.el" (0 0 0 0)) ;;; Generated autoloads from magit-remote.el - (autoload 'magit-remote-popup "magit-remote" nil t) + (autoload 'magit-remote "magit-remote" nil t) (autoload 'magit-remote-add "magit-remote" "\ Add a remote named REMOTE and fetch it. @@ -1921,11 +1706,7 @@ Unset the local representation of REMOTE's default branch. Delete the symbolic-ref \"refs/remotes//HEAD\". \(fn REMOTE)" t nil) - -(autoload 'magit-remote-config-popup "magit-remote" "\ -Popup console for setting remote variables. - -\(fn REMOTE)" t nil) + (autoload 'magit-remote-configure "magit-remote" nil t) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-remote" '("magit-"))) @@ -1948,7 +1729,7 @@ repositories are displayed. ;;;### (autoloads nil "magit-reset" "magit-reset.el" (0 0 0 0)) ;;; Generated autoloads from magit-reset.el - (autoload 'magit-reset-popup "magit" nil t) + (autoload 'magit-reset "magit" nil t) (autoload 'magit-reset-mixed "magit-reset" "\ Reset the `HEAD' and index to COMMIT, but not the working tree. @@ -1994,7 +1775,7 @@ With a prefix argument reset the working tree otherwise don't. \(fn COMMIT &optional HARD)" t nil) -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-reset" '("magit-reset-"))) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-reset" '("magit-reset"))) ;;;*** @@ -2024,7 +1805,7 @@ Abort the current cherry-pick or revert sequence. This discards all changes made since the sequence started. \(fn)" t nil) - (autoload 'magit-cherry-pick-popup "magit-sequence" nil t) + (autoload 'magit-cherry-pick "magit-sequence" nil t) (autoload 'magit-cherry-copy "magit-sequence" "\ Copy COMMITS from another branch onto the current branch. @@ -2073,7 +1854,7 @@ If a conflict occurs, then you have to fix that and finish the process manually. \(fn COMMITS BRANCH START-POINT &optional ARGS)" t nil) - (autoload 'magit-revert-popup "magit-sequence" nil t) + (autoload 'magit-revert "magit-sequence" nil t) (autoload 'magit-revert-and-commit "magit-sequence" "\ Revert COMMIT by creating a new commit. @@ -2090,7 +1871,7 @@ the region selects multiple commits, then revert all of them, without prompting. \(fn COMMIT &optional ARGS)" t nil) - (autoload 'magit-am-popup "magit-sequence" nil t) + (autoload 'magit-am "magit-sequence" nil t) (autoload 'magit-am-apply-patches "magit-sequence" "\ Apply the patches FILES. @@ -2117,18 +1898,9 @@ Abort the current patch applying sequence. This discards all changes made since the sequence started. \(fn)" t nil) - (autoload 'magit-rebase-popup "magit-sequence" nil t) - -(autoload 'magit-rebase-onto-pushremote "magit-sequence" "\ -Rebase the current branch onto `branch..pushRemote'. -If that variable is unset, then rebase onto `remote.pushDefault'. - -\(fn ARGS)" t nil) - -(autoload 'magit-rebase-onto-upstream "magit-sequence" "\ -Rebase the current branch onto its upstream branch. - -\(fn ARGS)" t nil) + (autoload 'magit-rebase "magit-sequence" nil t) + (autoload 'magit-rebase-onto-pushremote "magit-sequence" nil t) + (autoload 'magit-rebase-onto-upstream "magit-sequence" nil t) (autoload 'magit-rebase-branch "magit-sequence" "\ Rebase the current branch onto a branch read in the minibuffer. @@ -2197,11 +1969,11 @@ Abort the current rebase operation, restoring the original branch. ;;;### (autoloads nil "magit-stash" "magit-stash.el" (0 0 0 0)) ;;; Generated autoloads from magit-stash.el - (autoload 'magit-stash-popup "magit-stash" nil t) + (autoload 'magit-stash "magit-stash" nil t) (autoload 'magit-stash-both "magit-stash" "\ Create a stash of the index and working tree. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'. @@ -2218,7 +1990,7 @@ Applying the resulting stash has the inverse effect. (autoload 'magit-stash-worktree "magit-stash" "\ Create a stash of unstaged changes in the working tree. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'. @@ -2226,7 +1998,7 @@ while two prefix arguments are equivalent to `--all'. (autoload 'magit-stash-keep-index "magit-stash" "\ Create a stash of the index and working tree, keeping index intact. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'. @@ -2234,7 +2006,7 @@ while two prefix arguments are equivalent to `--all'. (autoload 'magit-snapshot-both "magit-stash" "\ Create a snapshot of the index and working tree. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'. @@ -2248,7 +2020,7 @@ Unstaged and untracked changes are not stashed. (autoload 'magit-snapshot-worktree "magit-stash" "\ Create a snapshot of unstaged changes in the working tree. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'. @@ -2353,10 +2125,10 @@ prefix arguments: \(fn &optional DIRECTORY CACHE)" t nil) -(autoload 'magit-status-internal "magit-status" "\ +(autoload 'magit-status-setup-buffer "magit-status" "\ -\(fn DIRECTORY)" nil nil) +\(fn &optional DIRECTORY)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-status" '("magit"))) @@ -2365,72 +2137,18 @@ prefix arguments: ;;;### (autoloads nil "magit-submodule" "magit-submodule.el" (0 0 ;;;;;; 0 0)) ;;; Generated autoloads from magit-submodule.el - (autoload 'magit-submodule-popup "magit-submodule" nil t) - -(autoload 'magit-submodule-add "magit-submodule" "\ -Add the repository at URL as a module. - -Optional PATH is the path to the module relative to the root of -the superproject. If it is nil, then the path is determined -based on the URL. Optional NAME is the name of the module. If -it is nil, then PATH also becomes the name. - -\(fn URL &optional PATH NAME ARGS)" t nil) + (autoload 'magit-submodule "magit-submodule" nil t) + (autoload 'magit-submodule-add "magit-submodule" nil t) (autoload 'magit-submodule-read-name-for-path "magit-submodule" "\ \(fn PATH &optional PREFER-SHORT)" nil nil) - -(autoload 'magit-submodule-register "magit-submodule" "\ -Register MODULES. - -With a prefix argument act on all suitable modules. Otherwise, -if the region selects modules, then act on those. Otherwise, if -there is a module at point, then act on that. Otherwise read a -single module from the user. - -\(fn MODULES)" t nil) - -(autoload 'magit-submodule-populate "magit-submodule" "\ -Create MODULES working directories, checking out the recorded commits. - -With a prefix argument act on all suitable modules. Otherwise, -if the region selects modules, then act on those. Otherwise, if -there is a module at point, then act on that. Otherwise read a -single module from the user. - -\(fn MODULES)" t nil) - -(autoload 'magit-submodule-update "magit-submodule" "\ -Update MODULES by checking out the recorded commits. - -With a prefix argument act on all suitable modules. Otherwise, -if the region selects modules, then act on those. Otherwise, if -there is a module at point, then act on that. Otherwise read a -single module from the user. - -\(fn MODULES ARGS)" t nil) - -(autoload 'magit-submodule-synchronize "magit-submodule" "\ -Synchronize url configuration of MODULES. - -With a prefix argument act on all suitable modules. Otherwise, -if the region selects modules, then act on those. Otherwise, if -there is a module at point, then act on that. Otherwise read a -single module from the user. - -\(fn MODULES ARGS)" t nil) - -(autoload 'magit-submodule-unpopulate "magit-submodule" "\ -Remove working directories of MODULES. - -With a prefix argument act on all suitable modules. Otherwise, -if the region selects modules, then act on those. Otherwise, if -there is a module at point, then act on that. Otherwise read a -single module from the user. - -\(fn MODULES ARGS)" t nil) + (autoload 'magit-submodule-register "magit-submodule" nil t) + (autoload 'magit-submodule-populate "magit-submodule" nil t) + (autoload 'magit-submodule-update "magit-submodule" nil t) + (autoload 'magit-submodule-synchronize "magit-submodule" nil t) + (autoload 'magit-submodule-unpopulate "magit-submodule" nil t) (autoload 'magit-submodule-remove "magit-submodule" "\ Unregister MODULES and remove their working directories. @@ -2498,7 +2216,9 @@ Display a list of the current repository's submodules. ;;;### (autoloads nil "magit-subtree" "magit-subtree.el" (0 0 0 0)) ;;; Generated autoloads from magit-subtree.el - (autoload 'magit-subtree-popup "magit-subtree" nil t) + (autoload 'magit-subtree "magit-subtree" nil t) + (autoload 'magit-subtree-import "magit-subtree" nil t) + (autoload 'magit-subtree-export "magit-subtree" nil t) (autoload 'magit-subtree-add "magit-subtree" "\ Add REF from REPOSITORY as a new subtree at PREFIX. @@ -2536,7 +2256,7 @@ Extract the history of the subtree PREFIX. ;;;### (autoloads nil "magit-tag" "magit-tag.el" (0 0 0 0)) ;;; Generated autoloads from magit-tag.el - (autoload 'magit-tag-popup "magit" nil t) + (autoload 'magit-tag "magit" nil t) (autoload 'magit-tag-create "magit-tag" "\ Create a new tag with the given NAME at REV. @@ -2586,6 +2306,14 @@ review the result. (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-tag" '("magit-"))) +;;;*** + +;;;### (autoloads nil "magit-transient" "magit-transient.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from magit-transient.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-transient" '("magit-"))) + ;;;*** ;;;### (autoloads nil "magit-utils" "magit-utils.el" (0 0 0 0)) @@ -2706,7 +2434,7 @@ a Git repository. ;;;### (autoloads nil "magit-worktree" "magit-worktree.el" (0 0 0 ;;;;;; 0)) ;;; Generated autoloads from magit-worktree.el - (autoload 'magit-worktree-popup "magit-worktree" nil t) + (autoload 'magit-worktree "magit-worktree" nil t) (autoload 'magit-worktree-checkout "magit-worktree" "\ Checkout BRANCH in a new worktree at PATH. @@ -2722,8 +2450,8 @@ Create a new BRANCH and check it out in a new worktree at PATH. ;;;*** -;;;### (autoloads nil nil ("magit-core.el" "magit-obsolete.el" "magit-pkg.el") -;;;;;; (0 0 0 0)) +;;;### (autoloads nil nil ("magit-core.el" "magit-pkg.el") (0 0 0 +;;;;;; 0)) ;;;*** diff --git a/elpa/magit-20190122.503/magit-autorevert.el b/elpa/magit-20190514.1814/magit-autorevert.el similarity index 79% rename from elpa/magit-20190122.503/magit-autorevert.el rename to elpa/magit-20190514.1814/magit-autorevert.el index 62c7c227..3a437e86 100644 --- a/elpa/magit-20190122.503/magit-autorevert.el +++ b/elpa/magit-20190514.1814/magit-autorevert.el @@ -43,15 +43,15 @@ (defcustom auto-revert-buffer-list-filter nil "Filter that determines which buffers `auto-revert-buffers' reverts. -This option is provided by `magit', which also redefines +This option is provided by Magit, which also advises `auto-revert-buffers' to respect it. Magit users who do not turn on the local mode `auto-revert-mode' themselves, are best served -by setting the value to `magit-auto-revert-repository-buffers-p'. +by setting the value to `magit-auto-revert-repository-buffer-p'. -However the default is nil, to not disturb users who do use the -local mode directly. If you experience delays when running Magit -commands, then you should consider using one of the predicates -provided by Magit - especially if you also use Tramp. +However the default is nil, so as not to disturb users who do use +the local mode directly. If you experience delays when running +Magit commands, then you should consider using one of the +predicates provided by Magit - especially if you also use Tramp. Users who do turn on `auto-revert-mode' in buffers in which Magit doesn't do that for them, should likely not use any filter. @@ -62,7 +62,7 @@ is enabled." :group 'auto-revert :group 'magit-auto-revert :group 'magit-related - :type '(radio (const :tag "no filter" nil) + :type '(radio (const :tag "No filter" nil) (function-item magit-auto-revert-buffer-p) (function-item magit-auto-revert-repository-buffer-p) function)) @@ -85,7 +85,7 @@ is enabled." If this is non-nil and either `global-auto-revert-mode' or `magit-auto-revert-mode' is enabled, then Magit immediately reverts buffers by explicitly calling `auto-revert-buffers' -after running git for side-effects. +after running Git for side-effects. If `auto-revert-use-notify' is non-nil (and file notifications are actually supported), then `magit-auto-revert-immediately' @@ -127,12 +127,8 @@ seconds of user inactivity. That is not desirable." ;; - In all other cases enable the mode because if buffers are not ;; automatically reverted that would make many very common tasks ;; much more cumbersome. - ;; - When `magit-revert-buffers' is nil, then the user has opted out - ;; of the automatic reverts while a very old implementation was - ;; still in use. We continued to respect that setting for another - ;; two and a half years, but no longer do so now. - :init-value (and (not global-auto-revert-mode) - (not noninteractive))) + :init-value (not (or global-auto-revert-mode + noninteractive))) ;; - Unfortunately `:init-value t' only sets the value of the mode ;; variable but does not cause the mode function to be called. ;; - I don't think it works like this on purpose, but since one usually @@ -140,9 +136,6 @@ seconds of user inactivity. That is not desirable." ;; - If the user has set the variable `magit-auto-revert-mode' to nil ;; after loading magit (instead of doing so before loading magit or ;; by using the function), then we should still respect that setting. -;; - If the user has set the obsolete variable `magit-revert-buffers' -;; to nil before or after loading magit, then we should still respect -;; that setting. ;; - If the user sets one of these variables after loading magit and ;; after `after-init-hook' has run, then that won't have an effect ;; and there is nothing we can do about it. @@ -157,7 +150,7 @@ and code surrounding the definition of this function." (magit-auto-revert-mode 1) (magit-message "Turning on magit-auto-revert-mode...done%s" - (let ((elapsed (float-time (time-subtract (current-time) start)))) + (let ((elapsed (float-time (time-subtract nil start)))) (if (> elapsed 0.2) (format " (%.3fs, %s buffers checked)" elapsed (length (buffer-list))) @@ -173,9 +166,10 @@ and code surrounding the definition of this function." (put 'magit-auto-revert-mode 'function-documentation "Toggle Magit Auto Revert mode. -With a prefix argument ARG, enable Magit Auto Revert mode if ARG -is positive, and disable it otherwise. If called from Lisp, -enable the mode if ARG is omitted or nil. +If called interactively, enable Magit Auto Revert mode if ARG is +positive, and disable it if ARG is zero or negative. If called +from Lisp, also enable the mode if ARG is omitted or nil, and +toggle it if ARG is `toggle'; disable the mode otherwise. Magit Auto Revert mode is a global minor mode that reverts buffers associated with a file that is located inside a Git @@ -208,50 +202,47 @@ This function calls the hook `magit-auto-revert-mode-hook'.") (and magit-auto-revert-mode auto-revert-buffer-list))) (let ((auto-revert-buffer-list-filter (or auto-revert-buffer-list-filter - 'magit-auto-revert-repository-buffer-p))) + #'magit-auto-revert-repository-buffer-p))) (auto-revert-buffers)))) (defvar magit-auto-revert-toplevel nil) -(when (< emacs-major-version 25) - (defvar auto-revert-buffers-counter 1 - "Incremented each time `auto-revert-buffers' is called")) +(defvar magit-auto-revert-counter 1 + "Incremented each time `auto-revert-buffers' is called.") (defun magit-auto-revert-buffer-p (buffer) - "Return t if BUFFER visits a file inside the current repository. -The current repository is the one in which `default-directory' is -located. If there is no current repository, then return t for -any BUFFER." + "Return non-nil if BUFFER visits a file inside the current repository. +The current repository is the one containing `default-directory'. +If there is no current repository, then return t for any BUFFER." (magit-auto-revert-repository-buffer-p buffer t)) (defun magit-auto-revert-repository-buffer-p (buffer &optional fallback) - "Return t if BUFFER visits a file inside the current repository. -The current repository is the one in which `default-directory' is -located. If there is no current repository, then return FALLBACK -\(which defaults to nil) for any BUFFER." + "Return non-nil if BUFFER visits a file inside the current repository. +The current repository is the one containing `default-directory'. +If there is no current repository, then return FALLBACK (which +defaults to nil) for any BUFFER." ;; Call `magit-toplevel' just once per cycle. (unless (and magit-auto-revert-toplevel (= (cdr magit-auto-revert-toplevel) - auto-revert-buffers-counter)) + magit-auto-revert-counter)) (setq magit-auto-revert-toplevel (cons (or (magit-toplevel) 'no-repo) - auto-revert-buffers-counter))) + magit-auto-revert-counter))) (let ((top (car magit-auto-revert-toplevel))) (if (eq top 'no-repo) fallback - (let ((dir (with-current-buffer buffer default-directory))) + (let ((dir (buffer-local-value 'default-directory buffer))) (and (equal (file-remote-p dir) (file-remote-p top)) ;; ^ `tramp-handle-file-in-directory-p' lacks this optimization. (file-in-directory-p dir top)))))) (defun auto-revert-buffers--buffer-list-filter () - (when (< emacs-major-version 25) - (cl-incf auto-revert-buffers-counter)) + (cl-incf magit-auto-revert-counter) (when auto-revert-buffer-list-filter (setq auto-revert-buffer-list - (--filter auto-revert-buffer-list-filter - auto-revert-buffer-list)))) + (-filter auto-revert-buffer-list-filter + auto-revert-buffer-list)))) (advice-add 'auto-revert-buffers :before 'auto-revert-buffers--buffer-list-filter) diff --git a/elpa/magit-20190122.503/magit-bisect.el b/elpa/magit-20190514.1814/magit-bisect.el similarity index 81% rename from elpa/magit-20190122.503/magit-bisect.el rename to elpa/magit-20190514.1814/magit-bisect.el index a4345c7b..3338f8f6 100644 --- a/elpa/magit-20190122.503/magit-bisect.el +++ b/elpa/magit-20190514.1814/magit-bisect.el @@ -54,18 +54,21 @@ ;;; Commands -;;;###autoload (autoload 'magit-bisect-popup "magit-bisect" nil t) -(magit-define-popup magit-bisect-popup - "Popup console for bisect commands." +;;;###autoload (autoload 'magit-bisect "magit-bisect" nil t) +(define-transient-command magit-bisect () + "Narrow in on the commit that introduced a bug." :man-page "git-bisect" - :actions '((?B "Start" magit-bisect-start) - (?s "Start script" magit-bisect-run)) - :sequence-actions '((?b "Bad" magit-bisect-bad) - (?g "Good" magit-bisect-good) - (?k "Skip" magit-bisect-skip) - (?r "Reset" magit-bisect-reset) - (?s "Run script" magit-bisect-run)) - :sequence-predicate 'magit-bisect-in-progress-p) + ["Actions" + :if-not magit-bisect-in-progress-p + ("B" "Start" magit-bisect-start) + ("s" "Start script" magit-bisect-run)] + ["Actions" + :if magit-bisect-in-progress-p + ("B" "Bad" magit-bisect-bad) + ("g" "Good" magit-bisect-good) + ("k" "Skip" magit-bisect-skip) + ("r" "Reset" magit-bisect-reset) + ("s" "Run script" magit-bisect-run)]) ;;;###autoload (defun magit-bisect-start (bad good) @@ -74,8 +77,8 @@ Bisecting a bug means to find the commit that introduced it. This command starts such a bisect session by asking for a know good and a bad commit. To move the session forward use the -other actions from the bisect popup (\ -\\\\[magit-bisect-popup])." +other actions from the bisect transient command (\ +\\\\[magit-bisect])." (interactive (if (magit-bisect-in-progress-p) (user-error "Already bisecting") (magit-bisect-start-read-args))) @@ -140,9 +143,27 @@ bisect run'." (defun magit-git-bisect (subcommand &optional args no-assert) (unless (or no-assert (magit-bisect-in-progress-p)) (user-error "Not bisecting")) + (message "Bisecting...") (magit-with-toplevel - (magit-run-git-with-logfile - (magit-git-dir "BISECT_CMD_OUTPUT") "bisect" subcommand args))) + (magit-run-git-async "bisect" subcommand args)) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (if (> (process-exit-status process) 0) + (magit-process-sentinel process event) + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (when (buffer-live-p (process-buffer process)) + (with-current-buffer (process-buffer process) + (when-let ((section (get-text-property (point) 'magit-section)) + (output (buffer-substring-no-properties + (oref section content) + (oref section end)))) + (with-temp-file (magit-git-dir "BISECT_CMD_OUTPUT") + (insert output))))) + (magit-refresh)) + (message "Bisecting...done"))))) ;;; Sections @@ -178,7 +199,7 @@ bisect run'." (magit-insert-heading "Bisect Rest:") (magit-git-wash (apply-partially 'magit-log-wash-log 'bisect-vis) "bisect" "visualize" "git" "log" - "--format=%h%d%x00%s" "--decorate=full" + "--format=%h%x00%D%x00%s" "--decorate=full" (and magit-bisect-show-graph "--graph"))))) (defun magit-insert-bisect-log () diff --git a/elpa/magit-20190122.503/magit-blame.el b/elpa/magit-20190514.1814/magit-blame.el similarity index 93% rename from elpa/magit-20190122.503/magit-blame.el rename to elpa/magit-20190514.1814/magit-blame.el index ed99cf35..3aacf1ef 100644 --- a/elpa/magit-20190122.503/magit-blame.el +++ b/elpa/magit-20190514.1814/magit-blame.el @@ -51,7 +51,8 @@ (highlight (highlight-face . magit-blame-highlight)) (lines - (show-lines . t))) + (show-lines . t) + (show-message . t))) "List of styles used to visualize blame information. Each entry has the form (IDENT (KEY . VALUE)...). IDENT has @@ -61,6 +62,9 @@ KEYs are recognized: `show-lines' Whether to prefix each chunk of lines with a thin line. This has no effect if `heading-format' is non-nil. + `show-message' + Whether to display a commit's summary line in the echo area + when crossing chunks. `highlight-face' Face used to highlight the first line of each chunk. If this is nil, then those lines are not highlighted. @@ -273,7 +277,7 @@ in `magit-blame-read-only-mode-map' instead.") (define-key map (kbd "j") 'magit-blame-addition) (define-key map (kbd "l") 'magit-blame-removal) (define-key map (kbd "f") 'magit-blame-reverse) - (define-key map (kbd "b") 'magit-blame-popup)) + (define-key map (kbd "b") 'magit-blame)) (t (define-key map (kbd "C-m") 'magit-show-commit) (define-key map (kbd "p") 'magit-blame-previous-chunk) @@ -283,7 +287,7 @@ in `magit-blame-read-only-mode-map' instead.") (define-key map (kbd "b") 'magit-blame-addition) (define-key map (kbd "r") 'magit-blame-removal) (define-key map (kbd "f") 'magit-blame-reverse) - (define-key map (kbd "B") 'magit-blame-popup))) + (define-key map (kbd "B") 'magit-blame))) (define-key map (kbd "c") 'magit-blame-cycle-style) (define-key map (kbd "q") 'magit-blame-quit) (define-key map (kbd "M-w") 'magit-blame-copy-hash) @@ -319,7 +323,7 @@ in `magit-blame-read-only-mode-map' instead.") (setq magit-blame-mode nil) (user-error (concat "Don't call `magit-blame-mode' directly; " - "instead use `magit-blame' or `magit-blame-popup'"))) + "instead use `magit-blame'"))) (add-hook 'after-save-hook 'magit-blame--run t t) (add-hook 'post-command-hook 'magit-blame-goto-chunk-hook t t) (add-hook 'before-revert-hook 'magit-blame--remove-overlays t t) @@ -697,23 +701,26 @@ modes is toggled, then this mode also gets toggled automatically. (defun magit-blame-maybe-show-message () (when (magit-blame--style-get 'show-message) (let ((message-log-max 0)) - (if-let ((msg (cdr (assq 'heading + (if-let ((msg (cdr (assoc "summary" (gethash (oref (magit-current-blame-chunk) orig-rev) magit-blame-cache))))) - (progn (setq msg (substring msg 0 -1)) - (set-text-properties 0 (length msg) nil msg) + (progn (set-text-properties 0 (length msg) nil msg) (message msg)) (message "Commit data not available yet. Still blaming."))))) ;;; Commands -;;;###autoload -(defun magit-blame-echo () +;;;###autoload (autoload 'magit-blame-echo "magit-blame" nil t) +(define-suffix-command magit-blame-echo () "For each line show the revision in which it was added. Show the information about the chunk at point in the echo area when moving between chunks. Unlike other blaming commands, do not turn on `read-only-mode'." + :if (lambda () + (and buffer-file-name + (or (not magit-blame-mode) + buffer-read-only))) (interactive) (when magit-buffer-file-name (user-error "Blob buffers aren't supported")) @@ -723,21 +730,24 @@ not turn on `read-only-mode'." (cons 'eldoc-mode magit-blame-disable-modes)) (if (not magit-blame-mode) (let ((magit-blame-read-only nil)) - (magit-blame-addition)) + (magit-blame--pre-blame-assert 'addition) + (magit-blame--pre-blame-setup 'addition) + (magit-blame--run)) (read-only-mode -1) (magit-blame--update-overlays))) -;;;###autoload -(defun magit-blame-addition () +;;;###autoload (autoload 'magit-blame-addition "magit-blame" nil t) +(define-suffix-command magit-blame-addition () "For each line show the revision in which it was added." (interactive) (magit-blame--pre-blame-assert 'addition) (magit-blame--pre-blame-setup 'addition) (magit-blame--run)) -;;;###autoload -(defun magit-blame-removal () +;;;###autoload (autoload 'magit-blame-removal "magit-blame" nil t) +(define-suffix-command magit-blame-removal () "For each line show the revision in which it was removed." + :if-nil 'buffer-file-name (interactive) (unless magit-buffer-file-name (user-error "Only blob buffers can be blamed in reverse")) @@ -745,9 +755,10 @@ not turn on `read-only-mode'." (magit-blame--pre-blame-setup 'removal) (magit-blame--run)) -;;;###autoload -(defun magit-blame-reverse () +;;;###autoload (autoload 'magit-blame-reverse "magit-blame" nil t) +(define-suffix-command magit-blame-reverse () "For each line show the last revision in which it still exists." + :if-nil 'buffer-file-name (interactive) (unless magit-buffer-file-name (user-error "Only blob buffers can be blamed in reverse")) @@ -804,10 +815,11 @@ not turn on `read-only-mode'." (goto-char (point-min)) (forward-line (1- orig-line)))) -(defun magit-blame-quit () +(define-suffix-command magit-blame-quit () "Turn off Magit-Blame mode. If the buffer was created during a recursive blame, then also kill the buffer." + :if-non-nil 'magit-blame-mode (interactive) (magit-blame-mode -1) (when magit-blame-recursive-p @@ -876,36 +888,40 @@ instead of the hash, like `kill-ring-save' would." ;;; Popup -;;;###autoload (autoload 'magit-blame-popup "magit-blame" nil t) -(magit-define-popup magit-blame-popup - "Popup console for blame commands." +;;;###autoload (autoload 'magit-blame "magit-blame" nil t) +(define-transient-command magit-blame () + "Show the commits that added or removed lines in the visited file." :man-page "git-blame" - :switches '((?w "Ignore whitespace" "-w") - (?r "Do not treat root commits as boundaries" "--root")) - :options '((?M "Detect lines moved or copied within a file" "-M") - (?C "Detect lines moved or copied between files" "-C")) - :actions '("Actions" - (?b "Show commits adding lines" magit-blame-addition) - (?r (lambda () - (with-current-buffer magit-pre-popup-buffer - (and (not buffer-file-name) - (propertize "Show commits removing lines" - 'face 'default)))) - magit-blame-removal) - (?f (lambda () - (with-current-buffer magit-pre-popup-buffer - (and (not buffer-file-name) - (propertize "Show last commits that still have lines" - 'face 'default)))) - magit-blame-reverse) - (lambda () - (and (with-current-buffer magit-pre-popup-buffer - magit-blame-mode) - (propertize "Refresh" 'face 'magit-popup-heading))) - (?c "Cycle style" magit-blame-cycle-style)) - :default-arguments '("-w") - :max-action-columns 1 - :default-action 'magit-blame-addition) + :value '("-w") + ["Arguments" + ("-w" "Ignore whitespace" "-w") + ("-r" "Do not treat root commits as boundaries" "--root") + (magit-blame:-M) + (magit-blame:-C)] + ["Actions" + ("b" "Show commits adding lines" magit-blame-addition) + ("r" "Show commits removing lines" magit-blame-removal) + ("f" "Show last commits that still have lines" magit-blame-reverse) + ("m" "Blame echo" magit-blame-echo) + ("q" "Quit blaming" magit-blame-quit)] + ["Refresh" + :if-non-nil magit-blame-mode + ("c" "Cycle style" magit-blame-cycle-style)]) + +(defun magit-blame-arguments () + (transient-args 'magit-blame)) + +(define-infix-argument magit-blame:-M () + :description "Detect lines moved or copied within a file" + :class 'transient-option + :argument "-M" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-blame:-C () + :description "Detect lines moved or copied between files" + :class 'transient-option + :argument "-C" + :reader 'transient-read-number-N+) ;;; Utilities @@ -914,7 +930,7 @@ instead of the hash, like `kill-ring-save' would." (setq magit--update-revision-buffer nil) (when-let ((chunk (magit-current-blame-chunk)) (commit (oref chunk orig-rev)) - (buffer (magit-mode-get-buffer 'magit-revision-mode nil t))) + (buffer (magit-get-mode-buffer 'magit-revision-mode nil t))) (setq magit--update-revision-buffer (list commit buffer)) (run-with-idle-timer magit-update-other-window-delay nil @@ -923,7 +939,8 @@ instead of the hash, like `kill-ring-save' would." (setq magit--update-revision-buffer nil) (when (buffer-live-p buf) (let ((magit-display-buffer-noselect t)) - (apply #'magit-show-commit rev (magit-diff-arguments)))))))))) + (apply #'magit-show-commit rev + (magit-diff-arguments 'magit-revision-mode)))))))))) ;;; _ (provide 'magit-blame) diff --git a/elpa/magit-20190514.1814/magit-bookmark.el b/elpa/magit-20190514.1814/magit-bookmark.el new file mode 100644 index 00000000..b5fef677 --- /dev/null +++ b/elpa/magit-20190514.1814/magit-bookmark.el @@ -0,0 +1,202 @@ +;;; magit-bookmark.el --- bookmark support for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Inspired by an earlier implementation by Yuri Khan. + +;; Magit is free software; you can redistribute it and/or modify it +;; 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. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; Support for bookmarks for most Magit buffers. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) +(require 'bookmark) + +;;; Core + +(defun magit--make-bookmark () + "Create a bookmark for the current Magit buffer. +Input values are the major-mode's `magit-bookmark-name' method, +and the buffer-local values of the variables referenced in its +`magit-bookmark-variables' property." + (if (plist-member (symbol-plist major-mode) 'magit-bookmark-variables) + (let ((bookmark (bookmark-make-record-default 'no-file))) + (bookmark-prop-set bookmark 'handler 'magit--handle-bookmark) + (bookmark-prop-set bookmark 'mode major-mode) + (bookmark-prop-set bookmark 'filename (magit-toplevel)) + (bookmark-prop-set bookmark 'defaults (list (magit-bookmark-name))) + (dolist (var (get major-mode 'magit-bookmark-variables)) + (bookmark-prop-set bookmark var (symbol-value var))) + (bookmark-prop-set + bookmark 'magit-hidden-sections + (--keep (and (oref it hidden) + (cons (oref it type) + (if (derived-mode-p 'magit-stash-mode) + (replace-regexp-in-string + (regexp-quote magit-buffer-revision) + magit-buffer-revision-hash + (oref it value)) + (oref it value)))) + (oref magit-root-section children))) + bookmark) + (user-error "Bookmarking is not implemented for %s buffers" major-mode))) + +(defun magit--handle-bookmark (bookmark) + "Open a bookmark created by `magit--make-bookmark'. +Call the `magit-*-setup-buffer' function of the the major-mode +with the variables' values as arguments, which were recorded by +`magit--make-bookmark'. Ignore `magit-display-buffer-function'." + (let ((buffer (let ((default-directory (bookmark-get-filename bookmark)) + (mode (bookmark-prop-get bookmark 'mode)) + (magit-display-buffer-function #'identity) + (magit-display-buffer-noselect t)) + (apply (intern (format "%s-setup-buffer" + (substring (symbol-name mode) 0 -5))) + (--map (bookmark-prop-get bookmark it) + (get mode 'magit-bookmark-variables)))))) + (set-buffer buffer) ; That is the interface we have to adhere to. + (when-let ((hidden (bookmark-prop-get bookmark 'magit-hidden-sections))) + (with-current-buffer buffer + (dolist (child (oref magit-root-section children)) + (if (member (cons (oref child type) + (oref child value)) + hidden) + (magit-section-hide child) + (magit-section-show child))))) + nil)) + +(cl-defgeneric magit-bookmark-name () + "Return name for bookmark to current buffer." + (format "%s%s" + (substring (symbol-name major-mode) 0 -5) + (if-let ((vars (get major-mode 'magit-bookmark-variables))) + (cl-mapcan (lambda (var) + (let ((val (symbol-value var))) + (if (and val (atom val)) + (list val) + val))) + vars) + ""))) + +;;; Diff +;;;; Diff + +(put 'magit-diff-mode 'magit-bookmark-variables + '(magit-buffer-range-hashed + magit-buffer-typearg + magit-buffer-diff-args + magit-buffer-diff-files)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-diff-mode)) + (format "magit-diff(%s%s)" + (pcase (magit-diff-type) + (`staged "staged") + (`unstaged "unstaged") + (`committed magit-buffer-range) + (`undefined + (delq nil (list magit-buffer-typearg magit-buffer-range-hashed)))) + (if magit-buffer-diff-files + (concat " -- " (mapconcat #'identity magit-buffer-diff-files " ")) + ""))) + +;;;; Revision + +(put 'magit-revision-mode 'magit-bookmark-variables + '(magit-buffer-revision-hash + magit-buffer-diff-args + magit-buffer-diff-files)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-revision-mode)) + (format "magit-revision(%s %s)" + (magit-rev-abbrev magit-buffer-revision) + (if magit-buffer-diff-files + (mapconcat #'identity magit-buffer-diff-files " ") + (magit-rev-format "%s" magit-buffer-revision)))) + +;;;; Stash + +(put 'magit-stash-mode 'magit-bookmark-variables + '(magit-buffer-revision-hash + magit-buffer-diff-args + magit-buffer-diff-files)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-stash-mode)) + (format "magit-stash(%s %s)" + (magit-rev-abbrev magit-buffer-revision) + (if magit-buffer-diff-files + (mapconcat #'identity magit-buffer-diff-files " ") + (magit-rev-format "%s" magit-buffer-revision)))) + +;;; Log +;;;; Log + +(put 'magit-log-mode 'magit-bookmark-variables + '(magit-buffer-revisions + magit-buffer-log-args + magit-buffer-log-files)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-log-mode)) + (format "magit-log(%s%s)" + (mapconcat #'identity magit-buffer-revisions " ") + (if magit-buffer-log-files + (concat " -- " (mapconcat #'identity magit-buffer-log-files " ")) + ""))) + +;;;; Cherry + +(put 'magit-cherry-mode 'magit-bookmark-variables + '(magit-buffer-refname + magit-buffer-upstream)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-cherry-mode)) + (format "magit-cherry(%s > %s)" + magit-buffer-refname + magit-buffer-upstream)) + +;;;; Reflog + +(put 'magit-reflog-mode 'magit-bookmark-variables + '(magit-buffer-refname)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-reflog-mode)) + (format "magit-reflog(%s)" magit-buffer-refname)) + +;;; Misc + +(put 'magit-status-mode 'magit-bookmark-variables nil) + +(put 'magit-refs-mode 'magit-bookmark-variables + '(magit-buffer-upstream + magit-buffer-arguments)) + +(put 'magit-stashes-mode 'magit-bookmark-variables nil) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-stashes-mode)) + (format "magit-states(%s)" magit-buffer-refname)) + +;;; _ +(provide 'magit-bookmark) +;;; magit-bookmark.el ends here diff --git a/elpa/magit-20190122.503/magit-branch.el b/elpa/magit-20190514.1814/magit-branch.el similarity index 61% rename from elpa/magit-20190122.503/magit-branch.el rename to elpa/magit-20190514.1814/magit-branch.el index d9e5010b..3385a129 100644 --- a/elpa/magit-20190122.503/magit-branch.el +++ b/elpa/magit-20190514.1814/magit-branch.el @@ -23,11 +23,11 @@ ;;; Commentary: -;; This library implements support for branches. It defines popups -;; and commands for creating, checking out, manipulating, and -;; configuring branches. Commands defined here are mainly concerned -;; with branches as pointers, commands that deal with what a branch -;; points at, are defined elsewhere. +;; This library implements support for branches. It defines commands +;; for creating, checking out, manipulating, and configuring branches. +;; Commands defined here are mainly concerned with branches as +;; pointers, commands that deal with what a branch points at, are +;; defined elsewhere. ;;; Code: @@ -183,12 +183,11 @@ Another supported but obsolete value is `github-only'. It is a (const :tag "... and rename corresponding branch on remote" t) (const :tag "... but only if remote is on a forge" forge-only))) -(defcustom magit-branch-popup-show-variables t - "Whether the `magit-branch-popup' shows Git variables. -This defaults to t to avoid changing key bindings. When set to -nil, no variables are displayed directly in this popup, instead -the sub-popup `magit-branch-config-popup' has to be used to view -and change branch related variables." +(defcustom magit-branch-direct-configure t + "Whether the command `magit-branch' shows Git variables. +When set to nil, no variables are displayed by this transient +command, instead the sub-transient `magit-branch-configure' +has to be used to view and change branch related variables." :package-version '(magit . "2.7.0") :group 'magit-commands :type 'boolean) @@ -199,40 +198,39 @@ and change branch related variables." :group 'magit-commands :type '(repeat string)) -;;; Branch Popup +;;; Commands -(defvar magit-branch-config-variables) - -;;;###autoload (autoload 'magit-branch-popup "magit" nil t) -(magit-define-popup magit-branch-popup - "Popup console for branch commands." +;;;###autoload (autoload 'magit-branch "magit" nil t) +(define-transient-command magit-branch (branch) + "Add, configure or remove a branch." :man-page "git-branch" - :variables (lambda () - (and magit-branch-popup-show-variables - magit-branch-config-variables)) - :actions '((?b "Checkout" magit-checkout) nil - (?C "Configure..." magit-branch-config-popup) - (?l "Checkout local branch" magit-branch-checkout) - (?s "Create new spin-off" magit-branch-spinoff) - (?m "Rename" magit-branch-rename) - (?c "Checkout new branch" magit-branch-and-checkout) - (?n "Create new branch" magit-branch-create) - (?x "Reset" magit-branch-reset) - (?w "Checkout new worktree" magit-worktree-checkout) - (?W "Create new worktree" magit-worktree-branch) - (?k "Delete" magit-branch-delete)) - :default-action 'magit-checkout - :max-action-columns 3 - :setup-function 'magit-branch-popup-setup) - -(defun magit-branch-popup-setup (val def) - (magit-popup-default-setup val def) - (use-local-map (copy-keymap magit-popup-mode-map)) - (dolist (ev (-filter #'magit-popup-event-p (magit-popup-get :variables))) - (local-set-key (vector (magit-popup-event-key ev)) - 'magit-invoke-popup-action))) - -;;; Branch Commands + ["Variables" + :if (lambda () + (and magit-branch-direct-configure + (oref transient--prefix scope))) + ("d" magit-branch..description) + ("u" magit-branch..merge/remote) + ("r" magit-branch..rebase) + ("p" magit-branch..pushRemote)] + [["Checkout" + ("b" "branch/revision" magit-checkout) + ("l" "local branch" magit-branch-checkout) + (6 "o" "new orphan" magit-branch-orphan)] + ["" + ("c" "new branch" magit-branch-and-checkout) + ("s" "new spin-off" magit-branch-spinoff) + (5 "w" "new worktree" magit-worktree-checkout)] + ["Create" + ("n" "new branch" magit-branch-create) + ("S" "new spin-out" magit-branch-spinout) + (5 "W" "new worktree" magit-worktree-branch)] + ["Do" + ("C" "configure..." magit-branch-configure) + ("m" "rename" magit-branch-rename) + ("x" "reset" magit-branch-reset) + ("k" "delete" magit-branch-delete)]] + (interactive (list (magit-get-current-branch))) + (transient-setup 'magit-branch nil nil :scope branch)) ;;;###autoload (defun magit-checkout (revision) @@ -248,22 +246,20 @@ changes. (magit-run-git "checkout" revision)) ;;;###autoload -(defun magit-branch-create (branch start-point &optional args) - "Create BRANCH at branch or revision START-POINT. -\n(git branch [ARGS] BRANCH START-POINT)." +(defun magit-branch-create (branch start-point) + "Create BRANCH at branch or revision START-POINT." (interactive (magit-branch-read-args "Create branch")) - (magit-call-git "branch" args branch start-point) + (magit-call-git "branch" branch start-point) (magit-branch-maybe-adjust-upstream branch start-point) (magit-refresh)) ;;;###autoload -(defun magit-branch-and-checkout (branch start-point &optional args) - "Create and checkout BRANCH at branch or revision START-POINT. -\n(git checkout [ARGS] -b BRANCH START-POINT)." +(defun magit-branch-and-checkout (branch start-point) + "Create and checkout BRANCH at branch or revision START-POINT." (interactive (magit-branch-read-args "Create and checkout branch")) (if (string-match-p "^stash@{[0-9]+}$" start-point) (magit-run-git "stash" "branch" branch start-point) - (magit-call-git "checkout" args "-b" branch start-point) + (magit-call-git "checkout" "-b" branch start-point) (magit-branch-maybe-adjust-upstream branch start-point) (magit-refresh))) @@ -287,7 +283,7 @@ does." (when (string-match "\\`heads/\\(.+\\)" arg) (setq arg (match-string 1 arg))) (if start-point - (magit-branch-and-checkout arg start-point (magit-branch-arguments)) + (magit-branch-and-checkout arg start-point) (magit-checkout arg))) ;;;###autoload @@ -343,7 +339,7 @@ when using `magit-branch-and-checkout'." (magit-checkout branch) (when (magit-anything-modified-p) (user-error "Cannot checkout when there are uncommitted changes")) - (magit-branch-and-checkout branch start-point (magit-branch-arguments)) + (magit-branch-and-checkout branch start-point) (when (magit-remote-branch-p start-point) (pcase-let ((`(,remote . ,remote-branch) (magit-split-branch-name start-point))) @@ -364,38 +360,45 @@ when using `magit-branch-and-checkout'." (magit-call-git "branch" (concat "--set-upstream-to=" it) branch))) ;;;###autoload -(defun magit-branch-orphan (branch start-point &optional args) - "Create and checkout an orphan BRANCH with contents from revision START-POINT. -\n(git checkout --orphan [ARGS] BRANCH START-POINT)." +(defun magit-branch-orphan (branch start-point) + "Create and checkout an orphan BRANCH with contents from revision START-POINT." (interactive (magit-branch-read-args "Create and checkout orphan branch")) - (magit-run-git "checkout" "--orphan" args branch start-point)) - -(defun magit-branch-read-args (prompt) - (let ((args (magit-branch-arguments))) - (if magit-branch-read-upstream-first - (let ((choice (magit-read-starting-point prompt))) - (if (magit-rev-verify choice) - (list (magit-read-string-ns - (if magit-completing-read--silent-default - (format "%s (starting at `%s')" prompt choice) - "Name for new branch") - (let ((def (mapconcat #'identity - (cdr (split-string choice "/")) - "/"))) - (and (member choice (magit-list-remote-branch-names)) - (not (member def (magit-list-local-branch-names))) - def))) - choice args) - (if (eq magit-branch-read-upstream-first 'fallback) - (list choice (magit-read-starting-point prompt choice) args) - (user-error "Not a valid starting-point: %s" choice)))) - (let ((branch (magit-read-string-ns (concat prompt " named")))) - (list branch - (magit-read-starting-point prompt branch) - args))))) + (magit-run-git "checkout" "--orphan" branch start-point)) + +(defun magit-branch-read-args (prompt &optional default-start) + (if magit-branch-read-upstream-first + (let ((choice (magit-read-starting-point prompt nil default-start))) + (if (magit-rev-verify choice) + (list (magit-read-string-ns + (if magit-completing-read--silent-default + (format "%s (starting at `%s')" prompt choice) + "Name for new branch") + (let ((def (mapconcat #'identity + (cdr (split-string choice "/")) + "/"))) + (and (member choice (magit-list-remote-branch-names)) + (not (member def (magit-list-local-branch-names))) + def))) + choice) + (if (eq magit-branch-read-upstream-first 'fallback) + (list choice + (magit-read-starting-point prompt choice default-start)) + (user-error "Not a valid starting-point: %s" choice)))) + (let ((branch (magit-read-string-ns (concat prompt " named")))) + (list branch (magit-read-starting-point prompt branch default-start))))) + +;;;###autoload +(defun magit-branch-spinout (branch &optional from) + "Create new branch from the unpushed commits. +Like `magit-branch-spinoff' but remain on the current branch. +If there are any uncommitted changes, then behave exactly like +`magit-branch-spinoff'." + (interactive (list (magit-read-string-ns "Spin out branch") + (car (last (magit-region-values 'commit))))) + (magit--branch-spinoff branch from nil)) ;;;###autoload -(defun magit-branch-spinoff (branch &optional from &rest args) +(defun magit-branch-spinoff (branch &optional from) "Create new branch from the unpushed commits. Create and checkout a new branch starting at and tracking the @@ -425,10 +428,16 @@ matter, all commits between FROM and `HEAD' are moved to the new branch. If FROM is not reachable from `HEAD' or is reachable from the source branch's upstream, then an error is raised." (interactive (list (magit-read-string-ns "Spin off branch") - (car (last (magit-region-values 'commit))) - (magit-branch-arguments))) + (car (last (magit-region-values 'commit))))) + (magit--branch-spinoff branch from t)) + +(defun magit--branch-spinoff (branch from checkout) (when (magit-branch-p branch) (user-error "Cannot spin off %s. It already exists" branch)) + (when (and (not checkout) + (magit-anything-modified-p)) + (message "Staying on HEAD due to uncommitted changes") + (setq checkout t)) (if-let ((current (magit-get-current-branch))) (let ((tracked (magit-get-upstream-branch current)) base) @@ -441,7 +450,9 @@ from the source branch's upstream, then an error is raised." (user-error "Cannot spin off %s. %s is ancestor of upstream %s" branch from tracked))) (let ((magit-process-raise-error t)) - (magit-call-git "checkout" args "-b" branch current)) + (if checkout + (magit-call-git "checkout" "-b" branch current) + (magit-call-git "branch" branch current))) (--when-let (magit-get-indirect-upstream-branch current) (magit-call-git "branch" "--set-upstream-to" it branch)) (when (and tracked @@ -450,14 +461,18 @@ from the source branch's upstream, then an error is raised." (concat from "^") (magit-git-string "merge-base" current tracked))) (not (magit-rev-eq base current))) - (magit-call-git "update-ref" "-m" - (format "reset: moving to %s" base) - (concat "refs/heads/" current) base)) - (magit-refresh)) - (magit-run-git "checkout" "-b" branch))) + (if checkout + (magit-call-git "update-ref" "-m" + (format "reset: moving to %s" base) + (concat "refs/heads/" current) base) + (magit-call-git "reset" "--hard" base)))) + (if checkout + (magit-call-git "checkout" "-b" branch) + (magit-call-git "branch" branch))) + (magit-refresh)) ;;;###autoload -(defun magit-branch-reset (branch to &optional args set-upstream) +(defun magit-branch-reset (branch to &optional set-upstream) "Reset a branch to the tip of another branch or any other commit. When the branch being reset is the current branch, then do a @@ -479,18 +494,23 @@ that is being reset." nil nil nil 'magit-revision-history (or (and (not (equal branch atpoint)) atpoint) (magit-get-upstream-branch branch))) - (magit-branch-arguments) current-prefix-arg))) - (unless (member "--force" args) - (setq args (cons "--force" args))) - (if (equal branch (magit-get-current-branch)) - (if (and (magit-anything-modified-p) - (not (yes-or-no-p "Uncommitted changes will be lost. Proceed? "))) - (user-error "Abort") - (magit-reset-hard to) - (when (and set-upstream (magit-branch-p to)) - (magit-set-upstream-branch branch to))) - (magit-branch-create branch to args))) + (let ((inhibit-magit-refresh t)) + (if (equal branch (magit-get-current-branch)) + (if (and (magit-anything-modified-p) + (not (yes-or-no-p + "Uncommitted changes will be lost. Proceed? "))) + (user-error "Abort") + (magit-reset-hard to)) + (magit-call-git "update-ref" + "-m" (format "reset: moving to %s" to) + (magit-git-string "rev-parse" "--symbolic-full-name" + branch) + to)) + (when (and set-upstream (magit-branch-p to)) + (magit-set-upstream-branch branch to) + (magit-branch-maybe-adjust-upstream branch to))) + (magit-refresh)) ;;;###autoload (defun magit-branch-delete (branches &optional force) @@ -542,7 +562,7 @@ defaulting to the branch at point." ;; If that is not the case, then this deletes the tracking branches. (set-process-sentinel magit-this-process - (apply-partially 'magit-delete-remote-branch-sentinel refs)))) + (apply-partially 'magit-delete-remote-branch-sentinel remote refs)))) ((> (length branches) 1) (setq branches (delete (magit-get-current-branch) branches)) (mapc 'magit-branch-maybe-delete-pr-remote branches) @@ -603,30 +623,35 @@ defaulting to the branch at point." (if (and (= (length refspecs) 1) (magit-confirm 'delete-pr-remote (format "Also delete remote %s (%s)" remote - "no pull-request branch remains"))) + "no pull-request branch remains") + nil t)) (magit-call-git "remote" "rm" remote) - (magit-call-git "config" "--unset" variable - (regexp-quote refspec))))))))) + (magit-call-git "config" "--unset-all" variable + (format "^%s$" (regexp-quote refspec)))))))))) (defun magit-branch-unset-pushRemote (branch) (magit-set nil "branch" branch "pushRemote")) -(defun magit-delete-remote-branch-sentinel (refs process event) +(defun magit-delete-remote-branch-sentinel (remote refs process event) (when (memq (process-status process) '(exit signal)) - (if (= (process-exit-status process) 0) - (magit-process-sentinel process event) - (if-let ((rest (-filter #'magit-ref-exists-p refs))) - (progn - (process-put process 'inhibit-refresh t) - (magit-process-sentinel process event) - (setq magit-this-error nil) - (message "Some remote branches no longer exist. %s" - "Deleting just the local tracking refs instead...") - (dolist (ref rest) - (magit-call-git "update-ref" "-d" ref)) - (magit-refresh) - (message "Deleting local remote-tracking refs...done")) - (magit-process-sentinel process event))))) + (if (= (process-exit-status process) 1) + (if-let ((on-remote (--map (concat "refs/remotes/" remote "/" it) + (magit-remote-list-branches remote))) + (rest (--filter (and (not (member it on-remote)) + (magit-ref-exists-p it)) + refs))) + (progn + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (setq magit-this-error nil) + (message "Some remote branches no longer exist. %s" + "Deleting just the local tracking refs instead...") + (dolist (ref rest) + (magit-call-git "update-ref" "-d" ref)) + (magit-refresh) + (message "Deleting local remote-tracking refs...done")) + (magit-process-sentinel process event)) + (magit-process-sentinel process event)))) ;;;###autoload (defun magit-branch-rename (old new &optional force) @@ -674,7 +699,7 @@ the remote." (remote (magit-get-push-remote new))) (when (and old-target (not new-target) - (magit-y-or-n-p (format "Also rename %S to %S on %S" + (magit-y-or-n-p (format "Also rename %S to %S on \"%s\"" old new remote))) ;; Rename on (i.e. within) the remote, but only if the ;; destination ref doesn't exist yet. If that ref already @@ -725,290 +750,134 @@ and also rename the respective reflog file." (make-directory (file-name-directory new) t) (rename-file old new t)))) -;;; Config Popup - -(defvar magit-branch-config-branch nil) +;;; Configure -;;;###autoload -(defun magit-branch-config-popup (branch) - "Popup console for setting branch variables." +;;;###autoload (autoload 'magit-branch-configure "magit-branch" nil t) +(define-transient-command magit-branch-configure (branch) + "Configure a branch." + :man-page "git-branch" + [:description + (lambda () + (concat + (propertize "Configure " 'face 'transient-heading) + (propertize (oref transient--prefix scope) 'face 'magit-branch-local))) + ("d" magit-branch..description) + ("u" magit-branch..merge/remote) + ("r" magit-branch..rebase) + ("p" magit-branch..pushRemote)] + ["Configure repository defaults" + ("R" magit-pull.rebase) + ("P" magit-remote.pushDefault)] + ["Configure branch creation" + ("a m" magit-branch.autoSetupMerge) + ("a r" magit-branch.autoSetupRebase)] (interactive - (list (if (or current-prefix-arg - (and (eq magit-current-popup 'magit-branch-popup) - magit-branch-popup-show-variables)) - (magit-read-local-branch "Configure branch") - (magit-get-current-branch)))) - (let ((magit-branch-config-branch branch)) - (magit-invoke-popup 'magit-branch-config-popup nil nil))) - -(defvar magit-branch-config-variables - '((lambda () - (concat - (propertize "Configure " 'face 'magit-popup-heading) - (propertize (magit-branch-config-branch) 'face 'magit-branch-local))) - (?d "branch.%s.description" - magit-edit-branch*description - magit-format-branch*description) - (?u "branch.%s.merge" - magit-set-branch*merge/remote - magit-format-branch*merge/remote) - (?r "branch.%s.rebase" - magit-cycle-branch*rebase - magit-format-branch*rebase) - (?p "branch.%s.pushRemote" - magit-cycle-branch*pushRemote - magit-format-branch*pushRemote) - "Configure repository defaults" - (?\M-r "pull.rebase" - magit-cycle-pull.rebase - magit-format-pull.rebase) - (?\M-p "remote.pushDefault" - magit-cycle-remote.pushDefault - magit-format-remote.pushDefault) - "Configure branch creation" - (?U "branch.autoSetupMerge" - magit-cycle-branch*autoSetupMerge - magit-format-branch*autoSetupMerge) - (?R "branch.autoSetupRebase" - magit-cycle-branch*autoSetupRebase - magit-format-branch*autoSetupRebase))) - -(defvar magit-branch-config-popup - `(:man-page "git-branch" - :variables ,magit-branch-config-variables - :setup-function magit-branch-config-popup-setup)) - -(defun magit-branch-config-popup-setup (val def) - (magit-popup-default-setup val def) - (setq-local magit-branch-config-branch magit-branch-config-branch) - (use-local-map (copy-keymap magit-popup-mode-map)) - (dolist (ev (-filter #'magit-popup-event-p (magit-popup-get :variables))) - (local-set-key (vector (magit-popup-event-key ev)) - 'magit-invoke-popup-action))) - -(defun magit-branch-config-branch (&optional prompt) - (if prompt - (or (and (not current-prefix-arg) - (or magit-branch-config-branch - (magit-get-current-branch))) - (magit-read-local-branch prompt)) - (or magit-branch-config-branch - (magit-get-current-branch) - ""))) - -;;; Config Commands and Inserters - -;;;###autoload -(defun magit-edit-branch*description (branch) - "Edit the description of the current branch. -With a prefix argument edit the description of another branch. - -The description for the branch named NAME is stored in the Git -variable `branch..description'." - (interactive (list (magit-branch-config-branch "Edit branch description"))) + (list (or (and (not current-prefix-arg) + (not (and magit-branch-direct-configure + (eq current-transient-command 'magit-branch))) + (magit-get-current-branch)) + (magit--read-remote-scope)))) + (transient-setup 'magit-branch-configure nil nil :scope branch)) + +(defun magit--read-branch-scope (&optional obj) + (magit-read-local-branch + (if obj + (format "Set %s for branch" + (format (oref obj variable) "")) + "Configure branch"))) + +(define-suffix-command magit-branch..description (branch) + "Edit the description of BRANCH." + :class 'magit--git-variable + :transient nil + :variable "branch.%s.description" + (interactive (list (oref current-transient-prefix scope))) (magit-run-git-with-editor "branch" "--edit-description" branch)) -(defun magit-edit-branch*description-check-buffers () - (and buffer-file-name - (string-match-p "/\\(BRANCH\\|EDIT\\)_DESCRIPTION\\'" buffer-file-name) - (add-hook 'with-editor-post-finish-hook - (lambda () - (when (derived-mode-p 'magit-popup-mode) - (magit-refresh-popup-buffer))) - nil t))) - -(add-hook 'find-file-hook 'magit-edit-branch*description-check-buffers) - -(defun magit-format-branch*description () - (let* ((branch (magit-branch-config-branch)) - (width (+ (length branch) 19)) - (var (format "branch.%s.description" branch))) - (concat var " " (make-string (- width (length var)) ?\s) - (if-let ((value (magit-get var))) - (propertize (car (split-string value "\n")) - 'face 'magit-popup-option-value) - (propertize "unset" 'face 'magit-popup-disabled-argument))))) +(add-hook 'find-file-hook 'magit-branch-description-check-buffers) -;;;###autoload -(defun magit-set-branch*merge/remote (branch upstream) - "Set or unset the upstream of the current branch. -With a prefix argument do so for another branch. - -When the branch in question already has an upstream then simply -unsets it. Invoke this command again to set another upstream. - -Together the Git variables `branch..remote' and -`branch..merge' define the upstream branch of the local -branch named NAME. The value of `branch..remote' is the -name of the upstream remote. The value of `branch..merge' -is the full reference of the upstream branch, on the remote. - -Non-interactively, when UPSTREAM is non-nil, then always set it -as the new upstream, regardless of whether another upstream was -already set. When nil, then always unset." - (interactive - (let ((branch (magit-branch-config-branch "Change upstream of branch"))) - (list branch (and (not (magit-get-upstream-branch branch)) - (magit-read-upstream-branch branch))))) - (magit-set-upstream-branch branch upstream) +(defun magit-branch-description-check-buffers () + (and buffer-file-name + (string-match-p "/\\(BRANCH\\|EDIT\\)_DESCRIPTION\\'" buffer-file-name))) + +(defclass magit--git-branch:upstream (magit--git-variable) + ((format :initform " %k %m %M\n %r %R"))) + +(define-infix-command magit-branch..merge/remote () + :class 'magit--git-branch:upstream) + +(cl-defmethod transient-init-value ((obj magit--git-branch:upstream)) + (when-let ((branch (oref transient--prefix scope)) + (remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (oset obj value (list remote merge)))) + +(cl-defmethod transient-infix-read ((obj magit--git-branch:upstream)) + (if (oref obj value) + (oset obj value nil) + (magit-read-upstream-branch (oref transient--prefix scope) "Upstream"))) + +(cl-defmethod transient-infix-set ((obj magit--git-branch:upstream) refname) + (magit-set-upstream-branch (oref transient--prefix scope) refname) + (oset obj value + (let ((branch (oref transient--prefix scope))) + (when-let ((r (magit-get "branch" branch "remote")) + (m (magit-get "branch" branch "merge"))) + (list r m)))) (magit-refresh)) -(defun magit-format-branch*merge/remote () - (let* ((branch (magit-branch-config-branch)) - (width (+ (length branch) 20)) - (varM (format "branch.%s.merge" branch)) - (varR (format "branch.%s.remote" branch)) - (face (if (equal (magit-get varR) ".") - 'magit-branch-local - 'magit-branch-remote))) - (concat varM (make-string (- width (length varM)) ?\s) - (if-let ((value (magit-get varM))) - (propertize value 'face face) - (propertize "unset" 'face 'magit-popup-disabled-argument)) - "\n " varR (make-string (- width (length varR)) ?\s) - (if-let ((value (magit-get varR))) - (propertize value 'face face) - (propertize "unset" 'face 'magit-popup-disabled-argument))))) - -;;;###autoload -(defun magit-cycle-branch*rebase (branch) - "Cycle the value of `branch..rebase' for the current branch. -With a prefix argument cycle the value for another branch. - -The Git variables `branch..rebase' controls whether pulling -into the branch named NAME is done by rebasing that branch onto -the fetched branch or by merging that branch. - -When `true' then pulling is done by rebasing. -When `false' then pulling is done by merging. - -When that variable is undefined then the value of `pull.rebase' -is used instead. It defaults to `false'." - (interactive (list (magit-branch-config-branch - "Cycle branch..rebase for"))) - (magit--set-popup-variable (format "branch.%s.rebase" branch) - '("true" "false") - "false" "pull.rebase")) - -(defun magit-format-branch*rebase () - (let ((branch (magit-branch-config-branch))) - (magit--format-popup-variable:choices - (format "branch.%s.rebase" branch) - '("true" "false") - "false" "pull.rebase" - (+ (length branch) 20)))) - -;;;###autoload -(defun magit-cycle-branch*pushRemote (branch) - "Cycle the value of `branch..pushRemote' for the current branch. -With a prefix argument cycle the value for another branch. - -The Git variable `branch..pushRemote' specifies the remote -that the branch named NAME is usually pushed to. The value has -to be the name of an existing remote. - -If that variable is undefined, then the value of the Git variable -`remote.pushDefault' is used instead, provided that it is defined, -which by default it is not." - (interactive (list (magit-branch-config-branch - "Cycle branch..pushRemote for"))) - (magit--set-popup-variable (format "branch.%s.pushRemote" branch) - (magit-list-remotes) - "remote.pushDefault")) - -(defun magit-format-branch*pushRemote () - (let ((branch (magit-branch-config-branch))) - (magit--format-popup-variable:choices - (format "branch.%s.pushRemote" branch) - (magit-list-remotes) - nil "remote.pushDefault" - (+ (length branch) 20)))) - -;;;###autoload -(defun magit-cycle-pull.rebase () - "Cycle the repository-local value of `pull.rebase'. - -The Git variable `pull.rebase' specifies whether pulling is done -by rebasing or by merging. It can be overwritten using the Git -variable `branch..rebase'. - -When `true' then pulling is done by rebasing. -When `false' (the default) then pulling is done by merging." - (interactive) - (magit--set-popup-variable "pull.rebase" '("true" "false") "false")) - -(defun magit-format-pull.rebase () - (magit--format-popup-variable:choices - "pull.rebase" '("true" "false") "false" nil 19)) - -;;;###autoload -(defun magit-cycle-remote.pushDefault () - "Cycle the repository-local value of `remote.pushDefault'. - -The Git variable `remote.pushDefault' specifies the remote that -local branches are usually pushed to. It can be overwritten -using the Git variable `branch..pushRemote'." - (interactive) - (magit--set-popup-variable "remote.pushDefault" (magit-list-remotes))) - -(defun magit-format-remote.pushDefault () - (magit--format-popup-variable:choices - "remote.pushDefault" (magit-list-remotes) nil nil 19)) - -;;;###autoload -(defun magit-cycle-branch*autoSetupMerge () - "Cycle the repository-local value of `branch.autoSetupMerge'. - -The Git variable `branch.autoSetupMerge' under what circumstances -creating a branch (named NAME) should result in the variables -`branch..merge' and `branch..remote' being set -according to the starting point used to create the branch. If -the starting point isn't a branch, then these variables are never -set. - -When `always' then the variables are set regardless of whether -the starting point is a local or a remote branch. - -When `true' (the default) then the variable are set when the -starting point is a remote branch, but not when it is a local -branch. - -When `false' then the variables are never set." - (interactive) - (magit--set-popup-variable "branch.autoSetupMerge" - '("always" "true" "false") "true")) - -(defun magit-format-branch*autoSetupMerge () - (magit--format-popup-variable:choices - "branch.autoSetupMerge" '("always" "true" "false") "true" nil 23)) - -;;;###autoload -(defun magit-cycle-branch*autoSetupRebase () - "Cycle the repository-local value of `branch.autoSetupRebase'. - -The Git variable `branch.autoSetupRebase' specifies whether -creating a branch (named NAME) should result in the variable -`branch..rebase' being set to `true'. - -When `always' then the variable is set regardless of whether the -starting point is a local or a remote branch. - -When `local' then the variable are set when the starting point -is a local branch, but not when it is a remote branch. - -When `remote' then the variable are set when the starting point -is a remote branch, but not when it is a local branch. - -When `never' (the default) then the variable is never set." - (interactive) - (magit--set-popup-variable "branch.autoSetupRebase" - '("always" "local" "remote" "never") "never")) - -(defun magit-format-branch*autoSetupRebase () - (magit--format-popup-variable:choices - "branch.autoSetupRebase" - '("always" "local" "remote" "never") - "never" nil 23)) +(cl-defmethod transient-format ((obj magit--git-branch:upstream)) + (let ((branch (oref transient--prefix scope))) + (format-spec + (oref obj format) + `((?k . ,(transient-format-key obj)) + (?r . ,(format "branch.%s.remote" branch)) + (?m . ,(format "branch.%s.merge" branch)) + (?R . ,(transient-format-value obj #'car)) + (?M . ,(transient-format-value obj #'cadr)))))) + +(cl-defmethod transient-format-value ((obj magit--git-branch:upstream) key) + (if-let ((value (funcall key (oref obj value)))) + (propertize value 'face 'transient-argument) + (propertize "unset" 'face 'transient-inactive-argument))) + +(define-infix-command magit-branch..rebase () + :class 'magit--git-variable:choices + :scope 'magit--read-branch-scope + :variable "branch.%s.rebase" + :fallback "pull.rebase" + :choices '("true" "false") + :default "false") + +(define-infix-command magit-branch..pushRemote () + :class 'magit--git-variable:choices + :scope 'magit--read-branch-scope + :variable "branch.%s.pushRemote" + :fallback "remote.pushDefault" + :choices 'magit-list-remotes) + +(define-infix-command magit-pull.rebase () + :class 'magit--git-variable:choices + :variable "pull.rebase" + :choices '("true" "false") + :default "false") + +(define-infix-command magit-remote.pushDefault () + :class 'magit--git-variable:choices + :variable "remote.pushDefault" + :choices 'magit-list-remotes) + +(define-infix-command magit-branch.autoSetupMerge () + :class 'magit--git-variable:choices + :variable "branch.autoSetupMerge" + :choices '("always" "true" "false") + :default "true") + +(define-infix-command magit-branch.autoSetupRebase () + :class 'magit--git-variable:choices + :variable "branch.autoSetupRebase" + :choices '("always" "local" "remote" "never") + :default "never") ;;; _ (provide 'magit-branch) diff --git a/elpa/magit-20190514.1814/magit-clone.el b/elpa/magit-20190514.1814/magit-clone.el new file mode 100644 index 00000000..a4128940 --- /dev/null +++ b/elpa/magit-20190514.1814/magit-clone.el @@ -0,0 +1,267 @@ +;;; magit-clone.el --- clone a repository -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; 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. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements clone commands. + +;;; Code: + +(require 'magit) + +;;; Options + +(defcustom magit-clone-set-remote-head nil + "Whether cloning creates the symbolic-ref `/HEAD'." + :package-version '(magit . "2.4.2") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-clone-set-remote.pushDefault 'ask + "Whether to set the value of `remote.pushDefault' after cloning. + +If t, then set without asking. If nil, then don't set. If +`ask', then ask." + :package-version '(magit . "2.4.0") + :group 'magit-commands + :type '(choice (const :tag "set" t) + (const :tag "ask" ask) + (const :tag "don't set" nil))) + +(defcustom magit-clone-default-directory nil + "Default directory to use when `magit-clone' reads destination. +If nil (the default), then use the value of `default-directory'. +If a directory, then use that. If a function, then call that +with the remote url as only argument and use the returned value." + :package-version '(magit . "2.90.0") + :group 'magit-commands + :type '(choice (const :tag "value of default-directory") + (directory :tag "constant directory") + (function :tag "function's value"))) + +(defcustom magit-clone-always-transient nil + "Whether `magit-clone' always acts as a transient prefix command. +If nil, then a prefix argument has to be used to show the transient +popup instead of invoking the default suffix `magit-clone-regular' +directly." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-clone-name-alist + '(("\\`\\(?:github:\\|gh:\\)?\\([^:]+\\)\\'" "github.com" "github.user") + ("\\`\\(?:gitlab:\\|gl:\\)\\([^:]+\\)\\'" "gitlab.com" "gitlab.user")) + "Alist mapping repository names to repository urls. + +Each element has the form (REGEXP HOSTNAME USER). When the user +enters a name when a cloning command asks for a name or url, then +that is looked up in this list. The first element whose REGEXP +matches is used. + +The format specified by option `magit-clone-url-format' is used +to turn the name into an url, using HOSTNAME and the repository +name. If the provided name contains a slash, then that is used. +Otherwise if the name omits the owner of the repository, then the +default user specified in the matched entry is used. + +If USER contains a dot, then it is treated as a Git variable and +the value of that is used as the username. Otherwise it is used +as the username itself." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type '(repeat (list regexp + (string :tag "hostname") + (string :tag "user name or git variable")))) + +(defcustom magit-clone-url-format "git@%h:%n.git" + "Format used when turning repository names into urls. +%h is the hostname and %n is the repository name, including +the name of the owner. Also see `magit-clone-name-alist'." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'regexp) + +;;; Commands + +;;;###autoload (autoload 'magit-clone "magit-clone" nil t) +(define-transient-command magit-clone (&optional transient) + "Clone a repository." + :man-page "git-clone" + ["Fetch arguments" + ("-B" "Clone a single branch" "--single-branch") + ("-n" "Do not clone tags" "--no-tags") + ("-S" "Clones submodules" "--recurse-submodules" :level 6) + ("-l" "Do not optimize" "--no-local" :level 7)] + ["Setup arguments" + ("-o" "Set name of remote" ("-o" "--origin=")) + ("-b" "Set HEAD branch" ("-b" "--branch=")) + ("-g" "Separate git directory" "--separate-git-dir=" + transient-read-directory :level 7) + ("-t" "Use template directory" "--template=" + transient-read-existing-directory :level 6)] + ["Local sharing arguments" + ("-s" "Share objects" ("-s" "--shared" :level 7)) + ("-h" "Do not use hardlinks" "--no-hardlinks")] + ["Clone" + ("C" "regular" magit-clone-regular) + ("s" "shallow" magit-clone-shallow) + ("d" "shallow since date" magit-clone-shallow-since :level 7) + ("e" "shallow excluding" magit-clone-shallow-exclude :level 7) + ("b" "bare" magit-clone-bare) + ("m" "mirror" magit-clone-mirror)] + (interactive (list (or magit-clone-always-transient current-prefix-arg))) + (if transient + (transient-setup #'magit-clone) + (call-interactively #'magit-clone-regular))) + +;;;###autoload +(defun magit-clone-regular (repository directory args) + "Create a clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository." + (interactive (magit-clone-read-args)) + (magit-clone-internal repository directory args)) + +;;;###autoload +(defun magit-clone-shallow (repository directory args depth) + "Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +With a prefix argument read the DEPTH of the clone; +otherwise use 1." + (interactive (append (magit-clone-read-args) + (list (if current-prefix-arg + (read-number "Depth: " 1) + 1)))) + (magit-clone-internal repository directory + (cons (format "--depth=%s" depth) args))) + +;;;###autoload +(defun magit-clone-shallow-since (repository directory args date) + "Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +Exclude commits before DATE, which is read from the +user." + (interactive (append (magit-clone-read-args) + (list (transient-read-date "Exclude commits before: " + nil nil)))) + (magit-clone-internal repository directory + (cons (format "--shallow-since=%s" date) args))) + +;;;###autoload +(defun magit-clone-shallow-exclude (repository directory args exclude) + "Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +Exclude commits reachable from EXCLUDE, which is a +branch or tag read from the user." + (interactive (append (magit-clone-read-args) + (list (read-string "Exclude commits reachable from: ")))) + (magit-clone-internal repository directory + (cons (format "--shallow-exclude=%s" exclude) args))) + +;;;###autoload +(defun magit-clone-bare (repository directory args) + "Create a bare clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository." + (interactive (magit-clone-read-args)) + (magit-clone-internal repository directory (cons "--bare" args))) + +;;;###autoload +(defun magit-clone-mirror (repository directory args) + "Create a mirror of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository." + (interactive (magit-clone-read-args)) + (magit-clone-internal repository directory (cons "--mirror" args))) + +(defun magit-clone-internal (repository directory args) + (run-hooks 'magit-credential-hook) + (setq directory (file-name-as-directory (expand-file-name directory))) + (magit-run-git-async "clone" args "--" repository + (magit-convert-filename-for-git directory)) + ;; Don't refresh the buffer we're calling from. + (process-put magit-this-process 'inhibit-refresh t) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (let ((magit-process-raise-error t)) + (magit-process-sentinel process event))) + (when (and (eq (process-status process) 'exit) + (= (process-exit-status process) 0)) + (unless (memq (car args) '("--bare" "--mirror")) + (let ((default-directory directory)) + (when (or (eq magit-clone-set-remote.pushDefault t) + (and magit-clone-set-remote.pushDefault + (y-or-n-p "Set `remote.pushDefault' to \"origin\"? "))) + (setf (magit-get "remote.pushDefault") "origin")) + (unless magit-clone-set-remote-head + (magit-remote-unset-head "origin")))) + (with-current-buffer (process-get process 'command-buf) + (magit-status-setup-buffer directory)))))) + +(defun magit-clone-read-args () + (let ((repo (magit-clone-read-repository))) + (list repo + (read-directory-name + "Clone to: " + (if (functionp magit-clone-default-directory) + (funcall magit-clone-default-directory repo) + magit-clone-default-directory) + nil nil + (and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" repo) + (match-string 1 repo))) + (transient-args 'magit-clone)))) + +(defun magit-clone-read-repository () + (magit-read-char-case "Clone from " nil + (?u "[u]rl or name" + (let ((str (magit-read-string-ns "Clone from url or name"))) + (if (string-match-p "\\(://\\|@\\)" str) + str + (magit-clone--name-to-url str)))) + (?p "[p]ath" + (read-directory-name "Clone repository: ")) + (?l "or [l]ocal url" + (concat "file://" (read-directory-name "Clone repository: file://"))))) + +(defun magit-clone--name-to-url (name) + (or (-some + (pcase-lambda (`(,re ,host ,user)) + (and (string-match re name) + (let ((repo (match-string 1 name))) + (format-spec + magit-clone-url-format + `((?h . ,host) + (?n . ,(if (string-match-p "/" repo) + repo + (if (string-match-p "\\." user) + (if-let ((user (magit-get user))) + (concat user "/" repo) + (user-error + "Set %S or specify owner explicitly" user)) + (concat user "/" repo))))))))) + magit-clone-name-alist) + (user-error "Not an url and no matching entry in `%s'" + 'magit-clone-name-alist))) + +;;; _ +(provide 'magit-clone) +;;; magit-clone.el ends here diff --git a/elpa/magit-20190122.503/magit-commit.el b/elpa/magit-20190514.1814/magit-commit.el similarity index 79% rename from elpa/magit-20190122.503/magit-commit.el rename to elpa/magit-20190514.1814/magit-commit.el index f47015e1..34c3fc51 100644 --- a/elpa/magit-20190122.503/magit-commit.el +++ b/elpa/magit-20190514.1814/magit-commit.el @@ -38,11 +38,6 @@ ;;; Options -(defcustom magit-commit-arguments nil - "The arguments used when committing." - :group 'magit-git-arguments - :type '(repeat (string :tag "Argument"))) - (defcustom magit-commit-ask-to-stage 'verbose "Whether to ask to stage all unstaged changes when committing and nothing is staged." :package-version '(magit . "2.3.0") @@ -103,48 +98,56 @@ Also see `git-commit-post-finish-hook'." ;;; Popup -(defun magit-commit-popup (&optional arg) - "Popup console for commit commands." - (interactive "P") - (--if-let (magit-commit-message-buffer) - (switch-to-buffer it) - (magit-invoke-popup 'magit-commit-popup nil arg))) - -(defvar magit-commit-popup - '(:variable magit-commit-arguments - :man-page "git-commit" - :switches ((?a "Stage all modified and deleted files" "--all") - (?e "Allow empty commit" "--allow-empty") - (?v "Show diff of changes to be committed" "--verbose") - (?h "Disable hooks" "--no-verify") - (?s "Add Signed-off-by line" "--signoff") - (?R "Claim authorship and reset author date" "--reset-author")) - :options ((?A "Override the author" "--author=") - (?S "Sign using gpg" "--gpg-sign=" magit-read-gpg-secret-key) - (?C "Reuse commit message" "--reuse-message=" - magit-read-reuse-message)) - :actions ((?c "Commit" magit-commit-create) - (?e "Extend" magit-commit-extend) - (?f "Fixup" magit-commit-fixup) - (?F "Instant Fixup" magit-commit-instant-fixup) nil - (?w "Reword" magit-commit-reword) - (?s "Squash" magit-commit-squash) - (?S "Instant Squash" magit-commit-instant-squash) nil - (?a "Amend" magit-commit-amend) - (?A "Augment" magit-commit-augment)) - :max-action-columns 4 - :default-action magit-commit-create)) - -(magit-define-popup-keys-deferred 'magit-commit-popup) +;;;###autoload (autoload 'magit-commit "magit-commit" nil t) +(define-transient-command magit-commit () + "Create a new commit or replace an existing commit." + :info-manual "(magit)Initiating a Commit" + :man-page "git-commit" + ["Arguments" + ("-a" "Stage all modified and deleted files" ("-a" "--all")) + ("-e" "Allow empty commit" "--allow-empty") + ("-v" "Show diff of changes to be committed" ("-v" "--verbose")) + ("-n" "Disable hooks" ("-n" "--no-verify")) + ("-R" "Claim authorship and reset author date" "--reset-author") + (magit:--author :description "Override the author") + (7 "-D" "Override the author date" "--date=" transient-read-date) + ("-s" "Add Signed-off-by line" ("-s" "--signoff")) + (5 magit:--gpg-sign) + (magit-commit:--reuse-message)] + [["Create" + ("c" "Commit" magit-commit-create)] + ["Edit HEAD" + ("e" "Extend" magit-commit-extend) + ("w" "Reword" magit-commit-reword) + ("a" "Amend" magit-commit-amend) + (6 "n" "Reshelve" magit-commit-reshelve)] + ["Edit" + ("f" "Fixup" magit-commit-fixup) + ("s" "Squash" magit-commit-squash) + ("A" "Augment" magit-commit-augment) + (6 "x" "Absorb changes" magit-commit-absorb)] + ["" + ("F" "Instant fixup" magit-commit-instant-fixup) + ("S" "Instant squash" magit-commit-instant-squash)]] + (interactive) + (if-let ((buffer (magit-commit-message-buffer))) + (switch-to-buffer buffer) + (transient-setup 'magit-commit))) (defun magit-commit-arguments nil - (if (eq magit-current-popup 'magit-commit-popup) - magit-current-popup-args - magit-commit-arguments)) + (transient-args 'magit-commit)) + +(define-infix-argument magit:--gpg-sign () + :description "Sign using gpg" + :class 'transient-option + :shortarg "-S" + :argument "--gpg-sign=" + :allow-empty t + :reader 'magit-read-gpg-secret-key) (defvar magit-gpg-secret-key-hist nil) -(defun magit-read-gpg-secret-key (prompt &optional _initial-input) +(defun magit-read-gpg-secret-key (prompt &optional _initial-input history) (require 'epa) (let ((keys (--map (concat (epg-sub-key-id (car (epg-key-sub-key-list it))) " " @@ -155,13 +158,21 @@ Also see `git-commit-post-finish-hook'." (epg-decode-dn id-obj))))) (epg-list-keys (epg-make-context epa-protocol) nil t)))) (car (split-string (magit-completing-read - prompt keys nil nil nil 'magit-gpg-secret-key-hist - (car (or magit-gpg-secret-key-hist keys))) + prompt keys nil nil nil history + (car (or history keys))) " ")))) -(defun magit-read-reuse-message (prompt &optional default) +(define-infix-argument magit-commit:--reuse-message () + :description "Reuse commit message" + :class 'transient-option + :shortarg "-C" + :argument "--reuse-message=" + :reader 'magit-read-reuse-message + :history-key 'magit-revision-history) + +(defun magit-read-reuse-message (prompt &optional default history) (magit-completing-read prompt (magit-list-refnames) - nil nil nil 'magit-revision-history + nil nil nil history (or default (and (magit-rev-verify "ORIG_HEAD") "ORIG_HEAD")))) @@ -394,45 +405,60 @@ history element." (and (magit-rev-author-p "HEAD") (concat "--date=" date))))) -;;;###autoload (autoload 'magit-commit-absorb-popup "magit-commit" nil t) -(magit-define-popup magit-commit-absorb-popup - "Spread unstaged changes across recent commits. -Without a prefix argument just call `magit-commit-absorb'. -With a prefix argument use a popup buffer to select arguments." - :man-page "git-bisect" - :options '((?c "Diff context lines" "--context=") - (?s "Strictness" "--strict=")) - :actions '((?x "Absorb" magit-commit-absorb)) - :default-action 'magit-commit-absorb - :use-prefix 'popup) - -(defun magit-commit-absorb (&optional commit args confirmed) +;;;###autoload (autoload 'magit-commit-absorb "magit-commit" nil t) +(define-transient-command magit-commit-absorb (phase commit args) "Spread unstaged changes across recent commits. -This command requires the git-autofixup script, which is -available from https://github.com/torbiak/git-autofixup." - (interactive (list (magit-get-upstream-branch) - (magit-commit-absorb-arguments))) - (unless (executable-find "git-autofixup") - (user-error "This command requires the git-autofixup script, which %s" - "is available from https://github.com/torbiak/git-autofixup")) - (when (magit-anything-staged-p) - (user-error "Cannot absorb when there are staged changes")) - (unless (magit-anything-unstaged-p) - (user-error "There are no unstaged changes that could be absorbed")) - (when commit - (setq commit (magit-rebase-interactive-assert commit t))) - (if (and commit confirmed) - (progn (magit-run-git-async "autofixup" "-vv" args commit) t) - (magit-log-select - (lambda (commit) - (magit-commit-absorb commit args t)) - nil nil nil nil commit))) +With a prefix argument use a transient command to select infix +arguments. This command requires the git-autofixup script, which +is available from https://github.com/torbiak/git-autofixup." + ["Arguments" + (magit-autofixup:--context) + (magit-autofixup:--strict)] + ["Actions" + ("x" "Absorb" magit-commit-absorb)] + (interactive (if current-prefix-arg + (list 'transient nil nil) + (list 'select + (magit-get-upstream-branch) + (transient-args 'magit-commit-absorb)))) + (if (eq phase 'transient) + (transient-setup 'magit-commit-absorb) + (unless (executable-find "git-autofixup") + (user-error "This command requires the git-autofixup script, which %s" + "is available from https://github.com/torbiak/git-autofixup")) + (when (magit-anything-staged-p) + (user-error "Cannot absorb when there are staged changes")) + (unless (magit-anything-unstaged-p) + (user-error "There are no unstaged changes that could be absorbed")) + (when commit + (setq commit (magit-rebase-interactive-assert commit t))) + (if (and commit (eq phase 'run)) + (progn (magit-run-git-async "autofixup" "-vv" args commit) t) + (magit-log-select + (lambda (commit) + (with-no-warnings ; about non-interactive use + (magit-commit-absorb 'run commit args))) + nil nil nil nil commit)))) + +(define-infix-argument magit-autofixup:--context () + :description "Diff context lines" + :class 'transient-option + :shortarg "-c" + :argument "--context=" + :reader 'transient-read-number-N0) + +(define-infix-argument magit-autofixup:--strict () + :description "Strictness" + :class 'transient-option + :shortarg "-s" + :argument "--strict=" + :reader 'transient-read-number-N0) ;;; Pending Diff (defun magit-commit-diff () (when (and git-commit-mode magit-commit-show-diff) - (when-let ((diff-buffer (magit-mode-get-buffer 'magit-diff-mode))) + (when-let ((diff-buffer (magit-get-mode-buffer 'magit-diff-mode))) ;; This window just started displaying the commit message ;; buffer. Without this that buffer would immediately be ;; replaced with the diff buffer. See #2632. @@ -484,25 +510,20 @@ If no commit is in progress, then initiate it. Use the function specified by variable `magit-commit-add-log-insert-function' to actually insert the entry." (interactive) - (let ((hunk (and (magit-section-match 'hunk) - (magit-current-section))) - (log (magit-commit-message-buffer)) buf pos) - (save-window-excursion - (call-interactively #'magit-diff-visit-file) - (setq buf (current-buffer)) - (setq pos (point))) + (pcase-let* ((hunk (and (magit-section-match 'hunk) + (magit-current-section))) + (log (magit-commit-message-buffer)) + (`(,buf ,pos) (magit-diff-visit-file--noselect))) (unless log (unless (magit-commit-assert nil) (user-error "Abort")) (magit-commit-create) (while (not (setq log (magit-commit-message-buffer))) (sit-for 0.01))) - (save-excursion - (with-current-buffer buf - (goto-char pos) - (funcall magit-commit-add-log-insert-function log - (magit-file-relative-name) - (and hunk (add-log-current-defun))))))) + (magit--with-temp-position buf pos + (funcall magit-commit-add-log-insert-function log + (magit-file-relative-name) + (and hunk (add-log-current-defun)))))) (defun magit-commit-add-log-insert (buffer file defun) (with-current-buffer buffer diff --git a/elpa/magit-20190122.503/magit-core.el b/elpa/magit-20190514.1814/magit-core.el similarity index 93% rename from elpa/magit-20190122.503/magit-core.el rename to elpa/magit-20190514.1814/magit-core.el index 93085171..ccb48bf3 100644 --- a/elpa/magit-20190122.503/magit-core.el +++ b/elpa/magit-20190514.1814/magit-core.el @@ -36,8 +36,17 @@ (require 'magit-mode) (require 'magit-margin) (require 'magit-process) +(require 'magit-transient) (require 'magit-autorevert) +(when (magit--libgit-available-p) + (condition-case err + (require 'magit-libgit) + (error + (setq magit-inhibit-libgit 'error) + (message "Error while loading `magit-libgit': %S" err) + (message "That is not fatal. The `libegit2' module just won't be used.")))) + (defgroup magit nil "Controlling Git from Emacs." :link '(url-link "https://magit.vc") @@ -102,8 +111,6 @@ are enabled by default by the popup `magit-NAME-popup'." "Extensions to Magit." :group 'magit) -(custom-add-to-group 'magit-modes 'magit-popup 'custom-group) -(custom-add-to-group 'magit-faces 'magit-popup-faces 'custom-group) (custom-add-to-group 'magit-modes 'git-commit 'custom-group) (custom-add-to-group 'magit-faces 'git-commit-faces 'custom-group) (custom-add-to-group 'magit-modes 'git-rebase 'custom-group) diff --git a/elpa/magit-20190122.503/magit-diff.el b/elpa/magit-20190514.1814/magit-diff.el similarity index 71% rename from elpa/magit-20190122.503/magit-diff.el rename to elpa/magit-20190514.1814/magit-diff.el index 6de0e278..f1898d8d 100644 --- a/elpa/magit-20190122.503/magit-diff.el +++ b/elpa/magit-20190514.1814/magit-diff.el @@ -29,6 +29,7 @@ ;;; Code: (eval-when-compile + (require 'ansi-color) (require 'subr-x)) (require 'git-commit) @@ -39,27 +40,34 @@ ;; For `magit-diff-visit-file' (declare-function dired-jump "dired-x" (&optional other-window file-name)) (declare-function magit-find-file-noselect "magit-files" (rev file)) -(declare-function magit-status-internal "magit-status" (directory)) +(declare-function magit-status-setup-buffer "magit-status" (directory)) ;; For `magit-diff-while-committing' (declare-function magit-commit-message-buffer "magit-commit" ()) ;; For `magit-insert-revision-gravatar' (defvar gravatar-size) ;; For `magit-show-commit' and `magit-diff-show-or-scroll' (declare-function magit-current-blame-chunk "magit-blame" ()) -(eval-when-compile - (cl-pushnew 'orig-rev eieio--known-slot-names)) (declare-function magit-blame-mode "magit-blame" (&optional arg)) (defvar magit-blame-mode) -(defvar git-rebase-line) +;; For `magit-diff-show-or-scroll' +(declare-function git-rebase-current-line "git-rebase" ()) ;; For `magit-diff-unmerged' (declare-function magit-merge-in-progress-p "magit-merge" ()) (declare-function magit--merge-range "magit-merge" (&optional head)) +;; For `magit-diff--dwim' +(declare-function forge--pullreq-ref "forge-pullreq" (pullreq)) +;; For `magit-diff-wash-diff' +(declare-function ansi-color-apply-on-region "ansi-color" (begin end)) + +(eval-when-compile + (cl-pushnew 'base-ref eieio--known-slot-names) + (cl-pushnew 'orig-rev eieio--known-slot-names) + (cl-pushnew 'action-type eieio--known-slot-names) + (cl-pushnew 'target eieio--known-slot-names)) (require 'diff-mode) (require 'smerge-mode) -(defvar bookmark-make-record-function) - ;;; Options ;;;; Diff Mode @@ -73,12 +81,6 @@ :group 'magit-diff :type 'hook) -(defcustom magit-diff-arguments '("--stat" "--no-ext-diff") - "The diff arguments used in buffers whose mode derives from `magit-diff-mode'." - :group 'magit-git-arguments - :group 'magit-diff - :type '(repeat (string :tag "Argument"))) - (defcustom magit-diff-sections-hook '(magit-insert-diff magit-insert-xref-buttons) @@ -274,20 +276,6 @@ many spaces. Otherwise, highlight neither." :group 'magit-diff :type 'boolean) -(defcustom magit-diff-visit-previous-blob t - "Whether `magit-diff-visit-file' may visit the previous blob. - -When this is t and point is on a removed line in a diff for a -committed change, then `magit-diff-visit-file' visits the blob -from the last revision which still had that line. - -Currently this is only supported for committed changes, for -staged and unstaged changes `magit-diff-visit-file' always -visits the file in the working tree." - :package-version '(magit . "2.9.0") - :group 'magit-diff - :type 'boolean) - (defcustom magit-diff-highlight-keywords t "Whether to highlight bracketed keywords in commit messages." :package-version '(magit . "2.12.0") @@ -445,16 +433,53 @@ a good reason to include a long line in the body sometimes." :type '(choice (const :tag "Don't fill" nil) (integer :tag "Fill if longer than"))) -;;;; Diff Sections +(defcustom magit-revision-filter-files-on-follow nil + "Whether to honor file filter if log arguments include --follow. -(defcustom magit-diff-section-arguments '("--no-ext-diff") - "The diff arguments used in buffers that show other things besides diffs." - :group 'magit-git-arguments +When a commit is displayed from a log buffer, the resulting +revision buffer usually shares the log's file arguments, +restricting the diff to those files. However, there's a +complication when the log arguments include --follow: if the log +follows a file across a rename event, keeping the file +restriction would mean showing an empty diff in revision buffers +for commits before the rename event. + +When this option is nil, the revision buffer ignores the log's +filter if the log arguments include --follow. If non-nil, the +log's file filter is always honored." + :package-version '(magit . "2.91.0") + :group 'magit-revision + :type 'boolean) + +;;;; Visit Commands + +(defcustom magit-diff-visit-previous-blob t + "Whether `magit-diff-visit-file' may visit the previous blob. + +When this is t and point is on a removed line in a diff for a +committed change, then `magit-diff-visit-file' visits the blob +from the last revision which still had that line. + +Currently this is only supported for committed changes, for +staged and unstaged changes `magit-diff-visit-file' always +visits the file in the working tree." + :package-version '(magit . "2.9.0") :group 'magit-diff - :group 'magit-status - :type '(repeat (string :tag "Argument"))) + :type 'boolean) + +(defcustom magit-diff-visit-avoid-head-blob nil + "Whether `magit-diff-visit-file' avoids visiting a blob from `HEAD'. -(put 'magit-diff-section-arguments 'permanent-local t) +By default `magit-diff-visit-file' always visits the blob that +added the current line, while `magit-diff-visit-file-worktree' +visits the respective file in the working tree. For the `HEAD' +commit, the former command used to visit the worktree file too, +but that made it impossible to visit a blob from `HEAD'. + +If you prefer the old behavior, then set this to t." + :package-version '(magit . "2.91.0") + :group 'magit-diff + :type 'boolean) ;;; Faces @@ -654,162 +679,209 @@ and `:slant'." "Face for minus sign in diffstat." :group 'magit-faces) -;;; Commands -;;;; Diff popups - -(defconst magit-diff-popup-common-keywords - '(:variable magit-diff-arguments - :man-page "git-diff")) - -(defconst magit-diff-popup-common-options - '((?f "Limit to files" "-- " magit-read-files) - (?u "Context lines" "-U") - (?m "Detect renames" "-M") - (?c "Detect copies" "-C") - (?a "Diff algorithm" "--diff-algorithm=" magit-diff-select-algorithm) - (?i "Ignore submodules" "--ignore-submodules=" - magit-diff-select-ignore-submodules))) - -(defconst magit-diff-popup-common-switches - '((?f "Show surrounding functions" "--function-context") - (?b "Ignore whitespace changes" "--ignore-space-change") - (?w "Ignore all whitespace" "--ignore-all-space") - (?x "Disallow external diff drivers" "--no-ext-diff"))) - -(defvar magit-diff-popup - `(,@magit-diff-popup-common-keywords - :options ,magit-diff-popup-common-options - :switches (,@magit-diff-popup-common-switches - (?s "Show stats" "--stat")) - :actions ((?d "Dwim" magit-diff-dwim) - (?u "Diff unstaged" magit-diff-unstaged) - (?c "Show commit" magit-show-commit) - (?r "Diff range" magit-diff-range) - (?s "Diff staged" magit-diff-staged) - (?t "Show stash" magit-stash-show) - (?p "Diff paths" magit-diff-paths) - (?w "Diff worktree" magit-diff-working-tree)) - :default-action magit-diff-dwim - :max-action-columns 3)) - -(defvar magit-diff-refresh-popup - `(,@magit-diff-popup-common-keywords - :options ,magit-diff-popup-common-options - :switches ,magit-diff-popup-common-switches - :actions ((?g "Refresh" magit-diff-refresh) - (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) - (?s "Set defaults" magit-diff-set-default-arguments) - (?F "Toggle file filter" magit-diff-toggle-file-filter) - (?w "Save defaults" magit-diff-save-default-arguments)) - :max-action-columns 2)) - -(defvar magit-diff-mode-refresh-popup - `(,@magit-diff-popup-common-keywords - :options ,magit-diff-popup-common-options - :switches (,@magit-diff-popup-common-switches - (?s "Show stats" "--stat")) - :actions ((?g "Refresh" magit-diff-refresh) - (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) - (?s "Set defaults" magit-diff-set-default-arguments) - (?r "Switch range type" magit-diff-switch-range-type) - (?w "Save defaults" magit-diff-save-default-arguments) - (?f "Flip revisions" magit-diff-flip-revs) nil - (?F "Toggle file filter" magit-diff-toggle-file-filter)) - :max-action-columns 2)) - -(defvar magit-revision-mode-refresh-popup - `(,@magit-diff-popup-common-keywords - :options ,magit-diff-popup-common-options - :switches (,@magit-diff-popup-common-switches - (?s "Show stats" "--stat")) - :actions ((?g "Refresh" magit-diff-refresh) - (?t "Toggle hunk refinement" magit-diff-toggle-refine-hunk) - (?s "Set defaults" magit-diff-set-default-arguments) - (?F "Toggle file filter" magit-diff-toggle-file-filter) - (?w "Save defaults" magit-diff-save-default-arguments)) - :max-action-columns 2)) - -(magit-define-popup-keys-deferred 'magit-diff-popup) -(magit-define-popup-keys-deferred 'magit-diff-refresh-popup) -(magit-define-popup-keys-deferred 'magit-diff-mode-refresh-popup) -(magit-define-popup-keys-deferred 'magit-revision-mode-refresh-popup) - -(defvar magit-diff-section-file-args nil) -(put 'magit-diff-section-file-args 'permanent-local t) -(put 'magit-diff-section-file-args 'safe-local-variable - (lambda (val) - (and (listp val) - (-all-p #'stringp val)))) - -(defun magit-diff-get-buffer-args () - (cond ((and magit-use-sticky-arguments - (derived-mode-p 'magit-diff-mode)) - (list (nth 2 magit-refresh-args) - (nth 3 magit-refresh-args))) - ((and (eq magit-use-sticky-arguments t) - (--when-let (magit-mode-get-buffer 'magit-diff-mode) - (with-current-buffer it - (list (nth 2 magit-refresh-args) - (nth 3 magit-refresh-args)))))) - (t - (list (default-value 'magit-diff-arguments) nil)))) - -(defun magit-diff-arguments (&optional refresh) - (cond ((memq magit-current-popup '(magit-diff-popup magit-diff-refresh-popup)) - (magit-popup-export-file-args magit-current-popup-args)) - ((and refresh (not (derived-mode-p 'magit-diff-mode))) - (list magit-diff-section-arguments - magit-diff-section-file-args)) - (t - (magit-diff-get-buffer-args)))) - -;;;###autoload -(defun magit-diff-popup (arg) - "Popup console for diff commands." - (interactive "P") - (let ((magit-diff-arguments - ;; We cannot possibly know what suffix command the user is - ;; about to invoke, so we also don't know from which buffer - ;; we should get the current values. However it is much - ;; more likely that we will end up updating the diff buffer, - ;; and we therefore use the value from that buffer. - (apply #'magit-popup-import-file-args (magit-diff-get-buffer-args)))) - (magit-invoke-popup 'magit-diff-popup nil arg))) - -;;;###autoload -(defun magit-diff-buffer-file-popup () - "Popup console for diff commands. +;;; Arguments +;;;; Prefix Classes + +(defclass magit-diff-prefix (transient-prefix) + ((history-key :initform 'magit-diff) + (major-mode :initform 'magit-diff-mode))) + +(defclass magit-diff-refresh-prefix (magit-diff-prefix) + ((history-key :initform 'magit-diff) + (major-mode :initform nil))) + +;;;; Prefix Methods + +(cl-defmethod transient-init-value ((obj magit-diff-prefix)) + (pcase-let ((`(,args ,files) + (magit-diff--get-value 'magit-diff-mode + magit-prefix-use-buffer-arguments))) + (unless (eq current-transient-command 'magit-dispatch) + (when-let ((file (magit-file-relative-name))) + (setq files (list file)))) + (oset obj value (if files `(("--" ,@files) ,args) args)))) + +(cl-defmethod transient-init-value ((obj magit-diff-refresh-prefix)) + (oset obj value (if magit-buffer-diff-files + `(("--" ,@magit-buffer-diff-files) + ,magit-buffer-diff-args) + magit-buffer-diff-args))) + +(cl-defmethod transient-set-value ((obj magit-diff-prefix)) + (magit-diff--set-value obj)) + +(cl-defmethod transient-save-value ((obj magit-diff-prefix)) + (magit-diff--set-value obj 'save)) + +;;;; Argument Access + +(defun magit-diff-arguments (&optional mode) + "Return the current diff arguments." + (if (memq current-transient-command '(magit-diff magit-diff-refresh)) + (pcase-let ((`(,args ,alist) + (transient-args nil t))) + (list args (cdr (assoc "--" alist)))) + (magit-diff--get-value (or mode 'magit-diff-mode)))) + +(defun magit-diff--get-value (mode &optional use-buffer-args) + (unless use-buffer-args + (setq use-buffer-args magit-direct-use-buffer-arguments)) + (let (args files) + (cond + ((and (memq use-buffer-args '(always selected current)) + (eq major-mode mode)) + (setq args magit-buffer-diff-args) + (setq files magit-buffer-diff-files)) + ((and (memq use-buffer-args '(always selected)) + (when-let ((buffer (magit-get-mode-buffer + mode nil + (or (eq use-buffer-args 'selected) 'all)))) + (setq args (buffer-local-value 'magit-buffer-diff-args buffer)) + (setq files (buffer-local-value 'magit-buffer-diff-files buffer)) + t))) + ((plist-member (symbol-plist mode) 'magit-diff-current-arguments) + (setq args (get mode 'magit-diff-current-arguments))) + ((when-let ((elt (assq (intern (format "magit-diff:%s" mode)) + transient-values))) + (setq args (cdr elt)) + t)) + (t + (setq args (get mode 'magit-diff-default-arguments)))) + (list args files))) + +(defun magit-diff--set-value (obj &optional save) + (pcase-let* ((obj (oref obj prototype)) + (mode (or (oref obj major-mode) major-mode)) + (key (intern (format "magit-diff:%s" mode))) + (`(,args ,alist) + (-separate #'atom (transient-args))) + (files (cdr (assoc "--" alist)))) + (put mode 'magit-diff-current-arguments args) + (when save + (setf (alist-get key transient-values) args) + (transient-save-values)) + (transient--history-push obj) + (setq magit-buffer-diff-args args) + (setq magit-buffer-diff-files files) + (magit-refresh))) -This is a variant of `magit-diff-popup' which shows the same popup -but which limits the diff to the file being visited in the current -buffer." +;;; Commands +;;;; Prefix Commands + +;;;###autoload (autoload 'magit-diff "magit-diff" nil t) +(define-transient-command magit-diff () + "Show changes between different versions." + :man-page "git-diff" + :class 'magit-diff-prefix + ["Limit arguments" + (magit:--) + (magit-diff:--ignore-submodules) + ("-b" "Ignore whitespace changes" ("-b" "--ignore-space-change")) + ("-w" "Ignore all whitespace" ("-w" "--ignore-all-space"))] + ["Context arguments" + (magit-diff:-U) + ("-W" "Show surrounding functions" ("-W" "--function-context"))] + ["Tune arguments" + (magit-diff:--diff-algorithm) + (magit-diff:-M) + (magit-diff:-C) + ("-x" "Disallow external diff drivers" "--no-ext-diff") + ("-s" "Show stats" "--stat") + (5 magit-diff:--color-moved) + (5 magit-diff:--color-moved-ws)] + ["Actions" + [("d" "Dwim" magit-diff-dwim) + ("r" "Diff range" magit-diff-range) + ("p" "Diff paths" magit-diff-paths)] + [("u" "Diff unstaged" magit-diff-unstaged) + ("s" "Diff staged" magit-diff-staged) + ("w" "Diff worktree" magit-diff-working-tree)] + [("c" "Show commit" magit-show-commit) + ("t" "Show stash" magit-stash-show)]]) + +;;;###autoload (autoload 'magit-diff-refresh "magit-diff" nil t) +(define-transient-command magit-diff-refresh () + "Change the arguments used for the diff(s) in the current buffer." + :man-page "git-diff" + :class 'magit-diff-refresh-prefix + ["Limit arguments" + (magit:--) + (magit-diff:--ignore-submodules) + ("-b" "Ignore whitespace changes" ("-b" "--ignore-space-change")) + ("-w" "Ignore all whitespace" ("-w" "--ignore-all-space"))] + ["Context arguments" + (magit-diff:-U) + ("-W" "Show surrounding functions" ("-W" "--function-context"))] + ["Tune arguments" + (magit-diff:--diff-algorithm) + (magit-diff:-M) + (magit-diff:-C) + ("-x" "Disallow external diff drivers" "--no-ext-diff") + ("-s" "Show stats" "--stat" + :if-derived magit-diff-mode) + (5 magit-diff:--color-moved) + (5 magit-diff:--color-moved-ws)] + [["Refresh" + ("g" "buffer" magit-diff-refresh) + ("s" "buffer and set defaults" transient-set :transient nil) + ("w" "buffer and save defaults" transient-save :transient nil)] + ["Toggle" + ("t" "hunk refinement" magit-diff-toggle-refine-hunk) + ("F" "file filter" magit-diff-toggle-file-filter) + ("b" "buffer lock" magit-toggle-buffer-lock + :if-mode (magit-diff-mode magit-revision-mode magit-stash-mode))] + [:if-mode magit-diff-mode + :description "Do" + ("r" "switch range type" magit-diff-switch-range-type) + ("f" "flip revisions" magit-diff-flip-revs)]] (interactive) - (if-let ((file (magit-file-relative-name))) - (let ((magit-diff-arguments - (magit-popup-import-file-args - (if-let ((buffer (magit-mode-get-buffer 'magit-diff-mode))) - (with-current-buffer buffer - (nth 3 magit-refresh-args)) - (default-value 'magit-diff-arguments)) - (list file)))) - (magit-invoke-popup 'magit-diff-popup nil nil)) - (user-error "Buffer isn't visiting a file"))) + (if (not (eq current-transient-command 'magit-diff-refresh)) + (transient-setup 'magit-diff-refresh) + (pcase-let ((`(,args ,files) (magit-diff-arguments))) + (setq magit-buffer-diff-args args) + (setq magit-buffer-diff-files files)) + (magit-refresh))) -(defun magit-diff-refresh-popup (arg) - "Popup console for changing diff arguments in the current buffer." - (interactive "P") - (let ((magit-diff-refresh-popup - (pcase major-mode - (`magit-revision-mode magit-revision-mode-refresh-popup) - (`magit-diff-mode magit-diff-mode-refresh-popup) - (_ magit-diff-refresh-popup))) - (magit-diff-arguments - (if (derived-mode-p 'magit-diff-mode) - (magit-popup-import-file-args (nth 2 magit-refresh-args) - (nth 3 magit-refresh-args)) - (magit-popup-import-file-args magit-diff-section-arguments - magit-diff-section-file-args)))) - (magit-invoke-popup 'magit-diff-refresh-popup nil arg))) +;;;; Infix Commands + +(define-infix-argument magit:-- () + :description "Limit to files" + :class 'transient-files + :key "--" + :argument "--" + :prompt "Limit to file(s): " + :reader 'magit-read-files + :multi-value t) + +(defun magit-read-files (prompt initial-input history) + (magit-completing-read-multiple* prompt + (magit-list-files) + nil nil initial-input history)) + +(define-infix-argument magit-diff:-U () + :description "Context lines" + :class 'transient-option + :argument "-U" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-diff:-M () + :description "Detect renames" + :class 'transient-option + :argument "-M" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-diff:-C () + :description "Detect copies" + :class 'transient-option + :argument "-C" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-diff:--diff-algorithm () + :description "Diff algorithm" + :class 'transient-option + :key "-A" + :argument "--diff-algorithm=" + :reader 'magit-diff-select-algorithm) (defun magit-diff-select-algorithm (&rest _ignore) (magit-read-char-case nil t @@ -818,13 +890,50 @@ buffer." (?p "[p]atience" "patience") (?h "[h]istogram" "histogram"))) +(define-infix-argument magit-diff:--ignore-submodules () + :description "Ignore submodules" + :class 'transient-option + :key "-i" + :argument "--ignore-submodules=" + :reader 'magit-diff-select-ignore-submodules) + (defun magit-diff-select-ignore-submodules (&rest _ignored) (magit-read-char-case "Ignore submodules " t (?u "[u]ntracked" "untracked") (?d "[d]irty" "dirty") (?a "[a]ll" "all"))) -;;;; Diff commands +(define-infix-argument magit-diff:--color-moved () + :description "Color moved lines" + :class 'transient-option + :key "-m" + :argument "--color-moved=" + :reader 'magit-diff-select-color-moved-mode) + +(defun magit-diff-select-color-moved-mode (&rest _ignore) + (magit-read-char-case "Color moved " t + (?d "[d]efault" "default") + (?p "[p]lain" "plain") + (?b "[b]locks" "blocks") + (?z "[z]ebra" "zebra") + (?Z "[Z] dimmed-zebra" "dimmed-zebra"))) + +(define-infix-argument magit-diff:--color-moved-ws () + :description "Whitespace treatment for --color-moved" + :class 'transient-option + :key "=w" + :argument "--color-moved-ws=" + :reader 'magit-diff-select-color-moved-ws-mode) + +(defun magit-diff-select-color-moved-ws-mode (&rest _ignore) + (magit-read-char-case "Ignore whitespace " t + (?i "[i]ndentation" "allow-indentation-change") + (?e "[e]nd of line" "ignore-space-at-eol") + (?s "[s]pace change" "ignore-space-change") + (?a "[a]ll space" "ignore-all-space") + (?n "[n]o" "no"))) + +;;;; Setup Commands ;;;###autoload (defun magit-diff-dwim (&optional args files) @@ -881,9 +990,9 @@ If no DWIM context is found, nil is returned." (oref parent) (oref value)))))) ((derived-mode-p 'magit-revision-mode) - (cons 'commit (car magit-refresh-args))) + (cons 'commit magit-buffer-revision)) ((derived-mode-p 'magit-diff-mode) - (nth 0 magit-refresh-args)) + magit-buffer-range) (t (magit-section-case ([* unstaged] 'unstaged) @@ -903,7 +1012,11 @@ If no DWIM context is found, nil is returned." (or current "HEAD") atpoint)))) (commit (cons 'commit (oref it value))) - (stash (cons 'stash (oref it value))))))) + (stash (cons 'stash (oref it value))) + (pullreq (let ((pullreq (oref it value))) + (format "%s...%s" + (oref pullreq base-ref) + (forge--pullreq-ref pullreq)))))))) (defun magit-diff-read-range-or-commit (prompt &optional secondary-default mbase) "Read range or revision with special diff range treatment. @@ -937,10 +1050,6 @@ a \"revA...revB\" range. Otherwise, always construct secondary-default (magit-get-current-branch))))) -(defun magit-diff-setup (rev-or-range const args files) - (require 'magit) - (magit-mode-setup #'magit-diff-mode rev-or-range const args files)) - ;;;###autoload (defun magit-diff-range (rev-or-range &optional args files) "Show differences between two commits. @@ -958,7 +1067,7 @@ revisions (i.e., use a \"...\" range)." (interactive (cons (magit-diff-read-range-or-commit "Diff for range" nil current-prefix-arg) (magit-diff-arguments))) - (magit-diff-setup rev-or-range nil args files)) + (magit-diff-setup-buffer rev-or-range nil args files)) ;;;###autoload (defun magit-diff-working-tree (&optional rev args files) @@ -969,7 +1078,7 @@ a commit read from the minibuffer." (cons (and current-prefix-arg (magit-read-branch-or-commit "Diff working tree and commit")) (magit-diff-arguments))) - (magit-diff-setup (or rev "HEAD") nil args files)) + (magit-diff-setup-buffer (or rev "HEAD") nil args files)) ;;;###autoload (defun magit-diff-staged (&optional rev args files) @@ -980,13 +1089,13 @@ a commit read from the minibuffer." (cons (and current-prefix-arg (magit-read-branch-or-commit "Diff index and commit")) (magit-diff-arguments))) - (magit-diff-setup rev (list "--cached") args files)) + (magit-diff-setup-buffer rev "--cached" args files)) ;;;###autoload (defun magit-diff-unstaged (&optional args files) "Show changes between the working tree and the index." (interactive (magit-diff-arguments)) - (magit-diff-setup nil nil args files)) + (magit-diff-setup-buffer nil nil args files)) ;;;###autoload (defun magit-diff-unmerged (&optional args files) @@ -994,7 +1103,7 @@ a commit read from the minibuffer." (interactive (magit-diff-arguments)) (unless (magit-merge-in-progress-p) (user-error "No merge is in progress")) - (magit-diff-setup (magit--merge-range) nil args files)) + (magit-diff-setup-buffer (magit--merge-range) nil args files)) ;;;###autoload (defun magit-diff-while-committing (&optional args) @@ -1006,21 +1115,20 @@ be committed." (unless (magit-commit-message-buffer) (user-error "No commit in progress")) (let ((magit-display-buffer-noselect t) - (diff-buf (magit-mode-get-buffer 'magit-diff-mode))) + (diff-buf (magit-get-mode-buffer 'magit-diff-mode))) (if (and diff-buf (get-buffer-window diff-buf)) (with-current-buffer diff-buf - (pcase-let ((`(,rev ,arg . ,_) magit-refresh-args)) - (cond ((and (equal rev "HEAD^") - (equal arg '("--cached"))) - (magit-diff-staged nil args)) - ((and (equal rev nil) - (equal arg '("--cached"))) - (magit-diff-while-amending args)) - ((magit-anything-staged-p) - (magit-diff-staged nil args)) - (t - (magit-diff-while-amending args))))) + (cond ((and (equal magit-buffer-range "HEAD^") + (equal magit-buffer-typearg "--cached")) + (magit-diff-staged nil args)) + ((and (equal magit-buffer-range nil) + (equal magit-buffer-typearg "--cached")) + (magit-diff-while-amending args)) + ((magit-anything-staged-p) + (magit-diff-staged nil args)) + (t + (magit-diff-while-amending args)))) (if (magit-anything-staged-p) (magit-diff-staged nil args) (magit-diff-while-amending args))))) @@ -1029,22 +1137,33 @@ be committed." (kbd "C-c C-d") 'magit-diff-while-committing) (defun magit-diff-while-amending (&optional args) - (magit-diff-setup "HEAD^" (list "--cached") args nil)) + (magit-diff-setup-buffer "HEAD^" "--cached" args nil)) ;;;###autoload (defun magit-diff-buffer-file () - "Show diff for the blob or file visited in the current buffer." + "Show diff for the blob or file visited in the current buffer. + +When the buffer visits a blob, then show the respective commit. +When the buffer visits a file, then show the differenced between +`HEAD' and the working tree. In both cases limit the diff to +the file or blob." (interactive) (require 'magit) (if-let ((file (magit-file-relative-name))) - (magit-mode-setup-internal #'magit-diff-mode - (list (or magit-buffer-refname - (magit-get-current-branch) - "HEAD") + (if magit-buffer-refname + (magit-show-commit magit-buffer-refname + (car (magit-show-commit--arguments)) + (list file)) + (save-buffer) + (let ((line (line-number-at-pos)) + (col (current-column))) + (with-current-buffer + (magit-diff-setup-buffer (or (magit-get-current-branch) "HEAD") nil - (cadr (magit-diff-arguments)) - (list file)) - magit-diff-buffer-file-locked) + (car (magit-diff-arguments)) + (list file) + magit-diff-buffer-file-locked) + (magit-diff--goto-position file line col)))) (user-error "Buffer isn't visiting a file"))) ;;;###autoload @@ -1052,19 +1171,19 @@ be committed." "Show changes between any two files on disk." (interactive (list (read-file-name "First file: " nil nil t) (read-file-name "Second file: " nil nil t))) - (magit-diff-setup nil (list "--no-index") - nil (list (magit-convert-filename-for-git - (expand-file-name a)) - (magit-convert-filename-for-git - (expand-file-name b))))) - -(defvar-local magit-buffer-revision-hash nil) + (magit-diff-setup-buffer nil "--no-index" + nil (list (magit-convert-filename-for-git + (expand-file-name a)) + (magit-convert-filename-for-git + (expand-file-name b))))) (defun magit-show-commit--arguments () - (pcase-let ((`(,args ,diff-files) (magit-diff-arguments))) + (pcase-let ((`(,args ,diff-files) + (magit-diff-arguments 'magit-revision-mode))) (list args (if (derived-mode-p 'magit-log-mode) - (and (not (member "--follow" (nth 1 magit-refresh-args))) - (nth 2 magit-refresh-args)) + (and (or magit-revision-filter-files-on-follow + (not (member "--follow" magit-buffer-log-args))) + magit-buffer-log-files) diff-files)))) ;;;###autoload @@ -1086,92 +1205,84 @@ for a revision." (and mcommit (magit-section-parent-value (magit-current-section)))))) (require 'magit) - (magit-with-toplevel - (when module - (setq default-directory - (expand-file-name (file-name-as-directory module)))) - (unless (magit-commit-p rev) - (user-error "%s is not a commit" rev)) - (magit-mode-setup #'magit-revision-mode rev nil args files))) - -;;;; Setting commands - -(defun magit-diff-refresh (args files) - "Set the local diff arguments for the current buffer." - (interactive (magit-diff-arguments t)) - (cond ((derived-mode-p 'magit-diff-mode) - (setcdr (cdr magit-refresh-args) (list args files))) - (t - (setq-local magit-diff-section-arguments args) - (setq-local magit-diff-section-file-args files))) - (magit-refresh)) - -(defun magit-diff-set-default-arguments (args files) - "Set the global diff arguments for the current buffer." - (interactive (magit-diff-arguments t)) - (cond ((derived-mode-p 'magit-diff-mode) - (customize-set-variable 'magit-diff-arguments args) - (setcdr (cdr magit-refresh-args) (list args files))) - (t - (customize-set-variable 'magit-diff-section-arguments args) - (kill-local-variable 'magit-diff-section-arguments) - (kill-local-variable 'magit-diff-section-file-args))) - (magit-refresh)) - -(defun magit-diff-save-default-arguments (args files) - "Set and save the global diff arguments for the current buffer." - (interactive (magit-diff-arguments t)) - (cond ((derived-mode-p 'magit-diff-mode) - (customize-save-variable 'magit-diff-arguments args) - (setcdr (cdr magit-refresh-args) (list args files))) - (t - (customize-save-variable 'magit-diff-section-arguments args) - (kill-local-variable 'magit-diff-section-arguments) - (kill-local-variable 'magit-diff-section-file-args))) - (magit-refresh)) + (let ((file (magit-file-relative-name))) + (magit-with-toplevel + (when module + (setq default-directory + (expand-file-name (file-name-as-directory module)))) + (unless (magit-commit-p rev) + (user-error "%s is not a commit" rev)) + (let ((buf (magit-revision-setup-buffer rev args files))) + (when file + (save-buffer) + (let ((line (magit-diff-visit--offset file (list "-R" rev) + (line-number-at-pos))) + (col (current-column))) + (with-current-buffer buf + (magit-diff--goto-position file line col)))))))) + +(defun magit-diff--goto-position (file line column) + (when-let ((diff (cl-find-if (lambda (section) + (and (cl-typep section 'magit-file-section) + (equal (oref section value) file))) + (oref magit-root-section children)))) + (goto-char (oref diff start)) + (let (hunk (hunks (oref diff children))) + (while (setq hunk (pop hunks)) + (pcase-let* ((`(,beg ,len) (oref hunk to-range)) + (end (+ beg len))) + (cond ((<= beg line end) + (goto-char (oref hunk content)) + (let ((pos beg)) + (while (or (< pos line) + (= (char-after) ?-)) + (unless (= (char-after) ?-) + (cl-incf pos)) + (forward-line))) + (move-to-column (1+ column)) + (setq hunks nil)) + ((> end line) + (goto-char (oref hunk start)) + (setq hunks nil)) + ;; ((not hunks) + ;; (goto-char (oref hunk end)) + ;; (forward-line -1)) + )))))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-revision-mode)) + (cons magit-buffer-range magit-buffer-diff-files)) + +;;;; Setting Commands (defun magit-diff-switch-range-type () "Convert diff range type. -Change \"revA..revB\" to \"revB...revA\", or vice versa." +Change \"revA..revB\" to \"revA...revB\", or vice versa." (interactive) - (let ((range (car magit-refresh-args))) - (if (and range - (derived-mode-p 'magit-diff-mode) - (string-match magit-range-re range)) - (progn - (setcar magit-refresh-args - (concat (match-string 1 range) - (if (string= (match-string 2 range) "..") - "..." - "..") - (match-string 3 range))) - (magit-refresh)) - (user-error "No range to change")))) + (if (and magit-buffer-range + (derived-mode-p 'magit-diff-mode) + (string-match magit-range-re magit-buffer-range)) + (setq magit-buffer-range + (replace-match (if (string= (match-string 2 magit-buffer-range) "..") + "..." + "..") + t t magit-buffer-range)) + (user-error "No range to change")) + (magit-refresh)) (defun magit-diff-flip-revs () "Swap revisions in diff range. Change \"revA..revB\" to \"revB..revA\"." (interactive) - (let ((range (car magit-refresh-args))) - (if (and range - (derived-mode-p 'magit-diff-mode) - (string-match magit-range-re range)) - (progn - (setcar magit-refresh-args - (concat (match-string 3 range) - (match-string 2 range) - (match-string 1 range))) - (magit-refresh)) - (user-error "No range to swap")))) - -(defvar-local magit-diff--last-file-args nil) -(defun magit-diff--toggle-file-args (files) - (cond (files - (setq magit-diff--last-file-args files) - nil) - (magit-diff--last-file-args) - (t - (user-error "No diff file filter to toggle")))) + (if (and magit-buffer-range + (derived-mode-p 'magit-diff-mode) + (string-match magit-range-re magit-buffer-range)) + (progn + (setq magit-buffer-range + (concat (match-string 3 magit-buffer-range) + (match-string 2 magit-buffer-range) + (match-string 1 magit-buffer-range))) + (magit-refresh)) + (user-error "No range to swap"))) (defun magit-diff-toggle-file-filter () "Toggle the file restriction of the current buffer's diffs. @@ -1179,18 +1290,27 @@ If the current buffer's mode is derived from `magit-log-mode', toggle the file restriction in the repository's revision buffer instead." (interactive) - (--if-let (and (derived-mode-p 'magit-log-mode) - (magit-mode-get-buffer 'magit-revision-mode)) - (with-current-buffer it - (setf (nth 3 magit-refresh-args) - (magit-diff--toggle-file-args (nth 3 magit-refresh-args))) - (magit-refresh)) - (if (derived-mode-p 'magit-diff-mode) - (setf (nth 3 magit-refresh-args) - (magit-diff--toggle-file-args (nth 3 magit-refresh-args))) - (setq-local magit-diff-section-file-args - (magit-diff--toggle-file-args magit-diff-section-file-args))) - (magit-refresh))) + (cl-flet ((toggle () + (if (or magit-buffer-diff-files + magit-buffer-diff-files-suspended) + (cl-rotatef magit-buffer-diff-files + magit-buffer-diff-files-suspended) + (setq magit-buffer-diff-files + (magit-read-files "Limit to file(s): " + (magit-file-at-point) + nil))) + (magit-refresh))) + (cond + ((derived-mode-p 'magit-log-mode + 'magit-cherry-mode + 'magit-reflog-mode) + (if-let ((buffer (magit-get-mode-buffer 'magit-revision-mode))) + (with-current-buffer buffer (toggle)) + (message "No revision buffer"))) + ((local-variable-p 'magit-buffer-diff-files) + (toggle)) + (t + (user-error "Cannot toggle file filter in this buffer"))))) (defun magit-diff-less-context (&optional count) "Decrease the context for diff hunks by COUNT lines." @@ -1209,32 +1329,29 @@ instead." (defun magit-diff-set-context (fn) (let* ((def (--if-let (magit-get "diff.context") (string-to-number it) 3)) - (val (car (magit-diff-arguments t))) + (val magit-buffer-diff-args) (arg (--first (string-match "^-U\\([0-9]+\\)?$" it) val)) (num (--if-let (and arg (match-string 1 arg)) (string-to-number it) def)) (val (delete arg val)) (num (funcall fn num)) (arg (and num (not (= num def)) (format "-U%i" num))) (val (if arg (cons arg val) val))) - (if (derived-mode-p 'magit-diff-mode) - (setcar (cddr magit-refresh-args) val) - (setq magit-diff-section-arguments val))) + (setq magit-buffer-diff-args val)) (magit-refresh)) (defun magit-diff-context-p () - (--if-let (--first (string-match "^-U\\([0-9]+\\)$" it) - (car (magit-diff-arguments t))) - (not (equal "-U0" it)) + (if-let ((arg (--first (string-match "^-U\\([0-9]+\\)$" it) + magit-buffer-diff-args))) + (not (equal arg "-U0")) t)) (defun magit-diff-ignore-any-space-p () - (let ((args (car (magit-diff-arguments t)))) - (--any-p (member it args) - '("--ignore-cr-at-eol" - "--ignore-space-at-eol" - "--ignore-space-change" "-b" - "--ignore-all-space" "-w" - "--ignore-blank-space")))) + (--any-p (member it magit-buffer-diff-args) + '("--ignore-cr-at-eol" + "--ignore-space-at-eol" + "--ignore-space-change" "-b" + "--ignore-all-space" "-w" + "--ignore-blank-space"))) (defun magit-diff-toggle-refine-hunk (&optional style) "Turn diff-hunk refining on or off. @@ -1257,178 +1374,174 @@ Customize variable `magit-diff-refine-hunk' to change the default mode." (not magit-diff-refine-hunk))) (magit-diff-update-hunk-refinement)) -;;;; Visit commands - -(defun magit-diff-visit-file - (file &optional other-window force-worktree display-fn) - "From a diff, visit the corresponding file at the appropriate position. - -If the diff shows changes in the worktree, the index, or `HEAD', -then visit the actual file. Otherwise, when the diff is about an -older commit or a range, then visit the appropriate blob. - -If point is on a removed line, then visit the blob for the first -parent of the commit which removed that line, i.e. the last -commit where that line still existed. Otherwise visit the blob -for the commit whose changes are being shown. - -Interactively, when the file or blob to be displayed is already -being displayed in another window of the same frame, then just -select that window and adjust point. Otherwise, or with a prefix -argument, display the buffer in another window. The meaning of -the prefix argument can be inverted or further modified using the -option `magit-display-file-buffer-function'. - -Non-interactively the optional OTHER-WINDOW argument is taken -literally. DISPLAY-FN can be used to specify the display -function explicitly, in which case OTHER-WINDOW is ignored. - -The optional FORCE-WORKTREE means to force visiting the worktree -version of the file. To do this interactively use the command -`magit-diff-visit-file-worktree' instead." - (interactive (list (--if-let (magit-file-at-point) - (expand-file-name it) - (user-error "No file at point")) - current-prefix-arg)) - (if (magit-file-accessible-directory-p file) - (magit-diff-visit-directory file other-window) - (let* ((hunk (magit-diff-visit--hunk)) - (last (and magit-diff-visit-previous-blob - (not force-worktree) - (magit-section-match 'hunk) - (save-excursion - (goto-char (line-beginning-position)) - (looking-at "-")))) - (line (and hunk (magit-diff-hunk-line hunk))) - (col (and hunk (magit-diff-hunk-column hunk last))) - (rev (if last - (magit-diff-visit--range-beginning) - (magit-diff-visit--range-end))) - (buf (if (and (not force-worktree) - (stringp rev)) - (magit-find-file-noselect rev file) - (or (get-file-buffer file) - (find-file-noselect file))))) - (cond ((called-interactively-p 'any) - (magit-display-file-buffer buf)) - (display-fn - (funcall display-fn buf)) - ((or other-window (get-buffer-window buf)) - (switch-to-buffer-other-window buf)) - (t - (pop-to-buffer buf))) - (with-selected-window - (or (get-buffer-window buf 'visible) - (error "File buffer is not visible")) - (when line - (setq line - (cond ((eq rev 'staged) - (apply 'magit-diff-visit--offset file nil line)) - ((and force-worktree - (stringp rev)) - (apply 'magit-diff-visit--offset file rev line)) - (t - (apply '+ line)))) - (let ((pos (save-restriction - (widen) - (goto-char (point-min)) - (forward-line (1- line)) - (move-to-column col) - (point)))) - (unless (<= (point-min) pos (point-max)) - (widen) - (goto-char pos)))) - (when (magit-anything-unmerged-p file) - (smerge-start-session)) - (run-hooks 'magit-diff-visit-file-hook))))) +;;;; Visit Commands +;;;;; Dwim Variants + +(defun magit-diff-visit-file (file &optional other-window) + "From a diff visit the appropriate version of FILE. + +Display the buffer in the selected window. With a prefix +argument OTHER-WINDOW display the buffer in another window +instead. + +Visit the worktree version of the appropriate file. The location +of point inside the diff determines which file is being visited. +The visited version depends on what changes the diff is about. + +1. If the diff shows uncommitted changes (i.e. stage or unstaged + changes), then visit the file in the working tree (i.e. the + same \"real\" file that `find-file' would visit. In all other + cases visit a \"blob\" (i.e. the version of a file as stored + in some commit). + +2. If point is on a removed line, then visit the blob for the + first parent of the commit that removed that line, i.e. the + last commit where that line still exists. + +3. If point is on an added or context line, then visit the blob + that adds that line, or if the diff shows from more than a + single commit, then visit the blob from the last of these + commits. + +In the file-visiting buffer also go to the line that corresponds +to the line that point is on in the diff. + +Note that this command only works if point is inside a diff. In +other cases `magit-find-file' (which see) had to be used." + (interactive (list (magit-file-at-point t t) current-prefix-arg)) + (magit-diff-visit-file--internal file nil + (if other-window + #'switch-to-buffer-other-window + #'pop-to-buffer-same-window))) (defun magit-diff-visit-file-other-window (file) - "From a diff, visit the corresponding file at the appropriate position. -The file is shown in another window. - -If the diff shows changes in the worktree, the index, or `HEAD', -then visit the actual file. Otherwise, when the diff is about an -older commit or a range, then visit the appropriate blob. - -If point is on a removed line, then visit the blob for the first -parent of the commit which removed that line, i.e. the last -commit where that line still existed. Otherwise visit the blob -for the commit whose changes are being shown." - (interactive (list (--if-let (magit-file-at-point) - (expand-file-name it) - (user-error "No file at point")))) - (magit-diff-visit-file file t)) - -(defvar magit-display-file-buffer-function - 'magit-display-file-buffer-traditional - "The function used by `magit-diff-visit-file' to display blob buffers. - -Other commands such as `magit-find-file' do not use this -function. Instead they use high-level functions to select the -window to be used to display the buffer. This variable and the -related functions are an experimental feature and should be -treated as such.") - -(defun magit-display-file-buffer (buffer) - (funcall magit-display-file-buffer-function buffer)) - -(defun magit-display-file-buffer-traditional (buffer) - "Display BUFFER in the current window. -With a prefix argument display it in another window. -Option `magit-display-file-buffer-function' controls -whether `magit-diff-visit-file' uses this function." - (if (or current-prefix-arg (get-buffer-window buffer)) - (pop-to-buffer buffer) - (switch-to-buffer buffer))) - -(defun magit-display-file-buffer-other-window (buffer) - "Display BUFFER in another window. -With a prefix argument display it in the current window. -Option `magit-display-file-buffer-function' controls -whether `magit-diff-visit-file' uses this function." - (if current-prefix-arg - (switch-to-buffer buffer) - (pop-to-buffer buffer))) - -(defun magit-diff-visit-file-worktree (file &optional other-window) - "From a diff, visit the corresponding file at the appropriate position. - -When the file is already being displayed in another window of the -same frame, then just select that window and adjust point. With -a prefix argument also display in another window. - -The actual file in the worktree is visited. The positions in the -hunk headers get less useful the \"older\" the changes are, and -as a result, jumping to the appropriate position gets less -reliable. - -Also see `magit-diff-visit-file' which visits the respective -blob, unless the diff shows changes in the worktree, the index, -or `HEAD'." - (interactive (list (or (magit-file-at-point) - (user-error "No file at point")) - current-prefix-arg)) - (magit-diff-visit-file file other-window t)) - -(defun magit-diff-visit--range-end () - (let ((rev (magit-diff--dwim))) - (if (symbolp rev) - rev - (setq rev (if (consp rev) - (cdr rev) - (cdr (magit-split-range rev)))) - (if (magit-rev-head-p rev) - 'unstaged - rev)))) + "From a diff visit the appropriate version of FILE in another window. +Like `magit-diff-visit-file' but use +`switch-to-buffer-other-window'." + (interactive (list (magit-file-at-point t t))) + (magit-diff-visit-file--internal file nil #'switch-to-buffer-other-window)) + +(defun magit-diff-visit-file-other-frame (file) + "From a diff visit the appropriate version of FILE in another frame. +Like `magit-diff-visit-file' but use +`switch-to-buffer-other-frame'." + (interactive (list (magit-file-at-point t t))) + (magit-diff-visit-file--internal file nil #'switch-to-buffer-other-frame)) + +;;;;; Worktree Variants + +(defun magit-diff-visit-worktree-file (file &optional other-window) + "From a diff visit the worktree version of FILE. + +Display the buffer in the selected window. With a prefix +argument OTHER-WINDOW display the buffer in another window +instead. + +Visit the worktree version of the appropriate file. The location +of point inside the diff determines which file is being visited. + +Unlike `magit-diff-visit-file' always visits the \"real\" file in +the working tree, i.e the \"current version\" of the file. + +In the file-visiting buffer also go to the line that corresponds +to the line that point is on in the diff. Lines that were added +or removed in the working tree, the index and other commits in +between are automatically accounted for." + (interactive (list (magit-file-at-point t t) current-prefix-arg)) + (magit-diff-visit-file--internal file t + (if other-window + #'switch-to-buffer-other-window + #'pop-to-buffer-same-window))) + +(defun magit-diff-visit-worktree-file-other-window (file) + "From a diff visit the worktree version of FILE in another window. +Like `magit-diff-visit-worktree-file' but use +`switch-to-buffer-other-window'." + (interactive (list (magit-file-at-point t t))) + (magit-diff-visit-file--internal file t #'switch-to-buffer-other-window)) + +(defun magit-diff-visit-worktree-file-other-frame (file) + "From a diff visit the worktree version of FILE in another frame. +Like `magit-diff-visit-worktree-file' but use +`switch-to-buffer-other-frame'." + (interactive (list (magit-file-at-point t t))) + (magit-diff-visit-file--internal file t #'switch-to-buffer-other-frame)) + +;;;;; Internal + +(defun magit-diff-visit-file--internal (file force-worktree fn) + "From a diff visit the appropriate version of FILE. +If FORCE-WORKTREE is non-nil, the visit the worktree version of +the file, even if the diff is about a committed change. USE FN +to display the buffer in some window." + (if (magit-file-accessible-directory-p file) + (magit-diff-visit-directory file force-worktree) + (pcase-let ((`(,buf ,pos) + (magit-diff-visit-file--noselect file force-worktree))) + (funcall fn buf) + (magit-diff-visit-file--setup buf pos) + buf))) -(defun magit-diff-visit--range-beginning () - (let ((rev (magit-diff--dwim))) - (cond ((consp rev) - (concat (cdr rev) "^")) - ((stringp rev) - (car (magit-split-range rev))) - (t - rev)))) +(defun magit-diff-visit-directory (directory &optional other-window) + "Visit DIRECTORY in some window. +Display the buffer in the selected window unless OTHER-WINDOW is +non-nil. If DIRECTORY is the top-level directory of the current +repository, then visit the containing directory using Dired and +in the Dired buffer put point on DIRECTORY. Otherwise display +the Magit-Status buffer for DIRECTORY." + (if (equal (magit-toplevel directory) + (magit-toplevel)) + (dired-jump other-window (concat directory "/.")) + (let ((display-buffer-overriding-action + (if other-window + '(nil (inhibit-same-window t)) + '(display-buffer-same-window)))) + (magit-status-setup-buffer directory)))) + +(defun magit-diff-visit-file--setup (buf pos) + (if-let ((win (get-buffer-window buf 'visible))) + (with-selected-window win + (when pos + (unless (<= (point-min) pos (point-max)) + (widen)) + (goto-char pos)) + (when (and buffer-file-name + (magit-anything-unmerged-p buffer-file-name)) + (smerge-start-session)) + (run-hooks 'magit-diff-visit-file-hook)) + (error "File buffer is not visible"))) + +(defun magit-diff-visit-file--noselect (&optional file goto-worktree) + (unless file + (setq file (magit-file-at-point t t))) + (let* ((hunk (magit-diff-visit--hunk)) + (goto-from (and hunk + (magit-diff-visit--goto-from-p hunk goto-worktree))) + (line (and hunk (magit-diff-hunk-line hunk goto-from))) + (col (and hunk (magit-diff-hunk-column hunk goto-from))) + (spec (magit-diff--dwim)) + (rev (if goto-from + (magit-diff-visit--range-from spec) + (magit-diff-visit--range-to spec))) + (buf (if (and (not goto-worktree) + (stringp rev)) + (magit-find-file-noselect rev file) + (or (get-file-buffer file) + (find-file-noselect file))))) + (if line + (with-current-buffer buf + (cond ((eq rev 'staged) + (setq line (magit-diff-visit--offset file nil line))) + ((and goto-worktree + (stringp rev)) + (setq line (magit-diff-visit--offset file rev line)))) + (list buf (save-restriction + (widen) + (goto-char (point-min)) + (forward-line (1- line)) + (move-to-column col) + (point)))) + (list buf nil)))) (defun magit-diff-visit--hunk () (when-let ((scope (magit-diff-scope))) @@ -1451,7 +1564,62 @@ or `HEAD'." (oref section value) section)))) -(defun magit-diff-visit--offset (file rev hunk-start line-offset) +(defun magit-diff-visit--goto-from-p (section in-worktree) + (and magit-diff-visit-previous-blob + (not in-worktree) + (not (oref section combined)) + (not (< (point) (oref section content))) + (= (char-after (line-beginning-position)) ?-))) + +(defun magit-diff-hunk-line (section goto-from) + (save-excursion + (goto-char (line-beginning-position)) + (with-slots (content combined from-ranges from-range to-range) section + (when (< (point) content) + (goto-char content) + (re-search-forward "^[-+]")) + (+ (car (if goto-from from-range to-range)) + (let ((prefix (if combined (length from-ranges) 1)) + (target (point)) + (offset 0)) + (goto-char content) + (while (< (point) target) + (unless (string-match-p + (if goto-from "\\+" "-") + (buffer-substring (point) (+ (point) prefix))) + (cl-incf offset)) + (forward-line)) + offset))))) + +(defun magit-diff-hunk-column (section goto-from) + (if (or (< (point) + (oref section content)) + (and (not goto-from) + (= (char-after (line-beginning-position)) ?-))) + 0 + (max 0 (- (+ (current-column) 2) + (length (oref section value)))))) + +(defun magit-diff-visit--range-from (spec) + (cond ((consp spec) + (concat (cdr spec) "^")) + ((stringp spec) + (car (magit-split-range spec))) + (t + spec))) + +(defun magit-diff-visit--range-to (spec) + (if (symbolp spec) + spec + (let ((rev (if (consp spec) + (cdr spec) + (cdr (magit-split-range spec))))) + (if (and magit-diff-visit-avoid-head-blob + (magit-rev-head-p spec)) + 'unstaged + rev)))) + +(defun magit-diff-visit--offset (file rev line) (let ((offset 0)) (with-temp-buffer (save-excursion @@ -1459,79 +1627,25 @@ or `HEAD'." (magit-git-insert "diff" rev "--" file))) (catch 'found (while (re-search-forward - "^@@ -\\([0-9]+\\),\\([0-9]+\\) \\+\\([0-9]+\\),\\([0-9]+\\) @@" + "^@@ -\\([0-9]+\\),\\([0-9]+\\) \\+\\([0-9]+\\),\\([0-9]+\\) @@.*\n" nil t) - (let* ((abeg (string-to-number (match-string 1))) - (alen (string-to-number (match-string 2))) - (bbeg (string-to-number (match-string 3))) - (blen (string-to-number (match-string 4))) - (aend (+ abeg alen)) - (bend (+ bbeg blen)) - (hend (+ hunk-start line-offset))) - (if (<= abeg hunk-start) - (if (or (>= aend hend) - (>= bend hend)) - (let ((line 0)) - (while (<= line alen) - (forward-line 1) - (cl-incf line) - (cond ((looking-at "^\\+") (cl-incf offset)) - ((looking-at "^-") (cl-decf offset))))) - (cl-incf offset (- blen alen))) + (let ((from-beg (string-to-number (match-string 1))) + (from-len (string-to-number (match-string 2))) + ( to-len (string-to-number (match-string 4)))) + (if (<= from-beg line) + (if (< (+ from-beg from-len) line) + (cl-incf offset (- to-len from-len)) + (let ((rest (- line from-beg))) + (while (> rest 0) + (pcase (char-after) + (?\s (cl-decf rest)) + (?- (cl-decf offset) (cl-decf rest)) + (?+ (cl-incf offset))) + (forward-line)))) (throw 'found nil)))))) - (+ hunk-start line-offset offset))) - -(defun magit-diff-hunk-line (section) - (let* ((value (oref section value)) - (prefix (- (length value) 2)) - (cpos (marker-position (oref section content))) - (stop (line-number-at-pos)) - (cstart (save-excursion (goto-char cpos) - (line-number-at-pos))) - (prior (and (= (length value) 3) - (save-excursion (goto-char (line-beginning-position)) - (looking-at "-")))) - (offset 0) - (line (if prior - (cadr value) - (car (last value))))) - (string-match (format "^%s\\([0-9]+\\)" (if prior "-" "\\+")) line) - (setq line (string-to-number (match-string 1 line))) - (when (> cstart stop) - (save-excursion - (goto-char cpos) - (re-search-forward "^[-+]") - (setq stop (line-number-at-pos)))) - (save-excursion - (goto-char cpos) - (while (< (line-number-at-pos) stop) - (unless (string-match-p - (if prior "\\+" "-") - (buffer-substring (point) (+ (point) prefix))) - (cl-incf offset)) - (forward-line))) - (list line offset))) + (+ line offset))) -(defun magit-diff-hunk-column (section visit-beginning) - (if (or (< (point) - (oref section content)) - (and (not visit-beginning) - (save-excursion (beginning-of-line) (looking-at-p "-")))) - 0 - (max 0 (- (+ (current-column) 2) - (length (oref section value)))))) - -(defun magit-diff-visit-directory (directory &optional other-window) - (if (equal (magit-toplevel directory) - (magit-toplevel)) - (dired-jump other-window (concat directory "/.")) - (let ((display-buffer-overriding-action - (if other-window - '(nil (inhibit-same-window t)) - '(display-buffer-same-window)))) - (magit-status-internal directory)))) - -;;;; Scroll commands +;;;; Scroll Commands (defun magit-diff-show-or-scroll-up () "Update the commit or diff buffer for the thing at point. @@ -1561,36 +1675,34 @@ commit or stash at point, then prompt for a commit." (magit-blame-mode (setq rev (oref (magit-current-blame-chunk) orig-rev)) (setq cmd 'magit-show-commit) - (setq buf (magit-mode-get-buffer 'magit-revision-mode))) + (setq buf (magit-get-mode-buffer 'magit-revision-mode))) ((derived-mode-p 'git-rebase-mode) - (save-excursion - (goto-char (line-beginning-position)) - (--if-let (and git-rebase-line - (looking-at git-rebase-line) - (match-string 2)) - (progn (setq rev it) - (setq cmd 'magit-show-commit) - (setq buf (magit-mode-get-buffer 'magit-revision-mode))) - (user-error "No commit on this line")))) + (with-slots (action-type target) + (git-rebase-current-line) + (if (not (eq action-type 'commit)) + (user-error "No commit on this line") + (setq rev target) + (setq cmd 'magit-show-commit) + (setq buf (magit-get-mode-buffer 'magit-revision-mode))))) (t (magit-section-case (branch (setq rev (magit-ref-maybe-qualify (oref it value))) (setq cmd 'magit-show-commit) - (setq buf (magit-mode-get-buffer 'magit-revision-mode))) + (setq buf (magit-get-mode-buffer 'magit-revision-mode))) (commit (setq rev (oref it value)) (setq cmd 'magit-show-commit) - (setq buf (magit-mode-get-buffer 'magit-revision-mode))) + (setq buf (magit-get-mode-buffer 'magit-revision-mode))) (stash (setq rev (oref it value)) (setq cmd 'magit-stash-show) - (setq buf (magit-mode-get-buffer 'magit-stash-mode)))))) + (setq buf (magit-get-mode-buffer 'magit-stash-mode)))))) (if rev (if (and buf (setq win (get-buffer-window buf)) (with-current-buffer buf - (and (equal rev (car magit-refresh-args)) + (and (equal rev magit-buffer-revision) (equal (magit-rev-parse rev) magit-buffer-revision-hash)))) (with-selected-window win @@ -1647,45 +1759,50 @@ Staging and applying changes is documented in info node (setq imenu-prev-index-position-function 'magit-imenu--diff-prev-index-position-function) (setq imenu-extract-index-name-function - 'magit-imenu--diff-extract-index-name-function) - (setq-local bookmark-make-record-function - 'magit-bookmark--diff-make-record)) + 'magit-imenu--diff-extract-index-name-function)) -(defun magit-diff-refresh-buffer (rev-or-range const _args files) - "Refresh the current `magit-diff-mode' buffer. +(put 'magit-diff-mode 'magit-diff-default-arguments + '("--stat" "--no-ext-diff")) -In such buffers the buffer-local value of `magit-refresh-args' -has the same form as the arguments of this function. The value -is set in `magit-mode-setup'." +(defun magit-diff-setup-buffer (range typearg args files &optional locked) + (require 'magit) + (magit-setup-buffer #'magit-diff-mode locked + (magit-buffer-range range) + (magit-buffer-typearg typearg) + (magit-buffer-diff-args args) + (magit-buffer-diff-files files))) + +(defun magit-diff-refresh-buffer () + "Refresh the current `magit-diff-mode' buffer." (magit-set-header-line-format - (if (member "--no-index" const) - (apply #'format "Differences between %s and %s" files) - (concat (if rev-or-range + (if (equal magit-buffer-typearg "--no-index") + (apply #'format "Differences between %s and %s" magit-buffer-diff-files) + (concat (if magit-buffer-range (if (string-match-p "\\(\\.\\.\\|\\^-\\)" - rev-or-range) - (format "Changes in %s" rev-or-range) - (format "Changes from %s to working tree" rev-or-range)) - (if (member "--cached" const) + magit-buffer-range) + (format "Changes in %s" magit-buffer-range) + (format "Changes from %s to working tree" magit-buffer-range)) + (if (equal magit-buffer-typearg "--cached") "Staged changes" "Unstaged changes")) - (pcase (length files) + (pcase (length magit-buffer-diff-files) (0) - (1 (concat " in file " (car files))) + (1 (concat " in file " (car magit-buffer-diff-files))) (_ (concat " in files " - (mapconcat #'identity files ", "))))))) + (mapconcat #'identity magit-buffer-diff-files ", "))))))) + (setq magit-buffer-range-hashed + (and magit-buffer-range (magit-hash-range magit-buffer-range))) (magit-insert-section (diffbuf) - (magit-run-section-hook 'magit-diff-sections-hook rev-or-range))) + (magit-run-section-hook 'magit-diff-sections-hook))) -(defun magit-insert-diff (rev-or-range) - "Insert the diff into this `magit-diff-mode' buffer." - (let ((magit-git-global-arguments - (remove "--literal-pathspecs" magit-git-global-arguments))) - (magit-git-wash #'magit-diff-wash-diffs - "diff" rev-or-range "-p" "--no-prefix" - (and (member "--stat" (nth 2 magit-refresh-args)) "--numstat") - (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args) "--" - (nth 3 magit-refresh-args)))) +(cl-defmethod magit-buffer-value (&context (major-mode magit-diff-mode)) + (nconc (cond (magit-buffer-range + (delq nil (list magit-buffer-range magit-buffer-typearg))) + ((equal magit-buffer-typearg "--cached") + (list 'staged)) + (t + (list 'unstaged magit-buffer-typearg))) + (and magit-buffer-diff-files (cons "--" magit-buffer-diff-files)))) (defvar magit-file-section-map (let ((map (make-sparse-keymap))) @@ -1736,6 +1853,43 @@ is set in `magit-mode-setup'." "\\(\\+*\\)" ; add "\\(-*\\)$")) ; del +(defvar magit-diff--reset-non-color-moved + (list + "-c" "color.diff.context=normal" + "-c" "color.diff.plain=normal" ; historical synonym for context + "-c" "color.diff.meta=normal" + "-c" "color.diff.frag=normal" + "-c" "color.diff.func=normal" + "-c" "color.diff.old=normal" + "-c" "color.diff.new=normal" + "-c" "color.diff.commit=normal" + "-c" "color.diff.whitespace=normal" + ;; "git-range-diff" does not support "--color-moved", so we don't + ;; need to reset contextDimmed, oldDimmed, newDimmed, contextBold, + ;; oldBold, and newBold. + )) + +(defun magit-insert-diff () + "Insert the diff into this `magit-diff-mode' buffer." + (magit--insert-diff + "diff" magit-buffer-range "-p" "--no-prefix" + (and (member "--stat" magit-buffer-diff-args) "--numstat") + magit-buffer-typearg + magit-buffer-diff-args "--" + magit-buffer-diff-files)) + +(defun magit--insert-diff (&rest args) + (declare (indent 0)) + (let ((magit-git-global-arguments + (remove "--literal-pathspecs" magit-git-global-arguments))) + (setq args (-flatten args)) + (when (cl-member-if (lambda (arg) (string-prefix-p "--color-moved" arg)) args) + (push "--color=always" (cdr args)) + (setq magit-git-global-arguments + (append magit-diff--reset-non-color-moved + magit-git-global-arguments))) + (magit-git-wash #'magit-diff-wash-diffs args))) + (defun magit-diff-wash-diffs (args &optional limit) (when (member "--stat" args) (magit-diff-wash-diffstat)) @@ -1799,6 +1953,9 @@ section or a child thereof." (if (looking-at "^$") (forward-line) (insert "\n")))))) (defun magit-diff-wash-diff (args) + (when (cl-member-if (lambda (arg) (string-prefix-p "--color-moved" arg)) args) + (require 'ansi-color) + (ansi-color-apply-on-region (point-min) (point-max))) (cond ((looking-at "^Submodule") (magit-diff-wash-submodule)) @@ -1879,8 +2036,7 @@ section or a child thereof." (setq file (magit-decode-git-path file)) ;; KLUDGE `git-log' ignores `--no-prefix' when `-L' is used. (when (and (derived-mode-p 'magit-log-mode) - (--first (string-match-p "\\`-L" it) - (nth 1 magit-refresh-args))) + (--first (string-match-p "\\`-L" it) magit-buffer-log-args)) (setq file (substring file 2)) (when orig (setq orig (substring orig 2)))) @@ -1901,7 +2057,8 @@ section or a child thereof." (oset section header header) (when modes (magit-insert-section (hunk) - (insert modes))) + (insert modes) + (magit-insert-heading))) (magit-wash-sequence #'magit-diff-wash-hunk))) (defun magit-diff-wash-submodule () @@ -1968,16 +2125,28 @@ section or a child thereof." (defun magit-diff-wash-hunk () (when (looking-at "^@\\{2,\\} \\(.+?\\) @\\{2,\\}\\(?: \\(.*\\)\\)?") - (let ((heading (match-string 0)) - (value (cons (match-string 2) (split-string (match-string 1))))) + (let* ((heading (match-string 0)) + (ranges (mapcar (lambda (str) + (mapcar (lambda (n) (string-to-number n)) + (split-string (substring str 1) ","))) + (split-string (match-string 1)))) + (about (match-string 2)) + (combined (= (length ranges) 3)) + (value (cons about ranges))) (magit-delete-line) - (magit-insert-section it (hunk value) + (magit-insert-section section (hunk value) (insert (propertize (concat heading "\n") 'face 'magit-diff-hunk-heading)) (magit-insert-heading) (while (not (or (eobp) (looking-at "^[^-+\s\\]"))) (forward-line)) - (oset it end (point)) - (oset it washer 'magit-diff-paint-hunk))) + (oset section end (point)) + (oset section washer 'magit-diff-paint-hunk) + (oset section combined combined) + (if combined + (oset section from-ranges (butlast ranges)) + (oset section from-range (car ranges))) + (oset section to-range (car (last ranges))) + (oset section about about))) t)) (defun magit-diff-expansion-threshold (section) @@ -2011,45 +2180,49 @@ Staging and applying changes is documented in info node \\{magit-revision-mode-map}" :group 'magit-revision - (hack-dir-local-variables-non-file-buffer) - (setq-local bookmark-make-record-function - 'magit-bookmark--revision-make-record)) + (hack-dir-local-variables-non-file-buffer)) + +(put 'magit-revision-mode 'magit-diff-default-arguments + '("--stat" "--no-ext-diff")) -(defun magit-revision-refresh-buffer (rev __const _args files) +(defun magit-revision-setup-buffer (rev args files) + (magit-setup-buffer #'magit-revision-mode nil + (magit-buffer-revision rev) + (magit-buffer-range (format "%s^..%s" rev rev)) + (magit-buffer-diff-args args) + (magit-buffer-diff-files files))) + +(defun magit-revision-refresh-buffer () (magit-set-header-line-format - (concat (capitalize (magit-object-type rev)) - " " - rev - (pcase (length files) + (concat (capitalize (magit-object-type magit-buffer-revision)) + " " magit-buffer-revision + (pcase (length magit-buffer-diff-files) (0) - (1 (concat " limited to file " (car files))) + (1 (concat " limited to file " (car magit-buffer-diff-files))) (_ (concat " limited to files " - (mapconcat #'identity files ", ")))))) - (setq magit-buffer-revision-hash (magit-rev-parse rev)) + (mapconcat #'identity magit-buffer-diff-files ", ")))))) + (setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision)) (magit-insert-section (commitbuf) - (magit-run-section-hook 'magit-revision-sections-hook rev))) + (magit-run-section-hook 'magit-revision-sections-hook))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-revision-mode)) + (cons magit-buffer-revision magit-buffer-diff-files)) -(defun magit-insert-revision-diff (rev) +(defun magit-insert-revision-diff () "Insert the diff into this `magit-revision-mode' buffer." - (let ((magit-git-global-arguments - (remove "--literal-pathspecs" magit-git-global-arguments))) - ;; Before v2.2.0, "--format=" did not mean "no output". - ;; Instead the default format was used. So use "--format=%n" - ;; and then delete the empty lines. - (magit-git-wash (lambda (args) - (delete-region (point) (progn (forward-line 3) (point))) - (magit-diff-wash-diffs args)) - "show" "-p" "--cc" "--format=%n" "--no-prefix" - (and (member "--stat" (nth 2 magit-refresh-args)) "--numstat") - (nth 2 magit-refresh-args) (concat rev "^{commit}") "--" - (nth 3 magit-refresh-args)))) - -(defun magit-insert-revision-tag (rev) + (magit--insert-diff + "show" "-p" "--cc" "--format=" "--no-prefix" + (and (member "--stat" magit-buffer-diff-args) "--numstat") + magit-buffer-diff-args + (concat magit-buffer-revision "^{commit}") + "--" magit-buffer-diff-files)) + +(defun magit-insert-revision-tag () "Insert tag message and headers into a revision buffer. This function only inserts anything when `magit-show-commit' is called with a tag as argument, when that is called with a commit or a ref which is not a branch, then it inserts nothing." - (when (equal (magit-object-type rev) "tag") + (when (equal (magit-object-type magit-buffer-revision) "tag") (magit-insert-section (taginfo) (let ((beg (point))) ;; "git verify-tag -v" would output what we need, but the gpg @@ -2059,7 +2232,7 @@ or a ref which is not a branch, then it inserts nothing." ;; instead, which inserts the signature instead of verifying ;; it. We remove that later and then insert the verification ;; output using "git verify-tag" (without the "-v"). - (magit-git-insert "cat-file" "tag" rev) + (magit-git-insert "cat-file" "tag" magit-buffer-revision) (goto-char beg) (forward-line 3) (delete-region beg (point))) @@ -2076,7 +2249,8 @@ or a ref which is not a branch, then it inserts nothing." (re-search-forward "-----END PGP SIGNATURE-----") (delete-region beg (point))) (insert ?\n) - (process-file magit-git-executable nil t nil "verify-tag" rev)) + (process-file magit-git-executable nil t nil + "verify-tag" magit-buffer-revision)) (goto-char (point-max))) (insert ?\n)))) @@ -2086,15 +2260,15 @@ or a ref which is not a branch, then it inserts nothing." map) "Keymap for `commit-message' sections.") -(defun magit-insert-revision-message (rev) +(defun magit-insert-revision-message () "Insert the commit message into a revision buffer." (magit-insert-section section (commit-message) (oset section heading-highlight-face 'magit-diff-hunk-heading-highlight) - (let ((beg (point))) - (insert (save-excursion ; The risky var query can move point. - (with-temp-buffer - (magit-rev-insert-format "%B" rev) - (magit-revision--wash-message)))) + (let ((beg (point)) + (rev magit-buffer-revision)) + (insert (with-temp-buffer + (magit-rev-insert-format "%B" rev) + (magit-revision--wash-message))) (if (= (point) (+ beg 2)) (progn (backward-delete-char 2) (insert "(no message)\n")) @@ -2149,14 +2323,15 @@ or a ref which is not a branch, then it inserts nothing." 'magit-keyword)))))) (goto-char (point-max)))))) -(defun magit-insert-revision-notes (rev) +(defun magit-insert-revision-notes () "Insert commit notes into a revision buffer." (let* ((var "core.notesRef") (def (or (magit-get var) "refs/notes/commits"))) (dolist (ref (or (magit-list-active-notes-refs))) (magit-insert-section section (notes ref (not (equal ref def))) (oset section heading-highlight-face 'magit-diff-hunk-heading-highlight) - (let ((beg (point))) + (let ((beg (point)) + (rev magit-buffer-revision)) (insert (with-temp-buffer (magit-git-insert "-c" (concat "core.notesRef=" ref) "notes" "show" rev) @@ -2185,20 +2360,21 @@ or a ref which is not a branch, then it inserts nothing." (font-lock-ensure)) (buffer-string)) -(defun magit-insert-revision-headers (rev) +(defun magit-insert-revision-headers () "Insert headers about the commit into a revision buffer." (magit-insert-section (headers) - ;; Before v2.2.0, "%D" was not supported. - (--when-let (magit-rev-format "%d" rev "--decorate=full") + (--when-let (magit-rev-format "%D" magit-buffer-revision "--decorate=full") (insert (magit-format-ref-labels it) ?\s)) - (insert (propertize (magit-rev-parse (concat rev "^{commit}")) - 'face 'magit-hash)) + (insert (propertize + (magit-rev-parse (concat magit-buffer-revision "^{commit}")) + 'face 'magit-hash)) (magit-insert-heading) (let ((beg (point))) - (magit-rev-insert-format magit-revision-headers-format rev) - (magit-insert-revision-gravatars rev beg)) + (magit-rev-insert-format magit-revision-headers-format + magit-buffer-revision) + (magit-insert-revision-gravatars magit-buffer-revision beg)) (when magit-revision-insert-related-refs - (dolist (parent (magit-commit-parents rev)) + (dolist (parent (magit-commit-parents magit-buffer-revision)) (magit-insert-section (commit parent) (let ((line (magit-rev-format "%h %s" parent))) (string-match "^\\([^ ]+\\) \\(.*\\)" line) @@ -2207,12 +2383,12 @@ or a ref which is not a branch, then it inserts nothing." (insert (propertize hash 'face 'magit-hash)) (insert " " msg "\n"))))) (magit--insert-related-refs - rev "--merged" "Merged" + magit-buffer-revision "--merged" "Merged" (eq magit-revision-insert-related-refs 'all)) (magit--insert-related-refs - rev "--contains" "Contained" + magit-buffer-revision "--contains" "Contained" (eq magit-revision-insert-related-refs '(all mixed))) - (when-let ((follows (magit-get-current-tag rev t))) + (when-let ((follows (magit-get-current-tag magit-buffer-revision t))) (let ((tag (car follows)) (cnt (cadr follows))) (magit-insert-section (tag tag) @@ -2220,7 +2396,7 @@ or a ref which is not a branch, then it inserts nothing." (propertize tag 'face 'magit-tag) (propertize (number-to-string cnt) 'face 'magit-branch-local)))))) - (when-let ((precedes (magit-get-next-tag rev t))) + (when-let ((precedes (magit-get-next-tag magit-buffer-revision t))) (let ((tag (car precedes)) (cnt (cadr precedes))) (magit-insert-section (tag tag) @@ -2264,17 +2440,18 @@ or a ref which is not a branch, then it inserts nothing." (save-excursion (goto-char beg) (when (re-search-forward regexp nil t) - (let* ((column (length (match-string 0))) - (font-obj (query-font (font-at (point) (get-buffer-window)))) - (size (* 2 (+ (aref font-obj 4) - (aref font-obj 5)))) - (align-to (+ column - (ceiling (/ size (aref font-obj 7) 1.0)) - 1)) - (gravatar-size (- size 2))) - (ignore-errors ; service may be unreachable - (gravatar-retrieve email 'magit-insert-revision-gravatar-cb - (list rev (point-marker) align-to column))))))) + (when-let ((window (get-buffer-window))) + (let* ((column (length (match-string 0))) + (font-obj (query-font (font-at (point) window))) + (size (* 2 (+ (aref font-obj 4) + (aref font-obj 5)))) + (align-to (+ column + (ceiling (/ size (aref font-obj 7) 1.0)) + 1)) + (gravatar-size (- size 2))) + (ignore-errors ; service may be unreachable + (gravatar-retrieve email 'magit-insert-revision-gravatar-cb + (list rev (point-marker) align-to column)))))))) (defun magit-insert-revision-gravatar-cb (image rev marker align-to column) (unless (eq image 'error) @@ -2285,7 +2462,7 @@ or a ref which is not a branch, then it inserts nothing." ;; The buffer might display another revision by now or ;; it might have been refreshed, in which case another ;; process might already have inserted the image. - (when (and (equal rev (car magit-refresh-args)) + (when (and (equal rev magit-buffer-revision) (not (eq (car-safe (car-safe (get-text-property (point) 'display))) @@ -2305,6 +2482,35 @@ or a ref which is not a branch, then it inserts nothing." (insert (propertize " " 'display bot)) (insert (propertize " " 'display align)))))))))) +;;; Merge-Preview Mode + +(define-derived-mode magit-merge-preview-mode magit-diff-mode "Magit Merge" + "Mode for previewing a merge." + :group 'magit-diff + (hack-dir-local-variables-non-file-buffer)) + +(put 'magit-merge-preview-mode 'magit-diff-default-arguments + '("--no-ext-diff")) + +(defun magit-merge-preview-setup-buffer (rev) + (magit-setup-buffer #'magit-merge-preview-mode nil + (magit-buffer-revision rev) + (magit-buffer-range (format "%s^..%s" rev rev)))) + +(defun magit-merge-preview-refresh-buffer () + (let* ((branch (magit-get-current-branch)) + (head (or branch (magit-rev-verify "HEAD")))) + (magit-set-header-line-format (format "Preview merge of %s into %s" + magit-buffer-revision + (or branch "HEAD"))) + (magit-insert-section (diffbuf) + (magit--insert-diff + "merge-tree" (magit-git-string "merge-base" head magit-buffer-revision) + head magit-buffer-revision)))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-merge-preview-mode)) + magit-buffer-revision) + ;;; Diff Sections (defvar magit-unstaged-section-map @@ -2322,9 +2528,9 @@ or a ref which is not a branch, then it inserts nothing." "Insert section showing unstaged changes." (magit-insert-section (unstaged) (magit-insert-heading "Unstaged changes:") - (magit-git-wash #'magit-diff-wash-diffs - "diff" magit-diff-section-arguments "--no-prefix" - "--" magit-diff-section-file-args))) + (magit--insert-diff + "diff" magit-buffer-diff-args "--no-prefix" + "--" magit-buffer-diff-files))) (defvar magit-staged-section-map (let ((map (make-sparse-keymap))) @@ -2344,9 +2550,9 @@ or a ref which is not a branch, then it inserts nothing." (unless (magit-bare-repo-p) (magit-insert-section (staged) (magit-insert-heading "Staged changes:") - (magit-git-wash #'magit-diff-wash-diffs - "diff" "--cached" magit-diff-section-arguments "--no-prefix" - "--" magit-diff-section-file-args)))) + (magit--insert-diff + "diff" "--cached" magit-buffer-diff-args "--no-prefix" + "--" magit-buffer-diff-files)))) ;;; Diff Type @@ -2376,15 +2582,15 @@ Do not confuse this with `magit-diff-scope' (which see)." (--when-let (or section (magit-current-section)) (cond ((derived-mode-p 'magit-revision-mode 'magit-stash-mode) 'committed) ((derived-mode-p 'magit-diff-mode) - (let ((range (nth 0 magit-refresh-args)) - (const (nth 1 magit-refresh-args))) - (cond ((member "--no-index" const) 'undefined) + (let ((range magit-buffer-range) + (const magit-buffer-typearg)) + (cond ((equal const "--no-index") 'undefined) ((or (not range) (magit-rev-eq range "HEAD")) - (if (member "--cached" const) + (if (equal const "--cached") 'staged 'unstaged)) - ((member "--cached" const) + ((equal const "--cached") (if (magit-rev-head-p range) 'staged 'undefined)) ; i.e. committed and staged @@ -2863,10 +3069,11 @@ last (visual) lines of the region." ((equal op (match-string-no-properties 1)) (push (concat " " (match-string-no-properties 2)) patch))) (forward-line))) - (with-temp-buffer - (insert (mapconcat 'identity (reverse patch) "")) - (diff-fixup-modifs (point-min) (point-max)) - (setq patch (buffer-string))) + (let ((buffer-list-update-hook nil)) ; #3759 + (with-temp-buffer + (insert (mapconcat #'identity (reverse patch) "")) + (diff-fixup-modifs (point-min) (point-max)) + (setq patch (buffer-string)))) patch)) ;;; _ diff --git a/elpa/magit-20190122.503/magit-ediff.el b/elpa/magit-20190514.1814/magit-ediff.el similarity index 95% rename from elpa/magit-20190122.503/magit-ediff.el rename to elpa/magit-20190514.1814/magit-ediff.el index 2ee4cf6e..fdcb0133 100644 --- a/elpa/magit-20190122.503/magit-ediff.el +++ b/elpa/magit-20190514.1814/magit-ediff.el @@ -103,19 +103,20 @@ tree at the time of stashing." (defvar magit-ediff-previous-winconf nil) -;;;###autoload (autoload 'magit-ediff-popup "magit-ediff" nil t) -(magit-define-popup magit-ediff-popup - "Popup console for ediff commands." - :actions '((?E "Dwim" magit-ediff-dwim) - (?u "Show unstaged" magit-ediff-show-unstaged) - (?s "Stage" magit-ediff-stage) - (?i "Show staged" magit-ediff-show-staged) - (?m "Resolve" magit-ediff-resolve) - (?w "Show worktree" magit-ediff-show-working-tree) - (?r "Diff range" magit-ediff-compare) - (?c "Show commit" magit-ediff-show-commit) nil - (?z "Show stash" magit-ediff-show-stash)) - :max-action-columns 2) +;;;###autoload (autoload 'magit-ediff "magit-ediff" nil) +(define-transient-command magit-ediff () + "Show differences using the Ediff package." + :info-manual "(ediff)" + ["Ediff" + [("E" "Dwim" magit-ediff-dwim) + ("s" "Stage" magit-ediff-stage) + ("m" "Resolve" magit-ediff-resolve)] + [("u" "Show unstaged" magit-ediff-show-unstaged) + ("i" "Show staged" magit-ediff-show-staged) + ("w" "Show worktree" magit-ediff-show-working-tree)] + [("c" "Show commit" magit-ediff-show-commit) + ("r" "Show range" magit-ediff-compare) + ("z" "Show stash" magit-ediff-show-stash)]]) ;;;###autoload (defun magit-ediff-resolve (file) @@ -159,13 +160,13 @@ conflicts, including those already resolved by Git, use "Stage and unstage changes to FILE using Ediff. FILE has to be relative to the top directory of the repository." (interactive - (list (magit-completing-read "Selectively stage file" - (magit-tracked-files) nil nil nil nil - (magit-current-file)))) + (let ((files (magit-tracked-files))) + (list (magit-completing-read "Selectively stage file" files nil t nil nil + (car (member (magit-current-file) files)))))) (magit-with-toplevel (let* ((conf (current-window-configuration)) (bufA (magit-get-revision-buffer "HEAD" file)) - (bufB (get-buffer (concat file ".~{index}~"))) + (bufB (magit-get-revision-buffer "{index}" file)) (bufBrw (and bufB (with-current-buffer bufB (not buffer-read-only)))) (bufC (get-file-buffer file)) (fileBufC (or bufC (find-file-noselect file))) @@ -316,7 +317,7 @@ mind at all, then it asks the user for a command to run." (pcase (magit-diff-type) (`committed (pcase-let ((`(,a ,b) (magit-ediff-compare--read-revisions - (car magit-refresh-args)))) + magit-buffer-range))) (setq revA a) (setq revB b))) ((guard (not magit-ediff-dwim-show-on-hunks)) diff --git a/elpa/magit-20190122.503/magit-extras.el b/elpa/magit-20190514.1814/magit-extras.el similarity index 93% rename from elpa/magit-20190122.503/magit-extras.el rename to elpa/magit-20190514.1814/magit-extras.el index 154aeba8..4ae8b19a 100644 --- a/elpa/magit-20190122.503/magit-extras.el +++ b/elpa/magit-20190514.1814/magit-extras.el @@ -154,12 +154,11 @@ is no file at point, then instead visit `default-directory'." (not (member "--follow" args)) (not (cdr files))) (push "--follow" args)) - (magit-mode-setup-internal - #'magit-log-mode - (list (list (or (magit-get-current-branch) "HEAD")) - args - (let ((default-directory topdir)) - (mapcar #'file-relative-name files))) + (magit-log-setup-buffer + (list (or (magit-get-current-branch) "HEAD")) + args + (let ((default-directory topdir)) + (mapcar #'file-relative-name files)) magit-log-buffer-file-locked)) (magit--not-inside-repository-error))) @@ -257,15 +256,9 @@ it acts on the current hunk in a Magit buffer instead of on a position in a file-visiting buffer." (interactive (list current-prefix-arg (prompt-for-change-log-name))) - (let (buf pos) - (save-window-excursion - (call-interactively #'magit-diff-visit-file) - (setq buf (current-buffer)) - (setq pos (point))) - (save-excursion - (with-current-buffer buf - (goto-char pos) - (add-change-log-entry whoami file-name other-window))))) + (pcase-let ((`(,buf ,pos) (magit-diff-visit-file--noselect))) + (magit--with-temp-position buf pos + (add-change-log-entry whoami file-name other-window)))) ;;;###autoload (defun magit-add-change-log-entry-other-window (&optional whoami file-name) @@ -322,7 +315,7 @@ points at it) otherwise." (put 'magit-edit-line-commit 'disabled t) ;;;###autoload -(defun magit-diff-edit-hunk-commit () +(defun magit-diff-edit-hunk-commit (file) "From a hunk, edit the respective commit and visit the file. First visit the file being modified by the hunk at the correct @@ -339,13 +332,11 @@ to be visited. Neither the blob nor the file buffer are killed when finishing the rebase. If that is undesirable, then it might be better to use `magit-rebase-edit-command' instead of this command." - (interactive) + (interactive (list (magit-file-at-point t t))) (let ((magit-diff-visit-previous-blob nil)) - (magit-diff-visit-file (--if-let (magit-file-at-point) - (expand-file-name it) - (user-error "No file at point")) - nil 'switch-to-buffer)) - (magit-edit-line-commit)) + (with-current-buffer + (magit-diff-visit-file--internal file nil #'pop-to-buffer-same-window) + (magit-edit-line-commit)))) (put 'magit-diff-edit-hunk-commit 'disabled t) @@ -624,21 +615,14 @@ above." (interactive) (if (use-region-p) (copy-region-as-kill nil nil 'region) - (when-let ((rev (cond ((memq major-mode '(magit-cherry-mode - magit-log-select-mode - magit-reflog-mode - magit-refs-mode - magit-revision-mode - magit-stash-mode - magit-stashes-mode)) - (car magit-refresh-args)) - ((memq major-mode '(magit-diff-mode - magit-log-mode)) - (let ((r (caar magit-refresh-args))) - (if (string-match "\\.\\.\\.?\\(.+\\)" r) - (match-string 1 r) - r))) - ((eq major-mode 'magit-status-mode) "HEAD")))) + (when-let ((rev (or magit-buffer-revision + (cl-case major-mode + (magit-diff-mode + (if (string-match "\\.\\.\\.?\\(.+\\)" + magit-buffer-range) + (match-string 1 magit-buffer-range) + magit-buffer-range)) + (magit-status-mode "HEAD"))))) (when (magit-commit-p rev) (setq rev (magit-rev-parse rev)) (push (list rev default-directory) magit-revision-stack) diff --git a/elpa/magit-20190122.503/magit-fetch.el b/elpa/magit-20190514.1814/magit-fetch.el similarity index 59% rename from elpa/magit-20190122.503/magit-fetch.el rename to elpa/magit-20190514.1814/magit-fetch.el index 81b1a82b..7557bb26 100644 --- a/elpa/magit-20190122.503/magit-fetch.el +++ b/elpa/magit-20190514.1814/magit-fetch.el @@ -40,48 +40,79 @@ Ignored for Git versions before v2.8.0." ;;; Commands -;;;###autoload (autoload 'magit-fetch-popup "magit-fetch" nil t) -(magit-define-popup magit-fetch-popup - "Popup console for fetch commands." +;;;###autoload (autoload 'magit-fetch "magit-fetch" nil t) +(define-transient-command magit-fetch () + "Fetch from another repository." :man-page "git-fetch" - :switches '((?p "Prune deleted branches" "--prune")) - :actions '("Configure" - (?C "variables..." magit-branch-config-popup) - "Fetch from" - (?p magit-get-push-remote magit-fetch-from-pushremote) - (?u magit-get-remote magit-fetch-from-upstream) - (?e "elsewhere" magit-fetch-other) - (?a "all remotes" magit-fetch-all) - "Fetch" - (?o "another branch" magit-fetch-branch) - (?r "explicit refspec" magit-fetch-refspec) - (?m "submodules" magit-fetch-modules)) - :default-action 'magit-fetch - :max-action-columns 1) + ["Arguments" + ("-p" "Prune deleted branches" ("-p" "--prune"))] + ["Fetch from" + ("p" magit-fetch-from-pushremote) + ("u" magit-fetch-from-upstream) + ("e" "elsewhere" magit-fetch-other) + ("a" "all remotes" magit-fetch-all)] + ["Fetch" + ("o" "another branch" magit-fetch-branch) + ("r" "explicit refspec" magit-fetch-refspec) + ("m" "submodules" magit-fetch-modules)] + ["Configure" + ("C" "variables..." magit-branch-configure)]) + +(defun magit-fetch-arguments () + (transient-args 'magit-fetch)) (defun magit-git-fetch (remote args) (run-hooks 'magit-credential-hook) (magit-run-git-async "fetch" remote args)) -;;;###autoload -(defun magit-fetch-from-pushremote (args) - "Fetch from the push-remote of the current branch." - (interactive (list (magit-fetch-arguments))) - (--if-let (magit-get-push-remote) - (magit-git-fetch it args) - (--if-let (magit-get-current-branch) - (user-error "No push-remote is configured for %s" it) - (user-error "No branch is checked out")))) +;;;###autoload (autoload 'magit-fetch-from-pushremote "magit-fetch" nil t) +(define-suffix-command magit-fetch-from-pushremote (args) + "Fetch from the current push-remote. -;;;###autoload -(defun magit-fetch-from-upstream (args) - "Fetch from the upstream repository of the current branch." +When the push-remote is not configured, then read the push-remote +from the user, set it, and then fetch from it. With a prefix +argument the push-remote can be changed before fetching from it." + :description 'magit-fetch--pushremote-description (interactive (list (magit-fetch-arguments))) - (--if-let (magit-get-remote) - (magit-git-fetch it args) - (--if-let (magit-get-current-branch) - (user-error "No upstream is configured for %s" it) - (user-error "No branch is checked out")))) + (let ((remote (magit-get-push-remote))) + (when (or current-prefix-arg + (not (member remote (magit-list-remotes)))) + (let ((var (magit--push-remote-variable))) + (setq remote + (magit-read-remote (format "Set %s and fetch from there" var))) + (magit-set remote var))) + (magit-git-fetch remote args))) + +(defun magit-fetch--pushremote-description () + (let* ((branch (magit-get-current-branch)) + (remote (magit-get-push-remote branch)) + (v (magit--push-remote-variable branch t))) + (cond + ((member remote (magit-list-remotes)) remote) + (remote + (format "%s, replacing invalid" v)) + (t + (format "%s, setting that" v))))) + +;;;###autoload (autoload 'magit-fetch-from-upstream "magit-fetch" nil t) +(define-suffix-command magit-fetch-from-upstream (remote args) + "Fetch from the \"current\" remote, usually the upstream. + +If the upstream is configured for the current branch and names +an existing remote, then use that. Otherwise try to use another +remote: If only a single remote is configured, then use that. +Otherwise if a remote named \"origin\" exists, then use that. + +If no remote can be determined, then this command is not available +from the `magit-fetch' transient prefix and invoking it directly +results in an error." + :if (lambda () (magit-get-current-remote t)) + :description (lambda () (magit-get-current-remote t)) + (interactive (list (magit-get-current-remote t) + (magit-fetch-arguments))) + (unless remote + (error "The \"current\" remote could not be determined")) + (magit-git-fetch remote args)) ;;;###autoload (defun magit-fetch-other (remote args) diff --git a/elpa/magit-20190122.503/magit-files.el b/elpa/magit-20190514.1814/magit-files.el similarity index 73% rename from elpa/magit-20190122.503/magit-files.el rename to elpa/magit-20190514.1814/magit-files.el index c18626bc..7d515451 100644 --- a/elpa/magit-20190122.503/magit-files.el +++ b/elpa/magit-20190514.1814/magit-files.el @@ -43,32 +43,88 @@ ;;;###autoload (defun magit-find-file (rev file) "View FILE from REV. -Switch to a buffer visiting blob REV:FILE, -creating one if none already exists." +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go +to the line and column corresponding to that location." (interactive (magit-find-file-read-args "Find file")) - (switch-to-buffer (magit-find-file-noselect rev file))) + (magit-find-file--internal rev file #'pop-to-buffer-same-window)) ;;;###autoload (defun magit-find-file-other-window (rev file) "View FILE from REV, in another window. -Like `magit-find-file', but create a new window or reuse an -existing one." +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go to +the line and column corresponding to that location." (interactive (magit-find-file-read-args "Find file in other window")) - (switch-to-buffer-other-window (magit-find-file-noselect rev file))) + (magit-find-file--internal rev file #'switch-to-buffer-other-window)) + +;;;###autoload +(defun magit-find-file-other-frame (rev file) + "View FILE from REV, in another frame. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go to +the line and column corresponding to that location." + (interactive (magit-find-file-read-args "Find file in other frame")) + (magit-find-file--internal rev file #'switch-to-buffer-other-frame)) (defun magit-find-file-read-args (prompt) - (let ((rev (magit-read-branch-or-commit "Find file from revision"))) - (list rev (magit-read-file-from-rev rev prompt)))) + (let ((pseudo-revs '("{worktree}" "{index}"))) + (if-let ((rev (magit-completing-read "Find file from revision" + (append pseudo-revs + (magit-list-refnames nil t)) + nil nil nil 'magit-revision-history + (or (magit-branch-or-commit-at-point) + (magit-get-current-branch))))) + (list rev (magit-read-file-from-rev (if (member rev pseudo-revs) + "HEAD" + rev) + prompt)) + (user-error "Nothing selected")))) + +(defun magit-find-file--internal (rev file fn) + (let ((buf (if (equal rev "{worktree}") + (find-file-noselect (expand-file-name file (magit-toplevel))) + (magit-find-file-noselect rev file))) + line col) + (when-let ((visited-file (magit-file-relative-name))) + (setq line (line-number-at-pos)) + (setq col (current-column)) + (cond + ((not (equal visited-file file))) + ((equal magit-buffer-revision rev)) + ((equal rev "{worktree}") + (setq line (magit-diff-visit--offset file magit-buffer-revision line))) + ((equal rev "{index}") + (setq line (magit-diff-visit--offset file nil line))) + (magit-buffer-revision + (setq line (magit-diff-visit--offset + file (concat magit-buffer-revision ".." rev) line))) + (t + (setq line (magit-diff-visit--offset file (list "-R" rev) line))))) + (funcall fn buf) + (when line + (with-current-buffer buf + (widen) + (goto-char (point-min)) + (forward-line (1- line)) + (move-to-column col))) + buf)) (defun magit-find-file-noselect (rev file) "Read FILE from REV into a buffer and return the buffer. +REV is a revision or one of \"{worktree}\" or \"{index}\". FILE must be relative to the top directory of the repository." - (magit-find-file-noselect-1 rev file 'magit-find-file-hook)) + (magit-find-file-noselect-1 rev file)) -(defun magit-find-file-noselect-1 (rev file hookvar &optional revert) +(defun magit-find-file-noselect-1 (rev file &optional revert) "Read FILE from REV into a buffer and return the buffer. +REV is a revision or one of \"{worktree}\" or \"{index}\". FILE must be relative to the top directory of the repository. -An empty REV stands for index." +Non-nil REVERT means to revert the buffer. If `ask-revert', +then only after asking." (let ((topdir (magit-toplevel))) (when (file-name-absolute-p file) (setq file (file-relative-name file topdir))) @@ -79,7 +135,9 @@ An empty REV stands for index." (buffer-name)))) revert) (setq magit-buffer-revision - (if (string= rev "") "{index}" (magit-rev-format "%H" rev))) + (if (equal rev "{index}") + "{index}" + (magit-rev-format "%H" rev))) (setq magit-buffer-refname rev) (setq magit-buffer-file-name (expand-file-name file topdir)) (setq default-directory @@ -87,7 +145,9 @@ An empty REV stands for index." (if (file-exists-p dir) dir topdir))) (setq-local revert-buffer-function #'magit-revert-rev-file-buffer) (revert-buffer t t) - (run-hooks hookvar)) + (run-hooks (if (equal rev "{index}") + 'magit-find-index-hook + 'magit-find-file-hook))) (current-buffer)))) (defun magit-get-revision-buffer-create (rev file) @@ -95,8 +155,7 @@ An empty REV stands for index." (defun magit-get-revision-buffer (rev file &optional create) (funcall (if create 'get-buffer-create 'get-buffer) - (format "%s.~%s~" file (if (equal rev "") "index" - (subst-char-in-string ?/ ?_ rev))))) + (format "%s.~%s~" file (subst-char-in-string ?/ ?_ rev)))) (defun magit-revert-rev-file-buffer (_ignore-auto noconfirm) (when (or noconfirm @@ -105,15 +164,19 @@ An empty REV stands for index." (dolist (regexp revert-without-query) (when (string-match regexp magit-buffer-file-name) (throw 'found t))))) - (yes-or-no-p (format "Revert buffer from git %s? " - (if (equal magit-buffer-refname "") "{index}" + (yes-or-no-p (format "Revert buffer from Git %s? " + (if (equal magit-buffer-refname "{index}") + "index" (concat "revision " magit-buffer-refname))))) (let* ((inhibit-read-only t) (default-directory (magit-toplevel)) (file (file-relative-name magit-buffer-file-name)) (coding-system-for-read (or coding-system-for-read 'undecided))) (erase-buffer) - (magit-git-insert "cat-file" "-p" (concat magit-buffer-refname ":" file)) + (magit-git-insert "cat-file" "-p" + (if (equal magit-buffer-refname "{index}") + (concat ":" file) + (concat magit-buffer-refname ":" file))) (setq buffer-file-coding-system last-coding-system-used)) (let ((buffer-file-name magit-buffer-file-name) (after-change-major-mode-hook @@ -131,8 +194,7 @@ An empty REV stands for index." (defun magit-find-file-index-noselect (file &optional revert) "Read FILE from the index into a buffer and return the buffer. FILE must to be relative to the top directory of the repository." - (magit-find-file-noselect-1 "" file 'magit-find-index-hook - (or revert 'ask-revert))) + (magit-find-file-noselect-1 "{index}" file (or revert 'ask-revert))) (defun magit-update-index () "Update the index with the contents of the current buffer. @@ -140,7 +202,7 @@ The current buffer has to be visiting a file in the index, which is done using `magit-find-index-noselect'." (interactive) (let ((file (magit-file-relative-name))) - (unless (equal magit-buffer-refname "") + (unless (equal magit-buffer-refname "{index}") (user-error "%s isn't visiting the index" file)) (if (y-or-n-p (format "Update index with contents of %s" (buffer-name))) (let ((index (make-temp-file "index")) @@ -162,7 +224,7 @@ is done using `magit-find-index-noselect'." (when magit-wip-after-apply-mode (magit-wip-commit-after-apply (list file) " after un-/stage"))) (message "Abort"))) - (--when-let (magit-mode-get-buffer 'magit-status-mode) + (--when-let (magit-get-mode-buffer 'magit-status-mode) (with-current-buffer it (magit-refresh))) t) @@ -221,40 +283,39 @@ directory, while reading the FILENAME." (defvar magit-file-mode-map (let ((map (make-sparse-keymap))) (define-key map "\C-xg" 'magit-status) - (define-key map "\C-x\M-g" 'magit-dispatch-popup) - (define-key map "\C-c\M-g" 'magit-file-popup) + (define-key map "\C-x\M-g" 'magit-dispatch) + (define-key map "\C-c\M-g" 'magit-file-dispatch) map) "Keymap for `magit-file-mode'.") -;;;###autoload (autoload 'magit-file-popup "magit" nil t) -(magit-define-popup magit-file-popup - "Popup console for Magit commands in file-visiting buffers." - :actions '((?s "Stage" magit-stage-file) - (?D "Diff..." magit-diff-buffer-file-popup) - (?L "Log..." magit-log-buffer-file-popup) - (?B "Blame..." magit-blame-popup) nil - (?u "Unstage" magit-unstage-file) - (?d "Diff" magit-diff-buffer-file) - (?l "Log" magit-log-buffer-file) - (?b "Blame" magit-blame-addition) - (?p "Prev blob" magit-blob-previous) - (?c "Commit" magit-commit-popup) nil - (?t "Trace" magit-log-trace-definition) - (?r (lambda () - (with-current-buffer magit-pre-popup-buffer - (and (not buffer-file-name) - (propertize "...removal" 'face 'default)))) - magit-blame-removal) - (?n "Next blob" magit-blob-next) - (?e "Edit line" magit-edit-line-commit) - nil nil - (?f (lambda () - (with-current-buffer magit-pre-popup-buffer - (and (not buffer-file-name) - (propertize "...reverse" 'face 'default)))) - magit-blame-reverse) - nil) - :max-action-columns 5) +;;;###autoload (autoload 'magit-file-dispatch "magit" nil t) +(define-transient-command magit-file-dispatch () + "Invoke a Magit command that acts on the visited file." + :info-manual "(magit) Minor Mode for Buffers Visiting Files" + ["Actions" + [("s" "Stage" magit-stage-file) + ("u" "Unstage" magit-unstage-file) + ("c" "Commit" magit-commit) + ("e" "Edit line" magit-edit-line-commit)] + [("D" "Diff..." magit-diff) + ("d" "Diff" magit-diff-buffer-file)] + [("L" "Log..." magit-log) + ("l" "Log" magit-log-buffer-file) + ("t" "Trace" magit-log-trace-definition)] + [("B" "Blame..." magit-blame) + ("b" "Blame" magit-blame-addition) + ("r" "...removal" magit-blame-removal) + ("f" "...reverse" magit-blame-reverse) + ("m" "Blame echo" magit-blame-echo) + ("q" "Quit blame" magit-blame-quit)] + [("p" "Prev blob" magit-blob-previous) + ("n" "Next blob" magit-blob-next) + ("g" "Goto blob" magit-find-file) + ("w" "Goto file" magit-blob-visit-file)] + [(5 "C-c r" "Rename file" magit-file-rename) + (5 "C-c d" "Delete file" magit-file-delete) + (5 "C-c u" "Untrack file" magit-file-untrack) + (5 "C-c c" "Checkout file" magit-file-checkout)]]) (defvar magit-file-mode-lighter "") @@ -321,8 +382,7 @@ Currently this only adds the following key bindings. (if magit-buffer-file-name (magit-blob-visit (or (magit-blob-successor magit-buffer-revision magit-buffer-file-name) - magit-buffer-file-name) - (line-number-at-pos)) + magit-buffer-file-name)) (if (buffer-file-name (buffer-base-buffer)) (user-error "You have reached the end of time") (user-error "Buffer isn't visiting a file or blob")))) @@ -333,20 +393,28 @@ Currently this only adds the following key bindings. (if-let ((file (or magit-buffer-file-name (buffer-file-name (buffer-base-buffer))))) (--if-let (magit-blob-ancestor magit-buffer-revision file) - (magit-blob-visit it (line-number-at-pos)) + (magit-blob-visit it) (user-error "You have reached the beginning of time")) (user-error "Buffer isn't visiting a file or blob"))) -(defun magit-blob-visit (blob-or-file line) +;;;###autoload +(defun magit-blob-visit-file () + "View the file from the worktree corresponding to the current blob. +When visiting a blob or the version from the index, then go to +the same location in the respective file in the working tree." + (interactive) + (if-let ((file (magit-file-relative-name))) + (magit-find-file--internal "{worktree}" file #'pop-to-buffer-same-window) + (user-error "Not visiting a blob"))) + +(defun magit-blob-visit (blob-or-file) (if (stringp blob-or-file) (find-file blob-or-file) (pcase-let ((`(,rev ,file) blob-or-file)) (magit-find-file rev file) (apply #'message "%s (%s %s ago)" (magit-rev-format "%s" rev) - (magit--age (magit-rev-format "%ct" rev))))) - (goto-char (point-min)) - (forward-line (1- line))) + (magit--age (magit-rev-format "%ct" rev)))))) (defun magit-blob-ancestor (rev file) (let ((lines (magit-with-toplevel @@ -482,12 +550,6 @@ If DEFAULT is non-nil, use this as the default value instead of default (concat "No file changed in " rev-or-range))) -(defun magit-read-files (prompt initial-contents) - (mapconcat 'identity - (completing-read-multiple (or prompt "File,s: ") - (magit-list-files) - nil nil initial-contents) ",")) - ;;; _ (provide 'magit-files) ;;; magit-files.el ends here diff --git a/elpa/magit-20190122.503/magit-git.el b/elpa/magit-20190514.1814/magit-git.el similarity index 85% rename from elpa/magit-20190122.503/magit-git.el rename to elpa/magit-20190514.1814/magit-git.el index 5675918c..dc5e0f56 100644 --- a/elpa/magit-20190122.503/magit-git.el +++ b/elpa/magit-20190514.1814/magit-git.el @@ -36,24 +36,68 @@ (require 'magit-utils) (require 'magit-section) -(declare-function magit-call-git "magit-process" (&rest args)) +;; From `magit-branch'. +(defvar magit-branch-prefer-remote-upstream) +(defvar magit-published-branches) + +;; From `magit-margin'. (declare-function magit-maybe-make-margin-overlay "magit-margin" ()) + +;; From `magit-mode'. +(declare-function magit-get-mode-buffer "magit-mode" + (mode &optional value frame)) +(declare-function magit-refresh "magit-mode" ()) +(defvar magit-buffer-diff-args) +(defvar magit-buffer-file-name) +(defvar magit-buffer-log-args) +(defvar magit-buffer-log-files) +(defvar magit-buffer-refname) +(defvar magit-buffer-revision) + +;; From `magit-process'. +(declare-function magit-call-git "magit-process" (&rest args)) (declare-function magit-process-buffer "magit-process" (&optional nodisplay)) (declare-function magit-process-file "magit-process" (&rest args)) (declare-function magit-process-insert-section "magit-process" - (pwe program args &optional errcode errlog)) -(declare-function magit-mode-get-buffer "magit-mode" - (mode &optional create frame value)) -(declare-function magit-refresh "magit-mode" ()) + (pwd program args &optional errcode errlog)) (defvar magit-this-error) (defvar magit-process-error-message-regexps) -(defvar magit-refresh-args) ; from `magit-mode' for `magit-current-file' -(defvar magit-branch-prefer-remote-upstream) -(defvar magit-published-branches) -(defvar magit-diff-section-arguments) +;; From later in `magit-git'. (defvar magit-tramp-process-environment nil) +;;; Git implementations + +(defvar magit-inhibit-libgit nil + "Whether to inhibit the use of libgit.") + +(defvar magit--libgit-available-p eieio-unbound + "Whether libgit is available. +Use the function by the same name instead of this variable.") + +(defun magit--libgit-available-p () + (if (eq magit--libgit-available-p eieio-unbound) + (setq magit--libgit-available-p + (and module-file-suffix + (let ((libgit (locate-library "libgit"))) + (and libgit + (or (locate-library "libegit2") + (let ((load-path + (cons (expand-file-name + (convert-standard-filename "build") + (file-name-directory libgit)) + load-path))) + (locate-library "libegit2"))))))) + magit--libgit-available-p)) + +(defun magit-gitimpl () + "Return the Git implementation used in this repository." + (if (and (not magit-inhibit-libgit) + (not (file-remote-p default-directory)) + (magit--libgit-available-p)) + 'libgit + 'git)) + ;;; Options ;; For now this is shared between `magit-process' and `magit-git'. @@ -171,8 +215,8 @@ and then set it as the upstream branch, offer a local or a remote branch as default completion candidate, when they have the choice. This affects all commands that use `magit-read-upstream-branch' -or `magit-read-starting-point', which includes all commands that -change the upstream and many which create new branches." +or `magit-read-starting-point', which includes most commands +that change the upstream and many that create new branches." :package-version '(magit . "2.4.2") :group 'magit-commands :type 'boolean) @@ -324,7 +368,7 @@ still subject to major changes. Also see `magit-git-string-p'." (magit-process-insert-section default-directory magit-git-executable args status buf))) - (when-let ((status-buf (magit-mode-get-buffer 'magit-status-mode))) + (when-let ((status-buf (magit-get-mode-buffer 'magit-status-mode))) (let ((msg (magit--locate-error-message))) (with-current-buffer status-buf (setq magit-this-error msg)))) @@ -470,7 +514,7 @@ call function WASHER with ARGS as its sole argument." (defun magit-git-version (&optional raw) (--when-let (let (magit-git-global-arguments) (ignore-errors (substring (magit-git-string "version") 12))) - (if raw it (and (string-match "^\\([0-9]+\\.[0-9]+\\.[0-9]+\\)" it) + (if raw it (and (string-match "\\`\\([0-9]+\\(\\.[0-9]+\\)\\{1,2\\}\\)" it) (match-string 1 it))))) ;;; Variables @@ -722,7 +766,7 @@ is non-nil, in which case return nil." (and (not noerror) (signal 'magit-outside-git-repo default-directory)))))) -(defun magit-bare-repo-p (&optional noerror) +(cl-defgeneric magit-bare-repo-p (&optional noerror) "Return t if the current repository is bare. If it is non-bare, then return nil. If `default-directory' isn't below a Git repository, then signal an error unless @@ -757,13 +801,6 @@ a bare repository." (file-directory-p (expand-file-name "refs" directory)) (file-directory-p (expand-file-name "objects" directory)))))) -(defvar-local magit-buffer-revision nil) -(defvar-local magit-buffer-refname nil) -(defvar-local magit-buffer-file-name nil) -(put 'magit-buffer-revision 'permanent-local t) -(put 'magit-buffer-refname 'permanent-local t) -(put 'magit-buffer-file-name 'permanent-local t) - (defun magit-file-relative-name (&optional file tracked) "Return the path of FILE relative to the repository root. @@ -821,6 +858,11 @@ tracked file." (magit-git-items "ls-files" "-z" "--others" "--ignored" "--exclude-standard" "--directory")) +(defun magit-skip-worktree-files () + (--keep (and (and (= (aref it 0) ?S) + (substring it 2))) + (magit-git-items "ls-files" "-z" "-t"))) + (defun magit-revision-files (rev) (magit-with-toplevel (magit-git-items "ls-tree" "-z" "-r" "--name-only" rev))) @@ -911,16 +953,21 @@ Sorted from longest to shortest CYGWIN name." t) path)) -(defun magit-file-at-point () - (magit-section-case - (file (oref it value)) - (hunk (magit-section-parent-value it)))) +(defun magit-file-at-point (&optional expand assert) + (if-let ((file (magit-section-case + (file (oref it value)) + (hunk (magit-section-parent-value it))))) + (if expand + (expand-file-name file (magit-toplevel)) + file) + (when assert + (user-error "No file at point")))) (defun magit-current-file () (or (magit-file-relative-name) (magit-file-at-point) (and (derived-mode-p 'magit-log-mode) - (car (nth 2 magit-refresh-args))))) + (car magit-buffer-log-files)))) ;;; Predicates @@ -971,7 +1018,7 @@ are considered." (defun magit-ignore-submodules-p () (cl-find-if (lambda (arg) (string-prefix-p "--ignore-submodules" arg)) - magit-diff-section-arguments)) + magit-buffer-diff-args)) ;;; Revisions and References @@ -1013,6 +1060,8 @@ string \"true\", otherwise return nil." (defalias 'magit-rev-verify-commit 'magit-commit-p) +(defalias 'magit-rev-hash 'magit-commit-p) + (defun magit-rev-equal (a b) "Return t if there are no differences between the commits A and B." (magit-git-success "diff" "--quiet" a b)) @@ -1042,25 +1091,43 @@ of REV." (or (equal (magit-get "user.name") (magit-rev-format "%an" rev)) (equal (magit-get "user.email") (magit-rev-format "%ae" rev)))) -(defun magit-rev-name (rev &optional pattern) - "Return a symbolic name for REV. -PATTERN is passed to the `--refs' flag of `git-name-rev' and can -be used to limit the result to a matching ref. When structured -as \"refs//*\", PATTERN is taken as a namespace. In this -case, the name returned by `git-name-rev' is discarded if it -corresponds to a ref outside of the namespace." - (--when-let (magit-git-string "name-rev" "--name-only" "--no-undefined" - (and pattern (concat "--refs=" pattern)) - rev) - ;; We can't use name-rev's --exclude to filter out "*/PATTERN" - ;; because --exclude wasn't added until Git v2.13.0. - (if (and pattern - (string-match-p "\\`refs/[^/]+/\\*\\'" pattern)) - (let ((namespace (substring pattern 0 -1))) - (unless (and (string-match-p namespace it) - (not (magit-rev-verify (concat namespace it)))) - it)) - it))) +(defun magit-rev-name (rev &optional pattern not-anchored) + "Return a symbolic name for REV using `git-name-rev'. + +PATTERN can be used to limit the result to a matching ref. +Unless NOT-ANCHORED is non-nil, the beginning of the ref must +match PATTERN. + +An anchored lookup is done using the arguments +\"--exclude=*/ --exclude=*/HEAD\" in addition to +\"--refs=\", provided at least version v2.13 of Git is +used. Older versions did not support the \"--exclude\" argument. +When \"--exclude\" cannot be used and `git-name-rev' returns a +ref that should have been excluded, then that is discarded and +this function returns nil instead. This is unfortunate because +there might be other refs that do match. To fix that, update +Git." + (if (version< (magit-git-version) "2.13") + (when-let + ((ref (magit-git-string "name-rev" "--name-only" "--no-undefined" + (and pattern (concat "--refs=" pattern)) + rev))) + (if (and pattern + (string-match-p "\\`refs/[^/]+/\\*\\'" pattern)) + (let ((namespace (substring pattern 0 -1))) + (and (not (or (string-suffix-p "HEAD" ref) + (and (string-match-p namespace ref) + (not (magit-rev-verify + (concat namespace ref)))))) + ref)) + ref)) + (magit-git-string "name-rev" "--name-only" "--no-undefined" + (and pattern (concat "--refs=" pattern)) + (and pattern + (not not-anchored) + (list "--exclude=*/HEAD" + (concat "--exclude=*/" pattern))) + rev))) (defun magit-rev-branch (rev) (--when-let (magit-rev-name rev "refs/heads/*") @@ -1099,38 +1166,46 @@ corresponds to a ref outside of the namespace." (and (or lax (not (string-match-p "[~^]" it))) (substring it 5)))) -(defun magit-ref-fullname (name) - "Return fully qualified refname for NAME. -If NAME is ambiguous, return nil. NAME may include suffixes such -as \"^1\" and \"~3\". " - (save-match-data - (if (string-match "\\`\\([^^~]+\\)\\(.*\\)" name) - (--when-let (magit-rev-parse "--symbolic-full-name" - (match-string 1 name)) - (concat it (match-string 2 name))) - (error "`name' has an unrecognized format")))) +(defun magit-ref-abbrev (refname) + "Return an unambigious abbreviation of REFNAME." + (magit-rev-parse "--verify" "--abbrev-ref" refname)) -(defun magit-ref-ambiguous-p (name) - (not (magit-ref-fullname name))) +(defun magit-ref-fullname (refname) + "Return fully qualified refname for REFNAME. +If REFNAME is ambiguous, return nil." + (magit-rev-parse "--verify" "--symbolic-full-name" refname)) -(cl-defun magit-ref-maybe-qualify (name &optional (prefix "heads/")) - "If NAME is ambiguous, prepend PREFIX to it." - (concat (and (magit-ref-ambiguous-p name) - prefix) - name)) +(defun magit-ref-ambiguous-p (refname) + (save-match-data + (if (string-match "\\`\\([^^~]+\\)\\(.*\\)" refname) + (not (magit-ref-fullname (match-string 1 refname))) + (error "%S has an unrecognized format" refname)))) + +(defun magit-ref-maybe-qualify (refname &optional prefix) + "If REFNAME is ambiguous, try to disambiguate it by prepend PREFIX to it. +Return an unambigious refname, either REFNAME or that prefixed +with PREFIX, nil otherwise. If REFNAME has an offset suffix +such as \"~1\", then that is preserved. If optional PREFIX is +nil, then use \"heads/\". " + (if (magit-ref-ambiguous-p refname) + (let ((refname (concat (or prefix "heads/") refname))) + (and (not (magit-ref-ambiguous-p refname)) refname)) + refname)) (defun magit-ref-exists-p (ref) (magit-git-success "show-ref" "--verify" ref)) (defun magit-ref-equal (a b) - "Return t if the refs A and B are `equal'. + "Return t if the refnames A and B are `equal'. A symbolic-ref pointing to some ref, is `equal' to that ref, -as are two symbolic-refs pointing to the same ref." - (equal (magit-ref-fullname a) - (magit-ref-fullname b))) +as are two symbolic-refs pointing to the same ref. Refnames +may be abbreviated." + (let ((a (magit-ref-fullname a)) + (b (magit-ref-fullname b))) + (and a b (equal a b)))) (defun magit-ref-eq (a b) - "Return t if the refs A and B are `eq'. + "Return t if the refnames A and B are `eq'. A symbolic-ref is `eq' to itself, but not to the ref it points to, or to some other symbolic-ref that points to the same ref." (let ((symbolic-a (magit-symbolic-ref-p a)) @@ -1159,8 +1234,8 @@ to, or to some other symbolic-ref that points to the same ref." (memq (get-text-property (point) 'face) (list 'magit-branch-local 'magit-branch-current)) - (cdr (magit-split-branch-name - (thing-at-point 'git-revision t)))) + (when-let ((branch (thing-at-point 'git-revision t))) + (cdr (magit-split-branch-name branch)))) (and (not (eq type 'local)) (memq (get-text-property (point) 'face) (list 'magit-branch-remote @@ -1185,23 +1260,25 @@ to, or to some other symbolic-ref that points to the same ref." (defun magit-commit-at-point () (or (magit-section-value-if 'commit) - (and (derived-mode-p 'magit-revision-mode) - (car magit-refresh-args)))) + (and (derived-mode-p 'magit-stash-mode + 'magit-merge-preview-mode + 'magit-revision-mode) + magit-buffer-revision))) (defun magit-branch-or-commit-at-point () - (or magit-buffer-refname + (or (and magit-buffer-file-name + magit-buffer-refname) (magit-section-case (branch (magit-ref-maybe-qualify (oref it value))) (commit (or (magit--painted-branch-at-point) (let ((rev (oref it value))) - (or (magit-name-branch rev) - (magit-get-shortname rev) - rev)))) + (or (magit-name-branch rev) rev)))) (tag (magit-ref-maybe-qualify (oref it value) "tags/"))) (thing-at-point 'git-revision t) - (and (derived-mode-p 'magit-revision-mode - 'magit-merge-preview-mode) - (car magit-refresh-args)))) + (and (derived-mode-p 'magit-stash-mode + 'magit-merge-preview-mode + 'magit-revision-mode) + magit-buffer-revision))) (defun magit-tag-at-point () (magit-section-case @@ -1249,41 +1326,38 @@ The amount of time spent searching is limited by (cl-incf i)) prev)) -(defun magit-get-upstream-ref (&optional branch) - (and (or branch (setq branch (magit-get-current-branch))) - (let ((remote (magit-get "branch" branch "remote")) - (merge (magit-get "branch" branch "merge"))) - (when (and remote merge) - (cond ((string-equal remote ".") merge) - ((string-prefix-p "refs/heads/" merge) - (concat "refs/remotes/" remote "/" (substring merge 11)))))))) - (defun magit-set-upstream-branch (branch upstream) + "Set UPSTREAM as the upstream of BRANCH. +If UPSTREAM is nil, then unset BRANCH's upstream. +Otherwise UPSTREAM has to be an existing branch." (if upstream - (pcase-let ((`(,remote . ,merge) (magit-split-branch-name upstream))) - (setf (magit-get (format "branch.%s.remote" branch)) remote) - (setf (magit-get (format "branch.%s.merge" branch)) - (concat "refs/heads/" merge))) + (magit-call-git "branch" "--set-upstream-to" upstream branch) (magit-call-git "branch" "--unset-upstream" branch))) -(defun magit-get-upstream-branch (&optional branch verify) - (and (or branch (setq branch (magit-get-current-branch))) - (when-let ((remote (magit-get "branch" branch "remote")) - (merge (magit-get "branch" branch "merge"))) - (and (string-prefix-p "refs/heads/" merge) - (let* ((upstream (substring merge 11)) - (upstream - (cond ((string-equal remote ".") - (propertize upstream 'face 'magit-branch-local)) - ((string-match-p "[@:]" remote) - (propertize (concat remote " " upstream) - 'face 'magit-branch-remote)) - (t - (propertize (concat remote "/" upstream) - 'face 'magit-branch-remote))))) - (and (or (not verify) - (magit-rev-verify upstream)) - upstream)))))) +(defun magit-get-upstream-ref (&optional branch) + "Return the upstream branch of BRANCH as a fully qualified ref. +It BRANCH is nil, then return the upstream of the current branch, +if any, nil otherwise. If the upstream is not configured, the +configured remote is an url, or the named branch does not exist, +then return nil. I.e. return an existing local or +remote-tracking branch ref." + (when-let ((branch (or branch (magit-get-current-branch)))) + (magit-ref-fullname (concat branch "@{upstream}")))) + +(defun magit-get-upstream-branch (&optional branch) + "Return the name of the upstream branch of BRANCH. +It BRANCH is nil, then return the upstream of the current branch +if any, nil otherwise. If the upstream is not configured, the +configured remote is an url, or the named branch does not exist, +then return nil. I.e. return the name of an existing local or +remote-tracking branch. The returned string is colorized +according to the branch type." + (when-let ((branch (or branch (magit-get-current-branch))) + (upstream (magit-ref-abbrev (concat branch "@{upstream}")))) + (propertize upstream 'face + (if (equal (magit-get "branch" branch "remote") ".") + 'magit-branch-local + 'magit-branch-remote)))) (defun magit-get-indirect-upstream-branch (branch &optional force) (let ((remote (magit-get "branch" branch "remote"))) @@ -1298,32 +1372,61 @@ The amount of time spent searching is limited by (let ((upstream (magit-get-upstream-branch branch))) ;; whose upstream... (and upstream - ;; has the same name as BRANCH and... + ;; has the same name as BRANCH... (equal (substring upstream (1+ (length remote))) branch) ;; and can be fast-forwarded to BRANCH. (magit-rev-ancestor-p upstream branch) upstream))))) -(defun magit-get-upstream-remote (&optional branch non-local) - (unless branch - (setq branch (magit-get-current-branch))) - (and branch - (let ((remote (magit-get "branch" branch "remote"))) - (and (not (and non-local (equal remote "."))) - remote)))) +(defun magit-get-upstream-remote (&optional branch allow-unnamed) + (when-let ((branch (or branch (magit-get-current-branch))) + (remote (magit-get "branch" branch "remote"))) + (and (not (equal remote ".")) + (cond ((member remote (magit-list-remotes)) + (propertize remote 'face 'magit-branch-remote)) + ((and allow-unnamed + (string-match-p "\\(\\`.\\{0,2\\}/\\|[:@]\\)" remote)) + (propertize remote 'face 'bold)))))) + +(defun magit-get-unnamed-upstream (&optional branch) + (when-let ((branch (or branch (magit-get-current-branch))) + (remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (and (magit--unnamed-upstream-p remote merge) + (list (propertize remote 'face 'bold) + (propertize merge 'face 'magit-branch-remote))))) + +(defun magit--unnamed-upstream-p (remote merge) + (and remote (string-match-p "\\(\\`\\.\\{0,2\\}/\\|[:@]\\)" remote) + merge (string-prefix-p "refs/" merge))) + +(defun magit--valid-upstream-p (remote merge) + (and (or (equal remote ".") + (member remote (magit-list-remotes))) + (string-prefix-p "refs/" merge))) + +(defun magit-get-current-remote (&optional allow-unnamed) + (or (magit-get-upstream-remote nil allow-unnamed) + (when-let ((remotes (magit-list-remotes)) + (remote (if (= (length remotes) 1) + (car remotes) + (car (member "origin" remotes))))) + (propertize remote 'face 'magit-branch-remote)))) (defun magit-get-push-remote (&optional branch) - (or (and (or branch (setq branch (magit-get-current-branch))) - (magit-get "branch" branch "pushRemote")) - (magit-get "remote.pushDefault"))) + (when-let ((remote + (or (and (or branch (setq branch (magit-get-current-branch))) + (magit-get "branch" branch "pushRemote")) + (magit-get "remote.pushDefault")))) + (propertize remote 'face 'magit-branch-remote))) (defun magit-get-push-branch (&optional branch verify) - (and (or branch (setq branch (magit-get-current-branch))) - (when-let ((remote (magit-get-push-remote branch)) - (push-branch (concat remote "/" branch))) - (and (or (not verify) - (magit-rev-verify push-branch)) - (propertize push-branch 'face 'magit-branch-remote))))) + (when-let ((branch (or branch (setq branch (magit-get-current-branch)))) + (remote (magit-get-push-remote branch)) + (target (concat remote "/" branch))) + (and (or (not verify) + (magit-rev-verify target)) + (propertize target 'face 'magit-branch-remote)))) (defun magit-get-@{push}-branch (&optional branch) (let ((ref (magit-rev-parse "--symbolic-full-name" @@ -1366,12 +1469,29 @@ as into its upstream." (--when-let (or target (magit-get-current-branch)) (magit-git-success "merge-base" "--is-ancestor" branch it))))) +(defun magit-get-tracked (refname) + "Return the remote branch tracked by the remote-tracking branch REFNAME. +The returned value has the form (REMOTE . REF), where REMOTE is +the name of a remote and REF is the ref local to the remote." + (when-let ((ref (magit-ref-fullname refname))) + (save-match-data + (-some (lambda (line) + (and (string-match "\ +\\`remote\\.\\([^.]+\\)\\.fetch=\\+?\\([^:]+\\):\\(.+\\)" line) + (let ((rmt (match-string 1 line)) + (src (match-string 2 line)) + (dst (match-string 3 line))) + (and (string-match (format "\\`%s\\'" + (replace-regexp-in-string + "*" "\\(.+\\)" dst t t)) + ref) + (cons rmt (replace-regexp-in-string + "*" (match-string 1 ref) src)))))) + (magit-git-lines "config" "--local" "--list"))))) + (defun magit-split-branch-name (branch) (cond ((member branch (magit-list-local-branch-names)) (cons "." branch)) - ((string-match " " branch) - (pcase-let ((`(,url ,branch) (split-string branch " "))) - (cons url branch))) ((string-match "/" branch) (or (-some (lambda (remote) (and (string-match (format "\\`\\(%s\\)/\\(.+\\)\\'" remote) @@ -1486,8 +1606,20 @@ SORTBY is a key or list of keys to pass to the `--sort' flag of name))) (magit-git-lines "show-ref")))) -(defun magit-list-refnames (&optional namespaces) - (magit-list-refs namespaces "%(refname:short)")) +(defun magit-list-refnames (&optional namespaces include-special) + (nconc (magit-list-refs namespaces "%(refname:short)") + (and include-special + (magit-list-special-refnames)))) + +(defvar magit-special-refnames + '("HEAD" "ORIG_HEAD" "FETCH_HEAD" "MERGE_HEAD" "CHERRY_PICK_HEAD")) + +(defun magit-list-special-refnames () + (let ((gitdir (magit-gitdir))) + (cl-mapcan (lambda (name) + (and (file-exists-p (expand-file-name name gitdir)) + (list name))) + magit-special-refnames))) (defun magit-list-branch-names () (magit-list-refnames (list "refs/heads" "refs/remotes"))) @@ -1709,17 +1841,11 @@ In refs buffers the displayed text is controlled by other means and this option only controls what face is used.") (defun magit-format-ref-labels (string) - ;; To support Git <2.2.0, we remove the surrounding parentheses here - ;; rather than specifying that STRING should be generated with Git's - ;; "%D" placeholder. - (setq string (->> string - (replace-regexp-in-string "\\`\\s-*(" "") - (replace-regexp-in-string ")\\s-*\\'" ""))) (save-match-data (let ((regexp "\\(, \\|tag: \\|HEAD -> \\)") names) (if (and (derived-mode-p 'magit-log-mode) - (member "--simplify-by-decoration" (cadr magit-refresh-args))) + (member "--simplify-by-decoration" magit-buffer-log-args)) (let ((branches (magit-list-local-branch-names)) (re (format "^%s/.+" (regexp-opt (magit-list-remotes))))) (setq names @@ -1763,7 +1889,7 @@ and this option only controls what face is used.") name)) remotes)) (let* ((current (magit-get-current-branch)) - (target (magit-get-upstream-branch current t))) + (target (magit-get-upstream-branch current))) (dolist (name branches) (let ((push (car (member (magit-get-push-branch name) remotes)))) (when push @@ -1893,26 +2019,25 @@ and this option only controls what face is used.") beg) end)))) -(defvar magit-thingatpt--git-revision-chars "-_./[:alnum:]@{}^~!" - "Characters allowable in filenames, excluding space and colon.") - -(put 'git-revision 'end-op - (lambda () - (re-search-forward - (concat "\\=[" magit-thingatpt--git-revision-chars "]*") - nil t))) - -(put 'git-revision 'beginning-op - (lambda () - (if (re-search-backward - (concat "[^" magit-thingatpt--git-revision-chars "]") nil t) - (forward-char) - (goto-char (point-min))))) +(defun magit-hash-range (range) + (if (string-match magit-range-re range) + (concat (magit-rev-hash (match-string 1 range)) + (match-string 2 range) + (magit-rev-hash (match-string 3 range))) + (magit-rev-hash range))) (put 'git-revision 'thing-at-point 'magit-thingatpt--git-revision) - (defun magit-thingatpt--git-revision () - (--when-let (bounds-of-thing-at-point 'git-revision) + (--when-let + (let ((c "\s\n\t~^:?*[\\")) + (cl-letf (((get 'git-revision 'beginning-op) + (if (re-search-backward (format "[%s]" c) nil t) + (forward-char) + (goto-char (point-min)))) + ((get 'git-revision 'end-op) + (lambda () + (re-search-forward (format "\\=[^%s]*" c) nil t)))) + (bounds-of-thing-at-point 'git-revision))) (let ((text (buffer-substring-no-properties (car it) (cdr it)))) (and (magit-commit-p text) text)))) @@ -1928,7 +2053,7 @@ and this option only controls what face is used.") (magit-get-current-branch)))) (defun magit-read-branch-or-commit (prompt &optional secondary-default) - (or (magit-completing-read prompt (cons "HEAD" (magit-list-refnames)) + (or (magit-completing-read prompt (magit-list-refnames nil t) nil nil nil 'magit-revision-history (or (magit-branch-or-commit-at-point) secondary-default @@ -1980,10 +2105,12 @@ and this option only controls what face is used.") (magit-get-current-branch)))) (defun magit-read-local-branch-or-commit (prompt) - (let ((branches (magit-list-local-branch-names)) + (let ((choices (nconc (magit-list-local-branch-names) + (magit-list-special-refnames))) (commit (magit-commit-at-point))) - (or (magit-completing-read prompt - (if commit (cons commit branches) branches) + (when commit + (push commit choices)) + (or (magit-completing-read prompt choices nil nil nil 'magit-revision-history (or (magit-local-branch-at-point) commit)) (user-error "Nothing selected")))) @@ -2014,7 +2141,10 @@ and this option only controls what face is used.") (let* ((current (magit-get-current-branch)) (atpoint (magit-branch-or-commit-at-point)) (exclude (or exclude current)) - (default (or (and (not (equal atpoint exclude)) atpoint) + (default (or (and (not (equal atpoint exclude)) + (not (and (not current) + (magit-rev-equal atpoint "HEAD"))) + atpoint) (and (not (equal current exclude)) current) secondary-default (magit-get-previous-branch)))) @@ -2050,27 +2180,27 @@ and this option only controls what face is used.") (magit-get-previous-branch) (car atrev))))) -(cl-defun magit-read-upstream-branch - (&optional (branch (magit-get-current-branch)) prompt) - (magit-completing-read - (or prompt (format "Change upstream of %s to" branch)) - (-union (--map (concat it "/" branch) - (magit-list-remotes)) - (delete branch (magit-list-branch-names))) - nil nil nil 'magit-revision-history - (or (let ((r (magit-remote-branch-at-point)) - (l (magit-branch-at-point))) - (when (and l (equal l branch)) - (setq l nil)) - (if magit-prefer-remote-upstream (or r l) (or l r))) - (let ((r (magit-branch-p "origin/master")) - (l (and (not (equal branch "master")) - (magit-branch-p "master")))) - (if magit-prefer-remote-upstream (or r l) (or l r))) - (let ((previous (magit-get-previous-branch))) - (and (not (equal previous branch)) previous))))) - -(defun magit-read-starting-point (prompt &optional branch) +(defun magit-read-upstream-branch (&optional branch prompt) + "Read the upstream for BRANCH using PROMPT. +If optional BRANCH is nil, then read the upstream for the +current branch, or raise an error if no branch is checked +out. Only existing branches can be selected." + (unless branch + (setq branch (or (magit-get-current-branch) + (error "Need a branch to set its upstream")))) + (let ((branches (delete branch (magit-list-branch-names)))) + (magit-completing-read + (or prompt (format "Change upstream of %s to" branch)) + branches nil t nil 'magit-revision-history + (or (let ((r (car (member (magit-remote-branch-at-point) branches))) + (l (car (member (magit-local-branch-at-point) branches)))) + (if magit-prefer-remote-upstream (or r l) (or l r))) + (let ((r (car (member "origin/master" branches))) + (l (car (member "master" branches)))) + (if magit-prefer-remote-upstream (or r l) (or l r))) + (car (member (magit-get-previous-branch) branches)))))) + +(defun magit-read-starting-point (prompt &optional branch default) (or (magit-completing-read (concat prompt (and branch @@ -2084,7 +2214,7 @@ and this option only controls what face is used.") (magit-list-refnames) (directory-files (magit-git-dir) nil "_HEAD\\'")) nil nil nil 'magit-revision-history - (magit--default-starting-point)) + (or default (magit--default-starting-point))) (user-error "Nothing selected"))) (defun magit--default-starting-point () @@ -2151,87 +2281,6 @@ and this option only controls what face is used.") (magit-confirm t nil (format "%s %%i modules" verb) nil modules) (list (magit-read-module-path (format "%s module" verb) predicate))))) -;;; Variables in Popups - -(defun magit--format-popup-variable:value (variable width &optional global) - (concat variable - (make-string (max 1 (- width 3 (length variable))) ?\s) - (if-let ((value (magit-get (and global "--global") variable))) - (propertize value 'face 'magit-popup-option-value) - (propertize "unset" 'face 'magit-popup-disabled-argument)))) - -(defun magit--format-popup-variable:values (variable width &optional global) - (concat variable - (make-string (max 1 (- width 3 (length variable))) ?\s) - (if-let ((values (magit-get-all (and global "--global") variable))) - (concat - (propertize (car values) 'face 'magit-popup-option-value) - (mapconcat - (lambda (value) - (concat "\n" (make-string width ?\s) - (propertize value - 'face 'magit-popup-option-value))) - (cdr values) "")) - (propertize "unset" 'face 'magit-popup-disabled-argument)))) - -(defun magit--set-popup-variable - (variable choices &optional default other) - (magit-set (--if-let (magit-git-string "config" "--local" variable) - (cadr (member it choices)) - (car choices)) - variable) - (magit-with-pre-popup-buffer - (magit-refresh)) - (message "%s %s" variable - (magit--format-popup-variable:choices* - variable choices default other))) - -(defun magit--format-popup-variable:choices - (variable choices &optional default other width) - (concat variable - (if width (make-string (- width (length variable)) ?\s) " ") - (magit--format-popup-variable:choices* - variable choices default other))) - -(defun magit--format-popup-variable:choices* - (variable choices &optional default other) - (let ((local (magit-git-string "config" "--local" variable)) - (global (magit-git-string "config" "--global" variable))) - (when other - (setq other (--when-let (magit-get other) - (concat other ":" it)))) - (concat - (propertize "[" 'face 'magit-popup-disabled-argument) - (mapconcat - (lambda (choice) - (propertize choice 'face (if (equal choice local) - 'magit-popup-option-value - 'magit-popup-disabled-argument))) - choices - (propertize "|" 'face 'magit-popup-disabled-argument)) - (when (or global other default) - (concat - (propertize "|" 'face 'magit-popup-disabled-argument) - (cond (global - (propertize (concat "global:" global) - 'face (cond (local - 'magit-popup-disabled-argument) - ((member global choices) - 'magit-popup-option-value) - (t - 'font-lock-warning-face)))) - (other - (propertize other - 'face (if local - 'magit-popup-disabled-argument - 'magit-popup-option-value))) - (default - (propertize (concat "default:" default) - 'face (if local - 'magit-popup-disabled-argument - 'magit-popup-option-value)))))) - (propertize "]" 'face 'magit-popup-disabled-argument)))) - ;;; _ (provide 'magit-git) ;;; magit-git.el ends here diff --git a/elpa/magit-20190514.1814/magit-gitignore.el b/elpa/magit-20190514.1814/magit-gitignore.el new file mode 100644 index 00000000..8578ae46 --- /dev/null +++ b/elpa/magit-20190514.1814/magit-gitignore.el @@ -0,0 +1,155 @@ +;;; magit-gitignore.el --- intentionally untracked files -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; 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. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements gitignore commands. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Transient + +;;;###autoload (autoload 'magit-gitignore "magit-gitignore" nil t) +(define-transient-command magit-gitignore () + "Instruct Git to ignore a file or pattern." + :man-page "gitignore" + ["Gitignore" + ("t" "shared at toplevel (.gitignore)" + magit-gitignore-in-topdir) + ("s" "shared in subdirectory (path/to/.gitignore)" + magit-gitignore-in-subdir) + ("p" "privately (.git/info/exclude)" + magit-gitignore-in-gitdir) + ("g" magit-gitignore-on-system + :if (lambda () (magit-get "core.excludesfile")) + :description (lambda () + (format "privately for all repositories (%s)" + (magit-get "core.excludesfile"))))] + ["Skip worktree" + (7 "w" "do skip worktree" magit-skip-worktree) + (7 "W" "do not skip worktree" magit-no-skip-worktree)]) + +;;; Gitignore Commands + +;;;###autoload +(defun magit-gitignore-in-topdir (rule) + "Add the Git ignore RULE to the top-level \".gitignore\" file. +Since this file is tracked, it is shared with other clones of the +repository. Also stage the file." + (interactive (list (magit-gitignore-read-pattern))) + (magit-with-toplevel + (magit--gitignore rule ".gitignore") + (magit-run-git "add" ".gitignore"))) + +;;;###autoload +(defun magit-gitignore-in-subdir (rule directory) + "Add the Git ignore RULE to a \".gitignore\" file. +Prompted the user for a directory and add the rule to the +\".gitignore\" file in that directory. Since such files are +tracked, they are shared with other clones of the repository. +Also stage the file." + (interactive (list (magit-gitignore-read-pattern) + (read-directory-name "Limit rule to files in: "))) + (magit-with-toplevel + (let ((file (expand-file-name ".gitignore" directory))) + (magit--gitignore rule file) + (magit-run-git "add" ".gitignore")))) + +;;;###autoload +(defun magit-gitignore-in-gitdir (rule) + "Add the Git ignore RULE to \"$GIT_DIR/info/exclude\". +Rules in that file only affects this clone of the repository." + (interactive (list (magit-gitignore-read-pattern))) + (magit--gitignore rule (magit-git-dir "info/exclude")) + (magit-refresh)) + +;;;###autoload +(defun magit-gitignore-on-system (rule) + "Add the Git ignore RULE to the file specified by `core.excludesFile'. +Rules that are defined in that file affect all local repositories." + (interactive (list (magit-gitignore-read-pattern))) + (magit--gitignore rule + (or (magit-get "core.excludesFile") + (error "Variable `core.excludesFile' isn't set"))) + (magit-refresh)) + +(defun magit--gitignore (rule file) + (when-let ((directory (file-name-directory file))) + (make-directory directory t)) + (with-temp-buffer + (when (file-exists-p file) + (insert-file-contents file)) + (goto-char (point-max)) + (unless (bolp) + (insert "\n")) + (insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" rule)) + (insert "\n") + (write-region nil nil file))) + +(defun magit-gitignore-read-pattern () + (let* ((default (magit-current-file)) + (choices + (delete-dups + (--mapcat + (cons (concat "/" it) + (when-let ((ext (file-name-extension it))) + (list (concat "/" (file-name-directory "foo") "*." ext) + (concat "*." ext)))) + (magit-untracked-files))))) + (when default + (setq default (concat "/" default)) + (unless (member default choices) + (setq default (concat "*." (file-name-extension default))) + (unless (member default choices) + (setq default nil)))) + (magit-completing-read "File or pattern to ignore" + choices nil nil nil nil default))) + +;;; Skip Worktree Commands + +;;;###autoload +(defun magit-skip-worktree (file) + "Call \"git update-index --skip-worktree FILE\"." + (interactive (list (magit-read-file-choice "Skip worktree for: " + (cl-set-difference + (magit-list-files) + (magit-skip-worktree-files))))) + (magit-with-toplevel + (magit-run-git "update-index" "--skip-worktree" "--" file))) + +;;;###autoload +(defun magit-no-skip-worktree (file) + "Call \"git update-index --no-skip-worktree FILE\"." + (interactive (list (magit-read-file-choice "Do not skip worktree for: " + (magit-skip-worktree-files)))) + (magit-with-toplevel + (magit-run-git "update-index" "--no-skip-worktree" "--" file))) + +;;; _ +(provide 'magit-gitignore) +;;; magit-gitignore.el ends here diff --git a/elpa/magit-20190122.503/magit-imenu.el b/elpa/magit-20190514.1814/magit-imenu.el similarity index 99% rename from elpa/magit-20190122.503/magit-imenu.el rename to elpa/magit-20190514.1814/magit-imenu.el index 2b2c298d..5125e8a8 100644 --- a/elpa/magit-20190122.503/magit-imenu.el +++ b/elpa/magit-20190514.1814/magit-imenu.el @@ -29,7 +29,7 @@ ;; a programming major mode). Selecting an item from this list moves ;; point to this item. -;; magit-imenu.el adds Imenu support to every major mode in Magit +;; magit-imenu.el adds Imenu support to every major mode in Magit. ;;; Code: @@ -39,6 +39,8 @@ (require 'magit) (require 'git-rebase) +;;; Core + (defun magit-imenu--index-function (entry-types menu-types) "Return an alist of imenu entries in current buffer. diff --git a/elpa/magit-20190122.503/magit-log.el b/elpa/magit-20190514.1814/magit-log.el similarity index 64% rename from elpa/magit-20190122.503/magit-log.el rename to elpa/magit-20190514.1814/magit-log.el index 1844ed62..e19db93a 100644 --- a/elpa/magit-20190122.503/magit-log.el +++ b/elpa/magit-20190514.1814/magit-log.el @@ -24,8 +24,8 @@ ;;; Commentary: ;; This library implements support for looking at Git logs, including -;; special logs like reflogs and cherry-logs, as well as for selecting -;; a commit from a log. +;; special logs like cherry-logs, as well as for selecting a commit +;; from a log. ;;; Code: @@ -41,6 +41,7 @@ (rev prompt &optional default)) (declare-function magit-show-commit "magit-diff" (arg1 &optional arg2 arg3 arg4)) +(declare-function magit-reflog-format-subject "magit-reflog" (subject)) (defvar magit-refs-focus-column-width) (defvar magit-refs-margin) (defvar magit-refs-show-commit-count) @@ -55,8 +56,6 @@ (eval-when-compile (require 'subr-x)) -(defvar bookmark-make-record-function) - ;;; Options ;;;; Log Mode @@ -70,13 +69,6 @@ :group 'magit-log :type 'hook) -(defcustom magit-log-arguments '("-n256" "--graph" "--decorate") - "The log arguments used in `magit-log-mode' buffers." - :package-version '(magit . "2.3.0") - :group 'magit-git-arguments - :group 'magit-log - :type '(repeat (string :tag "Argument"))) - (defcustom magit-log-remove-graph-args '("--follow" "--grep" "-G" "-S" "-L") "The log arguments that cause the `--graph' argument to be dropped." :package-version '(magit . "2.3.0") @@ -182,7 +174,7 @@ because the latter may make use of Imenu's outdated cache." ;;;; File Log (defcustom magit-log-buffer-file-locked t - "Whether `magit-log-buffer-file' uses a dedicated buffer." + "Whether `magit-log-buffer-file-quick' uses a dedicated buffer." :package-version '(magit . "2.7.0") :group 'magit-commands :group 'magit-log @@ -190,12 +182,6 @@ because the latter may make use of Imenu's outdated cache." ;;;; Select Mode -(defcustom magit-log-select-arguments '("-n256" "--graph" "--decorate") - "The log arguments used in `magit-log-select-mode' buffers." - :package-version '(magit . "2.3.0") - :group 'magit-log - :type '(repeat (string :tag "Argument"))) - (defcustom magit-log-select-show-usage 'both "Whether to show usage information when selecting a commit from a log. The message can be shown in the `echo-area' or the `header-line', or in @@ -274,78 +260,6 @@ AUTHOR-WIDTH has to be an integer. When the name of the author :set-after '(magit-log-margin) :set (apply-partially #'magit-margin-set-variable 'magit-cherry-mode)) -;;;; Reflog Mode - -(defcustom magit-reflog-arguments '("-n256") - "The log arguments used in `magit-reflog-mode' buffers." - :package-version '(magit . "2.3.0") - :group 'magit-git-arguments - :type '(repeat (string :tag "Argument"))) - -(defcustom magit-reflog-margin - (list (nth 0 magit-log-margin) - (nth 1 magit-log-margin) - 'magit-log-margin-width nil - (nth 4 magit-log-margin)) - "Format of the margin in `magit-reflog-mode' buffers. - -The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). - -If INIT is non-nil, then the margin is shown initially. -STYLE controls how to format the committer date. It can be one - of `age' (to show the age of the commit), `age-abbreviated' (to - abbreviate the time unit to a character), or a string (suitable - for `format-time-string') to show the actual date. -WIDTH controls the width of the margin. This exists for forward - compatibility and currently the value should not be changed. -AUTHOR controls whether the name of the author is also shown by - default. -AUTHOR-WIDTH has to be an integer. When the name of the author - is shown, then this specifies how much space is used to do so." - :package-version '(magit . "2.9.0") - :group 'magit-log - :group 'magit-margin - :type magit-log-margin--custom-type - :initialize 'magit-custom-initialize-reset - :set-after '(magit-log-margin) - :set (apply-partially #'magit-margin-set-variable 'magit-reflog-mode)) - -(defface magit-reflog-commit '((t :foreground "green")) - "Face for commit commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-amend '((t :foreground "magenta")) - "Face for amend commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-merge '((t :foreground "green")) - "Face for merge, checkout and branch commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-checkout '((t :foreground "blue")) - "Face for checkout commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-reset '((t :foreground "red")) - "Face for reset commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-rebase '((t :foreground "magenta")) - "Face for rebase commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-cherry-pick '((t :foreground "green")) - "Face for cherry-pick commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-remote '((t :foreground "cyan")) - "Face for pull and clone commands in reflogs." - :group 'magit-faces) - -(defface magit-reflog-other '((t :foreground "cyan")) - "Face for other commands in reflogs." - :group 'magit-faces) - ;;;; Log Sections (defcustom magit-log-section-commit-count 10 @@ -357,252 +271,273 @@ the upstream isn't ahead of the current branch) show." :group 'magit-status :type 'number) -(defcustom magit-log-section-arguments '("-n256" "--decorate") - "The log arguments used in buffers that show other things besides logs." - :package-version '(magit . "2.4.0") - :group 'magit-git-arguments - :group 'magit-log - :group 'magit-status - :type '(repeat (string :tag "Argument"))) +;;; Arguments +;;;; Prefix Classes + +(defclass magit-log-prefix (transient-prefix) + ((history-key :initform 'magit-log) + (major-mode :initform 'magit-log-mode))) + +(defclass magit-log-refresh-prefix (magit-log-prefix) + ((history-key :initform 'magit-log) + (major-mode :initform nil))) + +;;;; Prefix Methods + +(cl-defmethod transient-init-value ((obj magit-log-prefix)) + (pcase-let ((`(,args ,files) + (magit-log--get-value 'magit-log-mode + magit-prefix-use-buffer-arguments))) + (unless (eq current-transient-command 'magit-dispatch) + (when-let ((file (magit-file-relative-name))) + (setq files (list file)))) + (oset obj value (if files `(("--" ,@files) ,args) args)))) + +(cl-defmethod transient-init-value ((obj magit-log-refresh-prefix)) + (oset obj value (if magit-buffer-log-files + `(("--" ,@magit-buffer-log-files) + ,magit-buffer-log-args) + magit-buffer-log-args))) + +(cl-defmethod transient-set-value ((obj magit-log-prefix)) + (magit-log--set-value obj)) + +(cl-defmethod transient-save-value ((obj magit-log-prefix)) + (magit-log--set-value obj 'save)) + +;;;; Argument Access + +(defun magit-log-arguments (&optional mode) + "Return the current log arguments." + (if (memq current-transient-command '(magit-log magit-log-refresh)) + (pcase-let ((`(,args ,alist) + (transient-args nil t))) + (list args (cdr (assoc "--" alist)))) + (magit-log--get-value (or mode 'magit-log-mode)))) + +(defun magit-log--get-value (mode &optional use-buffer-args) + (unless use-buffer-args + (setq use-buffer-args magit-direct-use-buffer-arguments)) + (let (args files) + (cond + ((and (memq use-buffer-args '(always selected current)) + (eq major-mode mode)) + (setq args magit-buffer-log-args) + (setq files magit-buffer-log-files)) + ((and (memq use-buffer-args '(always selected)) + (when-let ((buffer (magit-get-mode-buffer + mode nil + (or (eq use-buffer-args 'selected) 'all)))) + (setq args (buffer-local-value 'magit-buffer-log-args buffer)) + (setq files (buffer-local-value 'magit-buffer-log-files buffer)) + t))) + ((plist-member (symbol-plist mode) 'magit-log-current-arguments) + (setq args (get mode 'magit-log-current-arguments))) + ((when-let ((elt (assq (intern (format "magit-log:%s" mode)) + transient-values))) + (setq args (cdr elt)) + t)) + (t + (setq args (get mode 'magit-log-default-arguments)))) + (list args files))) + +(defun magit-log--set-value (obj &optional save) + (pcase-let* ((obj (oref obj prototype)) + (mode (or (oref obj major-mode) major-mode)) + (key (intern (format "magit-log:%s" mode))) + (`(,args ,alist) + (-separate #'atom (transient-args))) + (files (cdr (assoc "--" alist)))) + (put mode 'magit-log-current-arguments args) + (when save + (setf (alist-get key transient-values) args) + (transient-save-values)) + (transient--history-push obj) + (setq magit-buffer-log-args args) + (unless (derived-mode-p 'magit-log-select-mode) + (setq magit-buffer-log-files files)) + (magit-refresh))) ;;; Commands -;;;; Popups - -(defvar magit-log-popup - '(:variable magit-log-arguments - :man-page "git-log" - :switches ((?g "Show graph" "--graph") - (?c "Show graph in color" "--color") - (?d "Show refnames" "--decorate") - (?S "Show signatures" "--show-signature") - (?u "Show diffs" "--patch") - (?s "Show diffstats" "--stat") - (?h "Show header" "++header" magit-log++header) - (?r "Show in reverse order" "--reverse") - (?D "Simplify by decoration" "--simplify-by-decoration") - (?f "Follow renames when showing single-file log" "--follow")) - :options ((?n "Limit number of commits" "-n") - (?f "Limit to files" "-- " magit-read-files) - (?a "Limit to author" "--author=") - (?o "Order commits by" "++order=" magit-log-select-order) - (?g "Search messages" "--grep=") - (?G "Search changes" "-G") - (?S "Search occurrences" "-S") - (?L "Trace line evolution" "-L" magit-read-file-trace)) - :actions ((?l "Log current" magit-log-current) - (?L "Log local branches" magit-log-branches) - (?r "Reflog current" magit-reflog-current) - (?o "Log other" magit-log-other) - (?b "Log all branches" magit-log-all-branches) - (?O "Reflog other" magit-reflog-other) - (?h "Log HEAD" magit-log-head) - (?a "Log all references" magit-log-all) - (?H "Reflog HEAD" magit-reflog-head)) - :default-action magit-log-current - :max-action-columns 3)) - -(defvar magit-log-mode-refresh-popup - '(:variable magit-log-arguments - :man-page "git-log" - :switches ((?g "Show graph" "--graph") - (?c "Show graph in color" "--color") - (?d "Show refnames" "--decorate") - (?S "Show signatures" "--show-signature") - (?u "Show diffs" "--patch") - (?s "Show diffstats" "--stat") - (?r "Show in reverse order" "--reverse") - (?D "Simplify by decoration" "--simplify-by-decoration") - (?f "Follow renames when showing single-file log" "--follow")) - :options ((?n "Limit number of commits" "-n") - (?f "Limit to files" "-- " magit-read-files) - (?a "Limit to author" "--author=") - (?o "Order commits by" "++order=" magit-log-select-order) - (?g "Search messages" "--grep=") - (?G "Search changes" "-G") - (?S "Search occurrences" "-S") - (?L "Trace line evolution" "-L" magit-read-file-trace)) - :actions ((?g "Refresh" magit-log-refresh) - (?L "Toggle margin" magit-toggle-margin) - (?s "Set defaults" magit-log-set-default-arguments) nil - (?w "Save defaults" magit-log-save-default-arguments)) - :max-action-columns 2)) - -(defvar magit-reflog-mode-refresh-popup - '(:variable magit-reflog-arguments - :man-page "git-reflog" - :options ((?n "Limit number of commits" "-n")))) - -(defvar magit-log-refresh-popup - '(:variable magit-log-arguments - :man-page "git-log" - :switches ((?g "Show graph" "--graph") - (?c "Show graph in color" "--color") - (?d "Show refnames" "--decorate")) - :options ((?n "Limit number of commits" "-n") - (?o "Order commits by" "++order=" magit-log-select-order)) - :actions ("Refresh" - (?g "buffer" magit-log-refresh) - (?s "buffer and set defaults" magit-log-set-default-arguments) - (?w "buffer and save defaults" magit-log-save-default-arguments) - "Margin" - (?L "toggle visibility" magit-toggle-margin) - (?l "cycle style" magit-cycle-margin-style) - (?d "toggle details" magit-toggle-margin-details)) - :max-action-columns 1)) - -(magit-define-popup-keys-deferred 'magit-log-popup) -(magit-define-popup-keys-deferred 'magit-log-mode-refresh-popup) -(magit-define-popup-keys-deferred 'magit-log-refresh-popup) - -(defun magit-log-select-order (&rest _ignored) - "Set one `---order' option in Git log. -This encompasses the options `--author-date-order', -`--date-order', and `--topo-order'." - (magit-read-char-case "Order commits by " t - (?t "[t]opography" "topo") - (?a "[a]uthor date" "author-date") - (?c "[c]ommitter date" "date"))) - -;; This is a dummy procedure used to show help in `magit-log-popup'. -(defun magit-log++header () - "Insert a header after each revision summary in Git log. -Customize `magit-log-revision-headers-format' to change this -header." - nil) - -(defun magit-log-get-buffer-args () - (cond ((and magit-use-sticky-arguments - (derived-mode-p 'magit-log-mode)) - (list (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args))) - ((and (eq magit-use-sticky-arguments t) - (--when-let (magit-mode-get-buffer 'magit-log-mode) - (with-current-buffer it - (list (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args)))))) - (t - (list (default-value 'magit-log-arguments) nil)))) - -(defun magit-log-arguments (&optional refresh) - (cond ((memq magit-current-popup - '(magit-log-popup magit-log-refresh-popup)) - (magit-popup-export-file-args magit-current-popup-args)) - ((and refresh (not (derived-mode-p 'magit-log-mode))) - (list magit-log-section-arguments nil)) - (t - (magit-log-get-buffer-args)))) - -;;;###autoload -(defun magit-log-popup (arg) - "Popup console for log commands." - (interactive "P") - (let ((magit-log-refresh-popup - (pcase major-mode - (`magit-log-mode magit-log-mode-refresh-popup) - (_ magit-log-refresh-popup))) - (magit-log-arguments - (apply #'magit-popup-import-file-args (magit-log-get-buffer-args)))) - (magit-invoke-popup 'magit-log-popup nil arg))) - -;;;###autoload -(defun magit-log-buffer-file-popup () - "Popup console for log commands. - -This is a variant of `magit-log-popup' which shows the same popup -but which limits the log to the file being visited in the current -buffer." +;;;; Prefix Commands + +;;;###autoload (autoload 'magit-log "magit-log" nil t) +(define-transient-command magit-log () + "Show a commit or reference log." + :man-page "git-log" + :class 'magit-log-prefix + ;; The grouping in git-log(1) appears to be guided by implementation + ;; details, so our logical grouping only follows it to an extend. + ;; Arguments that are "misplaced" here: + ;; 1. From "Commit Formatting". + ;; 2. From "Common Diff Options". + ;; 3. From unnamed first group. + ;; 4. Implemented by Magit. + ["Commit limiting" + (magit-log:-n) + (magit:--author) + (7 "=s" "Limit to commits since" "--since=" transient-read-date) + (7 "=u" "Limit to commits until" "--until=" transient-read-date) + (magit-log:--grep) + (magit-log:-G) ;2 + (magit-log:-S) ;2 + (magit-log:-L) ;2 + (7 "=m" "Omit merges" "--no-merges") + (7 "=p" "First parent" "--first-parent")] + ["History simplification" + (magit:--) + ("-f" "Follow renames when showing single-file log" "--follow") ;3 + ("-D" "Simplify by decoration" "--simplify-by-decoration")] + ["Commit ordering" + (magit-log:--*-order) + ("-r" "Reverse order" "--reverse")] + ["Formatting" + ("-g" "Show graph" "--graph") ;1 + ("-c" "Show graph in color" "--color") ;2 + ("-d" "Show refnames" "--decorate") ;3 + ("=S" "Show signatures" "--show-signature") ;1 + ("-h" "Show header" "++header") ;4 + ("-p" "Show diffs" ("-p" "--patch")) ;2 + ("-s" "Show diffstats" "--stat")] ;2 + [["Log" + ("l" "current" magit-log-current) + ("o" "other" magit-log-other) + ("h" "HEAD" magit-log-head)] + ["" + ("L" "local branches" magit-log-branches) + ("b" "all branches" magit-log-all-branches) + ("a" "all references" magit-log-all) + (7 "m" "merged" magit-log-merged)] + ["Reflog" + ("r" "current" magit-reflog-current) + ("O" "other" magit-reflog-other) + ("H" "HEAD" magit-reflog-head)] + [:if-non-nil magit-wip-mode + :description "Wiplog" + ("i" "index" magit-wip-log-index) + ("w" "worktree" magit-wip-log-worktree)]]) + +;;;###autoload (autoload 'magit-log-refresh "magit-log" nil t) +(define-transient-command magit-log-refresh () + "Change the arguments used for the log(s) in the current buffer." + :man-page "git-log" + :class 'magit-log-refresh-prefix + [:if-mode magit-log-mode + :class transient-subgroups + ["Commit limiting" + (magit-log:-n) + (magit:--author) + (magit-log:--grep) + (magit-log:-G) + (magit-log:-S) + (magit-log:-L)] + ["History simplification" + (magit:--) + ("-f" "Follow renames when showing single-file log" "--follow") + ("-D" "Simplify by decoration" "--simplify-by-decoration")] + ["Commit ordering" + (magit-log:--*-order) + ("-r" "Reverse order" "--reverse")] + ["Formatting" + ("-g" "Show graph" "--graph") + ("-c" "Show graph in color" "--color") + ("-d" "Show refnames" "--decorate") + ("=S" "Show signatures" "--show-signature") + ("-h" "Show header" "++header") + ("-p" "Show diffs" ("-p" "--patch")) + ("-s" "Show diffstats" "--stat")]] + [:if-not-mode magit-log-mode + :description "Arguments" + (magit-log:-n) + (magit-log:--*-order) + ("-g" "Show graph" "--graph") + ("-c" "Show graph in color" "--color") + ("-d" "Show refnames" "--decorate")] + [["Refresh" + ("g" "buffer" magit-log-refresh) + ("s" "buffer and set defaults" transient-set :transient nil) + ("w" "buffer and save defaults" transient-save :transient nil)] + ["Margin" + ("L" "toggle visibility" magit-toggle-margin) + ("l" "cycle style" magit-cycle-margin-style) + ("d" "toggle details" magit-toggle-margin-details) + ("x" "toggle shortstat" magit-toggle-log-margin-style)] + [:if-mode magit-log-mode + :description "Toggle" + ("b" "buffer lock" magit-toggle-buffer-lock)]] (interactive) - (if-let ((file (magit-file-relative-name))) - (let ((magit-log-arguments - (magit-popup-import-file-args - (if-let ((buffer (magit-mode-get-buffer 'magit-log-mode))) - (with-current-buffer buffer - (nth 2 magit-refresh-args)) - (default-value 'magit-log-arguments)) - (list file)))) - (magit-invoke-popup 'magit-log-popup nil nil)) - (user-error "Buffer isn't visiting a file"))) - -(defun magit-log-refresh-popup (arg) - "Popup console for changing log arguments in the current buffer." - (interactive "P") - (magit-log-refresh-assert) - (let ((magit-log-refresh-popup - (cond ((derived-mode-p 'magit-log-select-mode) - magit-log-refresh-popup) - ((derived-mode-p 'magit-log-mode) - (let ((def (copy-sequence magit-log-refresh-popup))) - (plist-put def :switches (plist-get magit-log-popup :switches)) - (plist-put def :options (plist-get magit-log-popup :options)) - def)) - (t - magit-log-refresh-popup))) - (magit-log-arguments - (cond ((derived-mode-p 'magit-log-select-mode) - (cadr magit-refresh-args)) - ((derived-mode-p 'magit-log-mode) - (magit-popup-import-file-args (nth 1 magit-refresh-args) - (nth 2 magit-refresh-args))) - (t - magit-log-section-arguments)))) - (magit-invoke-popup 'magit-log-refresh-popup nil arg))) + (cond + ((not (eq current-transient-command 'magit-log-refresh)) + (pcase major-mode + (`magit-reflog-mode + (user-error "Cannot change log arguments in reflog buffers")) + (`magit-cherry-mode + (user-error "Cannot change log arguments in cherry buffers"))) + (transient-setup 'magit-log-refresh)) + (t + (pcase-let ((`(,args ,files) (magit-log-arguments))) + (setq magit-buffer-log-args args) + (unless (derived-mode-p 'magit-log-select-mode) + (setq magit-buffer-log-files files))) + (magit-refresh)))) + +;;;; Infix Commands + +(define-infix-argument magit-log:-n () + :description "Limit number of commits" + :class 'transient-option + ;; For historic reasons (and because it easy to guess what "-n" + ;; stands for) this is the only argument where we do not use the + ;; long argument ("--max-count"). If we did switch to the long + ;; argument, then that would cause breakage for users who have + ;; customized `magit-log-arguments'. + :shortarg "-n" + :argument "-n" + :reader 'transient-read-number-N+) + +(define-infix-argument magit:--author () + :description "Limit to author" + :class 'transient-option + :key "-A" + :argument "--author=" + :reader 'magit-transient-read-person) + +(define-infix-argument magit-log:--*-order () + :description "Order commits by" + :class 'transient-switches + :key "-o" + :argument-format "--%s-order" + :argument-regexp "\\(--\\(topo\\|author-date\\|date\\)-order\\)" + :choices '("topo" "author-date" "date")) + +(define-infix-argument magit-log:--grep () + :description "Search messages" + :class 'transient-option + :key "-F" + :argument "--grep=") + +(define-infix-argument magit-log:-G () + :description "Search changes" + :class 'transient-option + :argument "-G") + +(define-infix-argument magit-log:-S () + :description "Search occurrences" + :class 'transient-option + :argument "-S") + +(define-infix-argument magit-log:-L () + :description "Trace line evolution" + :class 'transient-option + :argument "-L" + :reader 'magit-read-file-trace) (defun magit-read-file-trace (&rest _ignored) (let ((file (magit-read-file-from-rev "HEAD" "File")) (trace (magit-read-string "Trace"))) (concat trace (or (match-string 2 trace) ":") file))) -;;;; Refresh Commands - -(defun magit-log-refresh (args files) - "Set the local log arguments for the current buffer." - (interactive (magit-log-arguments t)) - (magit-log-refresh-assert) - (cond ((derived-mode-p 'magit-log-select-mode) - (setcar (cdr magit-refresh-args) args)) - ((derived-mode-p 'magit-log-mode) - (setcdr magit-refresh-args (list args files))) - (t - (setq-local magit-log-section-arguments args))) - (magit-refresh)) - -(defun magit-log-set-default-arguments (args files) - "Set the global log arguments for the current buffer." - (interactive (magit-log-arguments t)) - (magit-log-refresh-assert) - (cond ((derived-mode-p 'magit-log-select-mode) - (customize-set-variable 'magit-log-select-arguments args) - (setcar (cdr magit-refresh-args) args)) - ((derived-mode-p 'magit-log-mode) - (customize-set-variable 'magit-log-arguments args) - (setcdr magit-refresh-args (list args files))) - (t - (customize-set-variable 'magit-log-section-arguments args) - (kill-local-variable 'magit-log-section-arguments))) - (magit-refresh)) - -(defun magit-log-save-default-arguments (args files) - "Set and save the global log arguments for the current buffer." - (interactive (magit-log-arguments t)) - (magit-log-refresh-assert) - (cond ((derived-mode-p 'magit-log-select-mode) - (customize-save-variable 'magit-log-select-arguments args) - (setcar (cdr magit-refresh-args) args)) - ((derived-mode-p 'magit-log-mode) - (customize-save-variable 'magit-log-arguments args) - (setcdr magit-refresh-args (list args files))) - (t - (customize-save-variable 'magit-log-section-arguments args) - (kill-local-variable 'magit-log-section-arguments))) - (magit-refresh)) - -(defun magit-log-refresh-assert () - (cond ((derived-mode-p 'magit-reflog-mode) - (user-error "Cannot change log arguments in reflog buffers")) - ((derived-mode-p 'magit-cherry-mode) - (user-error "Cannot change log arguments in cherry buffers")))) - -;;;; Log Commands +;;;; Setup Commands (defvar magit-log-read-revs-map (let ((map (make-sparse-keymap))) @@ -612,9 +547,7 @@ buffer." (defun magit-log-read-revs (&optional use-current) (or (and use-current (--when-let (magit-get-current-branch) (list it))) - (let ((collection `(,@(and (file-exists-p (magit-git-dir "FETCH_HEAD")) - (list "FETCH_HEAD")) - ,@(magit-list-refnames)))) + (let ((collection (magit-list-refnames nil t))) (split-string (magit-completing-read-multiple "Log rev,s" collection "\\(\\.\\.\\.?\\|[, ]\\)" @@ -625,11 +558,6 @@ buffer." magit-log-read-revs-map) "[, ]" t)))) -(defun magit-git-log (revs args files) - (require 'magit) - (magit-mode-setup #'magit-log-mode revs args files) - (magit-log-goto-same-commit)) - ;;;###autoload (defun magit-log-current (revs &optional args files) "Show log for the current branch. @@ -637,7 +565,7 @@ When `HEAD' is detached or with a prefix argument show log for one or more revs read from the minibuffer." (interactive (cons (magit-log-read-revs t) (magit-log-arguments))) - (magit-git-log revs args files)) + (magit-log-setup-buffer revs args files)) ;;;###autoload (defun magit-log-other (revs &optional args files) @@ -648,40 +576,40 @@ representation of the commit at point, are available as completion candidates." (interactive (cons (magit-log-read-revs) (magit-log-arguments))) - (magit-git-log revs args files)) + (magit-log-setup-buffer revs args files)) ;;;###autoload (defun magit-log-head (&optional args files) "Show log for `HEAD'." (interactive (magit-log-arguments)) - (magit-git-log (list "HEAD") args files)) + (magit-log-setup-buffer (list "HEAD") args files)) ;;;###autoload (defun magit-log-branches (&optional args files) "Show log for all local branches and `HEAD'." (interactive (magit-log-arguments)) - (magit-git-log (if (magit-get-current-branch) - (list "--branches") - (list "HEAD" "--branches")) - args files)) + (magit-log-setup-buffer (if (magit-get-current-branch) + (list "--branches") + (list "HEAD" "--branches")) + args files)) ;;;###autoload (defun magit-log-all-branches (&optional args files) "Show log for all local and remote branches and `HEAD'." (interactive (magit-log-arguments)) - (magit-git-log (if (magit-get-current-branch) - (list "--branches" "--remotes") - (list "HEAD" "--branches" "--remotes")) - args files)) + (magit-log-setup-buffer (if (magit-get-current-branch) + (list "--branches" "--remotes") + (list "HEAD" "--branches" "--remotes")) + args files)) ;;;###autoload (defun magit-log-all (&optional args files) "Show log for all references and `HEAD'." (interactive (magit-log-arguments)) - (magit-git-log (if (magit-get-current-branch) - (list "--all") - (list "HEAD" "--all")) - args files)) + (magit-log-setup-buffer (if (magit-get-current-branch) + (list "--all") + (list "HEAD" "--all")) + args files)) ;;;###autoload (defun magit-log-buffer-file (&optional follow beg end) @@ -705,26 +633,24 @@ active, restrict the log to the lines that the region touches." (1- end))))))))) (require 'magit) (if-let ((file (magit-file-relative-name))) - (magit-mode-setup-internal - #'magit-log-mode - (list (list (or magit-buffer-refname - (magit-get-current-branch) - "HEAD")) - (let ((args (car (magit-log-arguments)))) - (when (and follow (not (member "--follow" args))) - (push "--follow" args)) - (when (and (file-regular-p - (expand-file-name file (magit-toplevel))) - beg end) - (setq args (cons (format "-L%s,%s:%s" beg end file) - (cl-delete "-L" args :test - 'string-prefix-p))) - (setq file nil)) - args) - (and file (list file))) + (magit-log-setup-buffer + (list (or magit-buffer-refname + (magit-get-current-branch) + "HEAD")) + (let ((args (car (magit-log-arguments)))) + (when (and follow (not (member "--follow" args))) + (push "--follow" args)) + (when (and (file-regular-p + (expand-file-name file (magit-toplevel))) + beg end) + (setq args (cons (format "-L%s,%s:%s" beg end file) + (cl-delete "-L" args :test + 'string-prefix-p))) + (setq file nil)) + args) + (and file (list file)) magit-log-buffer-file-locked) - (user-error "Buffer isn't visiting a file")) - (magit-log-goto-same-commit)) + (user-error "Buffer isn't visiting a file"))) ;;;###autoload (defun magit-log-trace-definition (file fn rev) @@ -736,47 +662,42 @@ active, restrict the log to the lines that the region touches." (magit-get-current-branch) "HEAD"))) (require 'magit) - (magit-mode-setup-internal - #'magit-log-mode - (list (list rev) - (cons (format "-L:%s%s:%s" - (regexp-quote fn) - (if (derived-mode-p 'lisp-mode 'emacs-lisp-mode) - ;; Git doesn't treat "-" the same way as - ;; "_", leading to false-positives such as - ;; "foo-suffix" being considered a match - ;; for "foo". Wing it. - "\\( \\|$\\)" - ;; We could use "\\b" here, but since Git - ;; already does something equivalent, that - ;; isn't necessary. - "") - file) - (cl-delete "-L" (car (magit-log-arguments)) - :test 'string-prefix-p)) - nil) - magit-log-buffer-file-locked) - (magit-log-goto-same-commit)) + (magit-log-setup-buffer + (list rev) + (cons (format "-L:%s%s:%s" + (regexp-quote fn) + (if (derived-mode-p 'lisp-mode 'emacs-lisp-mode) + ;; Git doesn't treat "-" the same way as + ;; "_", leading to false-positives such as + ;; "foo-suffix" being considered a match + ;; for "foo". Wing it. + "\\( \\|$\\)" + ;; We could use "\\b" here, but since Git + ;; already does something equivalent, that + ;; isn't necessary. + "") + file) + (cl-delete "-L" (car (magit-log-arguments)) + :test 'string-prefix-p)) + nil magit-log-buffer-file-locked)) (defun magit-diff-trace-definition () "Show log for the definition at point in a diff." (interactive) - (let (buf pos) - (save-window-excursion - (call-interactively #'magit-diff-visit-file) - (setq buf (current-buffer)) - (setq pos (point))) - (save-excursion - (with-current-buffer buf - (goto-char pos) - (call-interactively #'magit-log-trace-definition))))) + (pcase-let ((`(,buf ,pos) (magit-diff-visit-file--noselect))) + (magit--with-temp-position buf pos + (call-interactively #'magit-log-trace-definition)))) ;;;###autoload (defun magit-log-merged (commit branch &optional args files) "Show log for the merge of COMMIT into BRANCH. + More precisely, find merge commit M that brought COMMIT into -BRANCH, and show the log of the range \"M^..M\". This command -requires git-when-merged, which is available from +BRANCH, and show the log of the range \"M^1..M\". If COMMIT is +directly on BRANCH, then show approximately twenty surrounding +commits instead. + +This command requires git-when-merged, which is available from https://github.com/mhagger/git-when-merged." (interactive (append (let ((commit (magit-read-branch-or-commit "Commit"))) @@ -786,34 +707,33 @@ https://github.com/mhagger/git-when-merged." (unless (executable-find "git-when-merged") (user-error "This command requires git-when-merged (%s)" "https://github.com/mhagger/git-when-merged")) - (magit-git-log - (list (or (magit-git-string "when-merged" "--show-branch" commit branch) - (user-error "Could not find when %s was merged into %s" - commit branch))) - args files)) - -(defun magit-git-reflog (ref args) - (require 'magit) - (magit-mode-setup #'magit-reflog-mode ref args)) - -;;;###autoload -(defun magit-reflog-current (args) - "Display the reflog of the current branch." - (interactive (list magit-reflog-arguments)) - (magit-git-reflog (magit-get-current-branch) args)) - -;;;###autoload -(defun magit-reflog-other (ref args) - "Display the reflog of a branch or another ref." - (interactive (list (magit-read-local-branch-or-ref "Show reflog for") - magit-reflog-arguments)) - (magit-git-reflog ref args)) - -;;;###autoload -(defun magit-reflog-head (args) - "Display the `HEAD' reflog." - (interactive (list magit-reflog-arguments)) - (magit-git-reflog "HEAD" args)) + (let (exit m) + (with-temp-buffer + (save-excursion + (setq exit (magit-process-file + magit-git-executable nil t nil + "when-merged" "-c" + "--abbrev" (number-to-string (magit-abbrev-length)) + commit branch))) + (setq m (buffer-substring-no-properties (point) (line-end-position)))) + (if (zerop exit) + (magit-log-setup-buffer (list (format "%s^1..%s" m m)) + args files nil commit) + (setq m (string-trim-left (substring m (string-match " " m)))) + (if (equal m "Commit is directly on this branch.") + (let* ((from (concat commit "~10")) + (to (- (car (magit-rev-diff-count branch commit)) 10)) + (to (if (<= to 0) + branch + (format "%s~%s" branch to)))) + (unless (magit-rev-verify-commit from) + (setq from (magit-git-string "rev-list" "--max-parents=0" + commit))) + (magit-log-setup-buffer (list (concat from ".." to)) + (cons "--first-parent" args) + files nil commit)) + (user-error "Could not find when %s was merged into %s: %s" + commit branch m))))) ;;;; Limit Commands @@ -835,23 +755,23 @@ limit. Otherwise set it to 256." (magit-log-set-commit-limit '/)) (defun magit-log-set-commit-limit (fn) - (let* ((val (car (magit-log-arguments t))) + (let* ((val magit-buffer-log-args) (arg (--first (string-match "^-n\\([0-9]+\\)?$" it) val)) (num (and arg (string-to-number (match-string 1 arg)))) (num (if num (funcall fn num 2) 256))) (setq val (delete arg val)) - (setcar (cdr magit-refresh-args) - (if (and num (> num 0)) - (cons (format "-n%i" num) val) - val))) + (setq magit-buffer-log-args + (if (and num (> num 0)) + (cons (format "-n%i" num) val) + val))) (magit-refresh)) (defun magit-log-get-commit-limit () (--when-let (--first (string-match "^-n\\([0-9]+\\)?$" it) - (car (magit-log-arguments t))) + magit-buffer-log-args) (string-to-number (match-string 1 it)))) -;;;; Other Commands +;;;; Mode Commands (defun magit-log-bury-buffer (&optional arg) "Bury the current buffer or the revision buffer in the same frame. @@ -860,7 +780,7 @@ prefix argument instead bury the revision buffer, provided it is displayed in the current frame." (interactive "p") (if (< arg 0) - (let* ((buf (magit-mode-get-buffer 'magit-revision-mode)) + (let* ((buf (magit-get-mode-buffer 'magit-revision-mode)) (win (and buf (get-buffer-window buf (selected-frame))))) (if win (with-selected-window win @@ -890,6 +810,10 @@ is displayed in the current frame." ;;; Log Mode +(defvar magit-log-disable-graph-hack-args + '("-G" "--grep" "--author") + "Arguments which disable the graph speedup hack.") + (defvar magit-log-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-mode-map) @@ -913,9 +837,9 @@ Type \\[magit-refresh] to refresh the current buffer. Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ to visit the commit at point. -Type \\[magit-branch-popup] to see available branch commands. -Type \\[magit-merge-popup] to merge the branch or commit at point. -Type \\[magit-cherry-pick-popup] to apply the commit at point. +Type \\[magit-branch] to see available branch commands. +Type \\[magit-merge] to merge the branch or commit at point. +Type \\[magit-cherry-pick] to apply the commit at point. Type \\[magit-reset] to reset `HEAD' to the commit at point. \\{magit-log-mode-map}" @@ -924,45 +848,64 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point. (setq imenu-prev-index-position-function 'magit-imenu--log-prev-index-position-function) (setq imenu-extract-index-name-function - 'magit-imenu--log-extract-index-name-function) - (setq-local bookmark-make-record-function - 'magit-bookmark--log-make-record)) + 'magit-imenu--log-extract-index-name-function)) -(defvar magit-log-disable-graph-hack-args - '("-G" "--grep" "--author") - "Arguments which disable the graph speedup hack.") +(put 'magit-log-mode 'magit-log-default-arguments + '("--graph" "-n256" "--decorate")) -(defun magit-log-refresh-buffer (revs args files) - (magit-set-header-line-format - (funcall magit-log-header-line-function revs args files)) - (if (= (length files) 1) - (unless (magit-file-tracked-p (car files)) - (setq args (cons "--full-history" args))) - (setq args (remove "--follow" args))) - (when (--any-p (string-match-p - (concat "^" (regexp-opt magit-log-remove-graph-args)) it) - args) - (setq args (remove "--graph" args))) - (unless (member "--graph" args) - (setq args (remove "--color" args))) - (when-let ((limit (magit-log-get-commit-limit)) - (limit (* 2 limit)) ; increase odds for complete graph - (count (and (= (length revs) 1) - (> limit 1024) ; otherwise it's fast enough - (setq revs (car revs)) - (not (string-match-p "\\.\\." revs)) - (not (member revs '("--all" "--branches"))) - (-none-p (lambda (arg) - (--any-p (string-prefix-p it arg) - magit-log-disable-graph-hack-args)) - args) - (magit-git-string "rev-list" "--count" - "--first-parent" args revs)))) - (setq revs (if (< (string-to-number count) limit) - revs - (format "%s~%s..%s" revs limit revs)))) - (magit-insert-section (logbuf) - (magit-insert-log revs args files))) +(defun magit-log-setup-buffer (revs args files &optional locked focus) + (require 'magit) + (with-current-buffer + (magit-setup-buffer #'magit-log-mode locked + (magit-buffer-revisions revs) + (magit-buffer-log-args args) + (magit-buffer-log-files files)) + (when (if focus + (magit-log-goto-commit-section focus) + (magit-log-goto-same-commit)) + (magit-section-update-highlight)) + (current-buffer))) + +(defun magit-log-refresh-buffer () + (let ((revs magit-buffer-revisions) + (args magit-buffer-log-args) + (files magit-buffer-log-files)) + (magit-set-header-line-format + (funcall magit-log-header-line-function revs args files)) + (if (= (length files) 1) + (unless (magit-file-tracked-p (car files)) + (setq args (cons "--full-history" args))) + (setq args (remove "--follow" args))) + (when (--any-p (string-match-p + (concat "^" (regexp-opt magit-log-remove-graph-args)) it) + args) + (setq args (remove "--graph" args))) + (unless (member "--graph" args) + (setq args (remove "--color" args))) + (when-let ((limit (magit-log-get-commit-limit)) + (limit (* 2 limit)) ; increase odds for complete graph + (count (and (= (length revs) 1) + (> limit 1024) ; otherwise it's fast enough + (setq revs (car revs)) + (not (string-match-p "\\.\\." revs)) + (not (member revs '("--all" "--branches"))) + (-none-p (lambda (arg) + (--any-p (string-prefix-p it arg) + magit-log-disable-graph-hack-args)) + args) + (magit-git-string "rev-list" "--count" + "--first-parent" args revs)))) + (setq revs (if (< (string-to-number count) limit) + revs + (format "%s~%s..%s" revs limit revs)))) + (magit-insert-section (logbuf) + (magit-insert-log revs args files)))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-log-mode)) + (append magit-buffer-revisions + (if (and magit-buffer-revisions magit-buffer-log-files) + (cons "--" magit-buffer-log-files) + magit-buffer-log-files))) (defun magit-log-header-line-arguments (revs args files) "Return string describing some of the used arguments." @@ -992,12 +935,12 @@ Do not add this to a hook variable." (remove "--literal-pathspecs" magit-git-global-arguments))) (magit-git-wash (apply-partially #'magit-log-wash-log 'log) "log" - (format "--format=%s%%h%s%%x00%s%%x00%%aN%%x00%%at%%x00%%s%s" + (format "--format=%s%%h%%x00%s%%x00%s%%x00%%aN%%x00%%at%%x00%%s%s" (if (and (member "--left-right" args) (not (member "--graph" args))) "%m " "") - (if (member "--decorate" args) "%d" "") + (if (member "--decorate" args) "%D" "") (if (member "--show-signature" args) (progn (setq args (remove "--show-signature" args)) "%G?") "") @@ -1033,8 +976,8 @@ Do not add this to a hook variable." (defconst magit-log-heading-re (concat "^" "\\(?4:[-_/|\\*o<>. ]*\\)" ; graph - "\\(?1:[0-9a-fA-F]+\\)" ; sha1 - "\\(?3:[^\0\n]+)\\)?\0" ; refs + "\\(?1:[0-9a-fA-F]+\\)?\0" ; sha1 + "\\(?3:[^\0\n]+\\)?\0" ; refs "\\(?7:[BGUXYREN]\\)?\0" ; gpg "\\(?5:[^\0\n]*\\)\0" ; author ;; Note: Date is optional because, prior to Git v2.19.0, @@ -1057,8 +1000,8 @@ Do not add this to a hook variable." (defconst magit-log-bisect-vis-re (concat "^" "\\(?4:[-_/|\\*o<>. ]*\\)" ; graph - "\\(?1:[0-9a-fA-F]+\\)" ; sha1 - "\\(?3:[^\0\n]+)\\)?\0" ; refs + "\\(?1:[0-9a-fA-F]+\\)?\0" ; sha1 + "\\(?3:[^\0\n]+\\)?\0" ; refs "\\(?2:.*\\)$")) ; msg (defconst magit-log-bisect-log-re @@ -1105,7 +1048,7 @@ Do not add this to a hook variable." (let ((magit-log-count 0)) (magit-wash-sequence (apply-partially 'magit-log-wash-rev style (magit-abbrev-length))) - (if (derived-mode-p 'magit-log-mode) + (if (derived-mode-p 'magit-log-mode 'magit-reflog-mode) (when (eq magit-log-count (magit-log-get-commit-limit)) (magit-insert-section (longer) (insert-text-button @@ -1120,7 +1063,7 @@ Do not add this to a hook variable." (insert ?\n)))) (cl-defun magit-log-wash-rev (style abbrev) - (when (derived-mode-p 'magit-log-mode) + (when (derived-mode-p 'magit-log-mode 'magit-reflog-mode) (cl-incf magit-log-count)) (looking-at (pcase style (`log magit-log-heading-re) @@ -1136,7 +1079,7 @@ Do not add this to a hook variable." (when refs (setq refs (substring-no-properties refs))) (let ((align (or (eq style 'cherry) - (not (member "--stat" (cadr magit-refresh-args))))) + (not (member "--stat" magit-buffer-log-args)))) (non-graph-re (if (eq style 'bisect-vis) magit-log-bisect-vis-re magit-log-heading-re))) @@ -1286,19 +1229,21 @@ exists mostly for backward compatibility reasons." (defvar magit--update-revision-buffer nil) (defun magit-log-maybe-update-revision-buffer (&optional _) - "When moving in the log buffer, update the revision buffer. + "When moving in a log or cherry buffer, update the revision buffer. If there is no revision buffer in the same frame, then do nothing." - (when (derived-mode-p 'magit-log-mode) + (when (derived-mode-p 'magit-log-mode 'magit-cherry-mode 'magit-reflog-mode) (magit-log-maybe-update-revision-buffer-1))) (defun magit-log-maybe-update-revision-buffer-1 () (unless magit--update-revision-buffer (when-let ((commit (magit-section-value-if 'commit)) - (buffer (magit-mode-get-buffer 'magit-revision-mode nil t))) + (buffer (magit-get-mode-buffer 'magit-revision-mode nil t))) (setq magit--update-revision-buffer (list commit buffer)) (run-with-idle-timer magit-update-other-window-delay nil - (let ((args (magit-show-commit--arguments))) + (let ((args (with-current-buffer buffer + (let ((magit-direct-use-buffer-arguments 'selected)) + (magit-show-commit--arguments))))) (lambda () (pcase-let ((`(,rev ,buf) magit--update-revision-buffer)) (setq magit--update-revision-buffer nil) @@ -1310,15 +1255,17 @@ If there is no revision buffer in the same frame, then do nothing." (defvar magit--update-blob-buffer nil) (defun magit-log-maybe-update-blob-buffer (&optional _) - "When moving in the log buffer, update the blob buffer. + "When moving in a log or cherry buffer, update the blob buffer. If there is no blob buffer in the same frame, then do nothing." - (when (derived-mode-p 'magit-log-mode) + (when (derived-mode-p 'magit-log-mode 'magit-cherry-mode 'magit-reflog-mode) (magit-log-maybe-update-blob-buffer-1))) (defun magit-log-maybe-update-blob-buffer-1 () (unless magit--update-revision-buffer (when-let ((commit (magit-section-value-if 'commit)) - (buffer (--first (with-current-buffer it magit-buffer-revision) + (buffer (--first (with-current-buffer it + (eq revert-buffer-function + 'magit-revert-rev-file-buffer)) (mapcar #'window-buffer (window-list))))) (setq magit--update-blob-buffer (list commit buffer)) (run-with-idle-timer @@ -1327,24 +1274,25 @@ If there is no blob buffer in the same frame, then do nothing." (pcase-let ((`(,rev ,buf) magit--update-blob-buffer)) (setq magit--update-blob-buffer nil) (when (buffer-live-p buf) - (save-excursion - (with-selected-window (get-buffer-window buf) - (with-current-buffer buf + (with-selected-window (get-buffer-window buf) + (with-current-buffer buf + (save-excursion (magit-blob-visit (list (magit-rev-parse rev) (magit-file-relative-name magit-buffer-file-name)) (line-number-at-pos)))))))))))) -(defun magit-log-goto-same-commit (&optional default) - (let ((prev magit-previous-section)) - (when-let ((rev (cond ((and prev (magit-section-match 'commit prev)) - (oref prev value)) - ((and prev (magit-section-match 'branch prev)) - (magit-rev-format "%h" (oref prev value))) - (default (magit-rev-format "%h" default)))) - (same (--first (equal (oref it value) rev) - (oref magit-root-section children)))) - (goto-char (oref same start))))) +(defun magit-log-goto-commit-section (rev) + (let ((abbrev (magit-rev-format "%h" rev))) + (when-let ((section (--first (equal (oref it value) abbrev) + (oref magit-root-section children)))) + (goto-char (oref section start))))) + +(defun magit-log-goto-same-commit () + (when (and magit-previous-section + (magit-section-match '(commit branch) + magit-previous-section)) + (magit-log-goto-commit-section (oref magit-previous-section value)))) ;;; Log Margin @@ -1455,9 +1403,21 @@ Type \\[magit-log-select-quit] to abort without selecting a commit." :group 'magit-log (hack-dir-local-variables-non-file-buffer)) -(defun magit-log-select-refresh-buffer (rev args) +(put 'magit-log-select-mode 'magit-log-default-arguments + '("--graph" "-n256" "--decorate")) + +(defun magit-log-select-setup-buffer (revs args) + (magit-setup-buffer #'magit-log-select-mode nil + (magit-buffer-revisions revs) + (magit-buffer-log-args args))) + +(defun magit-log-select-refresh-buffer () (magit-insert-section (logbuf) - (magit-insert-log rev args))) + (magit-insert-log magit-buffer-revisions + magit-buffer-log-args))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-log-select-mode)) + magit-buffer-revisions) (defvar-local magit-log-select-pick-function nil) (defvar-local magit-log-select-quit-function nil) @@ -1466,10 +1426,13 @@ Type \\[magit-log-select-quit] to abort without selecting a commit." (declare (indent defun)) (unless initial (setq initial (magit-commit-at-point))) - (magit-mode-setup #'magit-log-select-mode - (or branch (magit-get-current-branch) "HEAD") - (append args magit-log-select-arguments)) - (magit-log-goto-same-commit initial) + (magit-log-select-setup-buffer + (or branch (magit-get-current-branch) "HEAD") + (append args + (car (magit-log--get-value 'magit-log-select-mode + magit-direct-use-buffer-arguments)))) + (when initial + (magit-log-goto-commit-section initial)) (setq magit-log-select-pick-function pick) (setq magit-log-select-quit-function quit) (when magit-log-select-show-usage @@ -1518,7 +1481,7 @@ commit as argument." (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-mode-map) (define-key map "q" 'magit-log-bury-buffer) - (define-key map "L" 'magit-margin-popup) + (define-key map "L" 'magit-margin-settings) map) "Keymap for `magit-cherry-mode'.") @@ -1530,15 +1493,26 @@ Type \\[magit-refresh] to refresh the current buffer. Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ to visit the commit at point. -Type \\[magit-cherry-pick-popup] to apply the commit at point. +Type \\[magit-cherry-pick] to apply the commit at point. \\{magit-cherry-mode-map}" :group 'magit-log (hack-dir-local-variables-non-file-buffer) (setq imenu-create-index-function - 'magit-imenu--cherry-create-index-function) - (setq-local bookmark-make-record-function - 'magit-bookmark--cherry-make-record)) + 'magit-imenu--cherry-create-index-function)) + +(defun magit-cherry-setup-buffer (head upstream) + (magit-setup-buffer #'magit-cherry-mode nil + (magit-buffer-refname head) + (magit-buffer-upstream upstream) + (magit-buffer-range (concat upstream ".." head)))) + +(defun magit-cherry-refresh-buffer () + (magit-insert-section (cherry) + (magit-run-section-hook 'magit-cherry-sections-hook))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-cherry-mode)) + magit-buffer-range) ;;;###autoload (defun magit-cherry (head upstream) @@ -1548,94 +1522,27 @@ Type \\[magit-cherry-pick-popup] to apply the commit at point. (list head (magit-read-other-branch "Cherry upstream" head (magit-get-upstream-branch head))))) (require 'magit) - (magit-mode-setup #'magit-cherry-mode upstream head)) - -(defun magit-cherry-refresh-buffer (_upstream _head) - (magit-insert-section (cherry) - (magit-run-section-hook 'magit-cherry-sections-hook))) + (magit-cherry-setup-buffer head upstream)) (defun magit-insert-cherry-headers () "Insert headers appropriate for `magit-cherry-mode' buffers." - (magit-insert-head-branch-header (nth 1 magit-refresh-args)) - (magit-insert-upstream-branch-header (nth 1 magit-refresh-args) - (nth 0 magit-refresh-args) - "Upstream: ") - (insert ?\n)) + (let ((branch (propertize magit-buffer-refname 'face 'magit-branch-local)) + (upstream (propertize magit-buffer-upstream 'face + (if (magit-local-branch-p magit-buffer-upstream) + 'magit-branch-local + 'magit-branch-remote)))) + (magit-insert-head-branch-header branch) + (magit-insert-upstream-branch-header branch upstream "Upstream: ") + (insert ?\n))) (defun magit-insert-cherry-commits () "Insert commit sections into a `magit-cherry-mode' buffer." (magit-insert-section (cherries) (magit-insert-heading "Cherry commits:") (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) - "cherry" "-v" "--abbrev" magit-refresh-args))) - -;;; Reflog Mode - -(defvar magit-reflog-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-log-mode-map) - (define-key map "L" 'magit-margin-popup) - map) - "Keymap for `magit-reflog-mode'.") - -(define-derived-mode magit-reflog-mode magit-log-mode "Magit Reflog" - "Mode for looking at Git reflog. - -This mode is documented in info node `(magit)Reflog'. - -\\\ -Type \\[magit-refresh] to refresh the current buffer. -Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ -to visit the commit at point. - -Type \\[magit-cherry-pick-popup] to apply the commit at point. -Type \\[magit-reset] to reset `HEAD' to the commit at point. - -\\{magit-reflog-mode-map}" - :group 'magit-log - (hack-dir-local-variables-non-file-buffer) - (setq-local bookmark-make-record-function - 'magit-bookmark--reflog-make-record)) - -(defun magit-reflog-refresh-buffer (ref args) - (magit-set-header-line-format (concat "Reflog for " ref)) - (magit-insert-section (reflogbuf) - (magit-git-wash (apply-partially 'magit-log-wash-log 'reflog) - "reflog" "show" "--format=%h%x00%aN%x00%gd%x00%gs" "--date=raw" - args ref "--"))) - -(defvar magit-reflog-labels - '(("commit" . magit-reflog-commit) - ("amend" . magit-reflog-amend) - ("merge" . magit-reflog-merge) - ("checkout" . magit-reflog-checkout) - ("branch" . magit-reflog-checkout) - ("reset" . magit-reflog-reset) - ("rebase" . magit-reflog-rebase) - ("cherry-pick" . magit-reflog-cherry-pick) - ("initial" . magit-reflog-commit) - ("pull" . magit-reflog-remote) - ("clone" . magit-reflog-remote) - ("autosave" . magit-reflog-commit) - ("restart" . magit-reflog-reset))) - -(defun magit-reflog-format-subject (subject) - (let* ((match (string-match magit-reflog-subject-re subject)) - (command (and match (match-string 1 subject))) - (option (and match (match-string 2 subject))) - (type (and match (match-string 3 subject))) - (label (if (string= command "commit") - (or type command) - command)) - (text (if (string= command "commit") - label - (mapconcat #'identity - (delq nil (list command option type)) - " ")))) - (format "%-16s " - (propertize text 'face - (or (cdr (assoc label magit-reflog-labels)) - 'magit-reflog-other))))) + "cherry" "-v" "--abbrev" + magit-buffer-upstream + magit-buffer-refname))) ;;; Log Sections ;;;; Standard Log Sections @@ -1651,12 +1558,12 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point. (defun magit-insert-unpulled-from-upstream () "Insert commits that haven't been pulled from the upstream yet." - (when (magit-git-success "rev-parse" "@{upstream}") + (when-let ((upstream (magit-get-upstream-branch))) (magit-insert-section (unpulled "..@{upstream}" t) (magit-insert-heading (format (propertize "Unpulled from %s:" 'face 'magit-section-heading) - (magit-get-upstream-branch))) - (magit-insert-log "..@{upstream}" magit-log-section-arguments)))) + upstream)) + (magit-insert-log "..@{upstream}" magit-buffer-log-args)))) (magit-define-section-jumper magit-jump-to-unpulled-from-pushremote "Unpulled from " unpulled @@ -1675,7 +1582,7 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point. (magit-insert-heading (format (propertize "Unpulled from %s:" 'face 'magit-section-heading) (propertize it 'face 'magit-branch-remote))) - (magit-insert-log (concat ".." it) magit-log-section-arguments))))) + (magit-insert-log (concat ".." it) magit-buffer-log-args))))) (defvar magit-unpushed-section-map (let ((map (make-sparse-keymap))) @@ -1693,7 +1600,7 @@ behind of the current branch, then show the commits that have not yet been pushed into the upstream branch. If no upstream is configured or if the upstream is not behind of the current branch, then show the last `magit-log-section-commit-count' commits." - (let ((upstream (magit-rev-parse "@{upstream}"))) + (let ((upstream (magit-get-upstream-branch))) (if (or (not upstream) (magit-rev-ancestor-p "HEAD" upstream)) (magit-insert-recent-commits 'unpushed "@{upstream}..") @@ -1706,7 +1613,7 @@ then show the last `magit-log-section-commit-count' commits." (magit-insert-heading (format (propertize "Unmerged into %s:" 'face 'magit-section-heading) (magit-get-upstream-branch))) - (magit-insert-log "@{upstream}.." magit-log-section-arguments)))) + (magit-insert-log "@{upstream}.." magit-buffer-log-args)))) (defun magit-insert-recent-commits (&optional type value) "Insert section showing recent commits. @@ -1721,7 +1628,7 @@ Show the last `magit-log-section-commit-count' commits." (magit-insert-log range (cons (format "-n%d" magit-log-section-commit-count) (--remove (string-prefix-p "-n" it) - magit-log-section-arguments)))))) + magit-buffer-log-args)))))) (magit-define-section-jumper magit-jump-to-unpushed-to-pushremote "Unpushed to " unpushed @@ -1740,7 +1647,7 @@ Show the last `magit-log-section-commit-count' commits." (magit-insert-heading (format (propertize "Unpushed to %s:" 'face 'magit-section-heading) (propertize it 'face 'magit-branch-remote))) - (magit-insert-log (concat it "..") magit-log-section-arguments))))) + (magit-insert-log (concat it "..") magit-buffer-log-args))))) ;;;; Auxiliary Log Sections diff --git a/elpa/magit-20190122.503/magit-margin.el b/elpa/magit-20190514.1814/magit-margin.el similarity index 93% rename from elpa/magit-20190122.503/magit-margin.el rename to elpa/magit-20190514.1814/magit-margin.el index ad8b3595..37c9e179 100644 --- a/elpa/magit-20190122.503/magit-margin.el +++ b/elpa/magit-20190514.1814/magit-margin.el @@ -36,6 +36,7 @@ (require 'subr-x)) (require 'magit-section) +(require 'magit-transient) (require 'magit-mode) (defgroup magit-margin nil @@ -61,18 +62,15 @@ does not carry to other options." ;;; Commands -(magit-define-popup magit-margin-popup - "Popup console for changing appearance of the margin." - :actions '("Margin" - (?L "Toggle visibility" magit-toggle-margin) - (?l "Cycle style" magit-cycle-margin-style) - (?d "Toggle details" magit-toggle-margin-details) - (lambda () - (and (with-current-buffer magit-pre-popup-buffer - (derived-mode-p 'magit-refs-mode)) - (propertize "Left edge" 'face 'magit-popup-heading))) - (?v "Change verbosity" magit-refs-set-show-commit-count)) - :max-action-columns 1) +(define-transient-command magit-margin-settings () + "Change what information is displayed in the margin." + :info-manual "(magit) Log Margin" + ["Margin" + ("L" "Toggle visibility" magit-toggle-margin) + ("l" "Cycle style" magit-cycle-margin-style) + ("d" "Toggle details" magit-toggle-margin-details) + ("v" "Change verbosity" magit-refs-set-show-commit-count + :if-derived magit-refs-mode)]) (defun magit-toggle-margin () "Show or hide the Magit margin." diff --git a/elpa/magit-20190122.503/magit-merge.el b/elpa/magit-20190514.1814/magit-merge.el similarity index 79% rename from elpa/magit-20190122.503/magit-merge.el rename to elpa/magit-20190514.1814/magit-merge.el index 4c1fe233..bedbb50f 100644 --- a/elpa/magit-20190122.503/magit-merge.el +++ b/elpa/magit-20190514.1814/magit-merge.el @@ -36,25 +36,45 @@ ;;; Commands -;;;###autoload (autoload 'magit-merge-popup "magit" nil t) -(magit-define-popup magit-merge-popup - "Popup console for merge commands." +;;;###autoload (autoload 'magit-merge "magit" nil t) +(define-transient-command magit-merge () + "Merge branches." :man-page "git-merge" - :switches '((?f "Fast-forward only" "--ff-only") - (?n "No fast-forward" "--no-ff")) - :options '((?s "Strategy" "--strategy=")) - :actions '((?m "Merge" magit-merge-plain) - (?p "Preview merge" magit-merge-preview) - (?e "Merge and edit message" magit-merge-editmsg) nil - (?n "Merge but don't commit" magit-merge-nocommit) - (?s "Squash merge" magit-merge-squash) - (?a "Absorb" magit-merge-absorb) - (?i "Merge into" magit-merge-into)) - :sequence-actions '((?m "Commit merge" magit-commit-create) - (?a "Abort merge" magit-merge-abort)) - :sequence-predicate 'magit-merge-in-progress-p - :default-action 'magit-merge - :max-action-columns 2) + :incompatible '(("--ff-only" "--no-ff")) + ["Arguments" + :if-not magit-merge-in-progress-p + ("-f" "Fast-forward only" "--ff-only") + ("-n" "No fast-forward" "--no-ff") + (magit-merge:--strategy) + (5 magit:--gpg-sign)] + ["Actions" + :if-not magit-merge-in-progress-p + [("m" "Merge" magit-merge-plain) + ("e" "Merge and edit message" magit-merge-editmsg) + ("n" "Merge but don't commit" magit-merge-nocommit) + ("a" "Absorb" magit-merge-absorb)] + [("p" "Preview merge" magit-merge-preview) + ?\n + ("s" "Squash merge" magit-merge-squash) + ("i" "Merge into" magit-merge-into)]] + ["Actions" + :if magit-merge-in-progress-p + ("m" "Commit merge" magit-commit-create) + ("a" "Abort merge" magit-merge-abort)]) + +(defun magit-merge-arguments () + (transient-args 'magit-merge)) + +(define-infix-argument magit-merge:--strategy () + :description "Strategy" + :class 'transient-option + ;; key for merge: "-s" + ;; key for cherry-pick and revert: "=s" + ;; shortarg for merge: "-s" + ;; shortarg for cherry-pick and revert: none + :key "-s" + :argument "--strategy=" + :choices '("resolve" "recursive" "octopus" "ours" "subtree")) ;;;###autoload (defun magit-merge-plain (rev &optional args nocommit) @@ -84,7 +104,8 @@ edit it. (magit-merge-assert) (cl-pushnew "--no-ff" args :test #'equal) (apply #'magit-run-git-with-editor "merge" "--edit" - (append args (list rev)))) + (append (delete "--ff-only" args) + (list rev)))) ;;;###autoload (defun magit-merge-nocommit (rev &optional args) @@ -112,13 +133,13 @@ branch, then also remove the respective remote branch." (list (magit-read-other-local-branch (format "Merge `%s' into" (magit-get-current-branch)) nil - (when-let ((upstream (magit-get-upstream-branch))) - (when-let ((upstream (cdr (magit-split-branch-name upstream)))) - (and (magit-branch-p upstream) upstream)))) + (when-let ((upstream (magit-get-upstream-branch)) + (upstream (cdr (magit-split-branch-name upstream)))) + (and (magit-branch-p upstream) upstream))) (magit-merge-arguments))) (let ((current (magit-get-current-branch))) (when (zerop (magit-call-git "checkout" branch)) - (magit--merge-absort current args)))) + (magit--merge-absorb current args)))) ;;;###autoload (defun magit-merge-absorb (branch &optional args) @@ -132,9 +153,9 @@ if `forge-branch-pullreq' was used to create the merged branch, then also remove the respective remote branch." (interactive (list (magit-read-other-local-branch "Absorb branch") (magit-merge-arguments))) - (magit--merge-absort branch args)) + (magit--merge-absorb branch args)) -(defun magit--merge-absort (branch args) +(defun magit--merge-absorb (branch args) (when (equal branch "master") (unless (yes-or-no-p "Do you really want to merge `master' into another branch? ") @@ -150,10 +171,10 @@ then also remove the respective remote branch." (magit-process-sentinel process event) (process-put process 'inhibit-refresh t) (magit-process-sentinel process event) - (magit--merge-absort-1 branch args)))))) - (magit--merge-absort-1 branch args))) + (magit--merge-absorb-1 branch args)))))) + (magit--merge-absorb-1 branch args))) -(defun magit--merge-absort-1 (branch args) +(defun magit--merge-absorb-1 (branch args) (magit-run-git-async "merge" args "--no-edit" branch) (set-process-sentinel magit-this-process @@ -179,22 +200,7 @@ then also remove the respective remote branch." (defun magit-merge-preview (rev) "Preview result of merging REV into the current branch." (interactive (list (magit-read-other-branch-or-commit "Preview merge"))) - (magit-mode-setup #'magit-merge-preview-mode rev)) - -(define-derived-mode magit-merge-preview-mode magit-diff-mode "Magit Merge" - "Mode for previewing a merge." - :group 'magit-diff - (hack-dir-local-variables-non-file-buffer)) - -(defun magit-merge-preview-refresh-buffer (rev) - (let* ((branch (magit-get-current-branch)) - (head (or branch (magit-rev-verify "HEAD")))) - (magit-set-header-line-format (format "Preview merge of %s into %s" - rev - (or branch "HEAD"))) - (magit-insert-section (diffbuf) - (magit-git-wash #'magit-diff-wash-diffs - "merge-tree" (magit-git-string "merge-base" head rev) head rev)))) + (magit-merge-preview-setup-buffer rev)) ;;;###autoload (defun magit-merge-abort () @@ -275,8 +281,8 @@ If no merge is in progress, do nothing." (format "Merging %s:" (mapconcat #'identity heads ", "))) (magit-insert-log range - (let ((args magit-log-section-arguments)) - (unless (member "--decorate=full" magit-log-section-arguments) + (let ((args magit-buffer-log-args)) + (unless (member "--decorate=full" magit-buffer-log-args) (push "--decorate=full" args)) args)))))) diff --git a/elpa/magit-20190122.503/magit-mode.el b/elpa/magit-20190514.1814/magit-mode.el similarity index 81% rename from elpa/magit-20190122.503/magit-mode.el rename to elpa/magit-20190514.1814/magit-mode.el index 2fc0ac8a..9a31efde 100644 --- a/elpa/magit-20190122.503/magit-mode.el +++ b/elpa/magit-20190514.1814/magit-mode.el @@ -35,14 +35,13 @@ (eval-when-compile (require 'subr-x)) +(require 'transient) + (require 'magit-section) (require 'magit-git) ;; For `magit-display-buffer-fullcolumn-most-v1' from `git-commit' (defvar git-commit-mode) -;; For `magit-xref-insert-buttons' from `magit' -(defvar magit-diff-show-xref-buttons) -(defvar magit-revision-show-xref-buttons) ;; For `magit-refresh' (defvar magit-post-commit-hook-commands) (defvar magit-post-stage-hook-commands) @@ -53,6 +52,8 @@ (declare-function magit-process-unset-mode-line-error-status "magit-process" ()) ;; For `magit-mode-setup-internal' (declare-function magit-status-goto-initial-section "magit-status" ()) +;; For `magit-mode' from `bookmark' +(defvar bookmark-make-record-function) (require 'format-spec) (require 'help-mode) @@ -60,19 +61,18 @@ ;;; Options (defcustom magit-mode-hook - '(magit-load-config-extensions - magit-xref-setup) + '(magit-load-config-extensions) "Hook run when entering a mode derived from Magit mode." + :package-version '(magit . "2.91.0") :group 'magit-modes :type 'hook :options '(magit-load-config-extensions - magit-xref-setup bug-reference-mode)) -(defcustom magit-mode-setup-hook +(defcustom magit-setup-buffer-hook '(magit-maybe-save-repository-buffers magit-set-buffer-margin) - "Hook run by `magit-mode-setup'. + "Hook run by `magit-setup-buffer'. This is run right after displaying the buffer and right before generating or updating its content. `magit-mode-hook' and other, @@ -209,42 +209,62 @@ support additional %-sequences." (function-item magit-restore-window-configuration) (function :tag "Function"))) -(defcustom magit-use-sticky-arguments t - "How to reuse arguments from existing diff and log buffers. - -nil Always use the default value of the variable - `magit-log-arguments' for log commands. Likewise, - always use the default value of the variable - `magit-diff-arguments' for diff command calls. - -current If the mode of the current buffer is derived from - `magit-log-mode' or `magit-diff-mode', reuse the - arguments from that buffer instead of those given by - the variable `magit-log-arguments' or - `magit-diff-arguments', respectively. - -t Like `current', but if the mode of the current buffer - is not derived from `magit-log-mode' or - `magit-diff-mode', use the arguments from the current - repository's active (i.e. non-locked) `magit-log-mode' - or `magit-diff-mode' buffer, respectively, if it - exists. - - Note that commands that generate a - `magit-revision-mode' or `magit-stash-mode' buffer will - also collect their diff arguments from the active - `magit-diff-mode' buffer. - -In general, there is a separation between the \"sticky\" -arguments for log and diff buffers, but there is one special -case: if the current buffer is a log buffer, -`magit-show-commit' (considered a diff command) uses the file -filter from the log buffer." - :package-version '(magit . "2.11.0") +(defcustom magit-prefix-use-buffer-arguments 'selected + "Whether certain prefix commands reuse arguments active in relevant buffer. + +This affects the transient prefix commands `magit-diff', +`magit-log' and `magit-show-refs'. + +Valid values are: + +`always': Always use the set of arguments that is currently + active in the respective buffer, provided that buffer exists + of course. +`selected' or t: Use the set of arguments from the respective + buffer, but only if it is displayed in a window of the current + frame. This is the default. +`current': Use the set of arguments from the respective buffer, + but only if it is the current buffer. +`never': Never use the set of arguments from the respective + buffer. + +For more information see info node `(magit)Transient Arguments +and Buffer Arguments'." + :package-version '(magit . "2.91.0") :group 'magit-buffers - :type '(choice (const :tag "disabled" nil) - (const :tag "sticky for current" current) - (const :tag "sticky" t))) + :group 'magit-commands + :type '(choice (const :tag "always use args from buffer" always) + (const :tag "use args from buffer if it is current" current) + (const :tag "never use args from buffer" never))) + +(defcustom magit-direct-use-buffer-arguments 'selected + "Whether certain commands reuse arguments active in relevant buffer. + +This affects certain commands such as `magit-show-commit' that +are suffixes of the diff or log transient prefix commands, but +only if they are invoked directly, i.e. *not* as a suffix. + +Valid values are: + +`always': Always use the set of arguments that is currently + active in the respective buffer, provided that buffer exists + of course. +`selected' or t: Use the set of arguments from the respective + buffer, but only if it is displayed in a window of the current + frame. This is the default. +`current': Use the set of arguments from the respective buffer, + but only if it is the current buffer. +`never': Never use the set of arguments from the respective + buffer. + +For more information see info node `(magit)Transient Arguments +and Buffer Arguments'." + :package-version '(magit . "2.91.0") + :group 'magit-buffers + :group 'magit-commands + :type '(choice (const :tag "always use args from buffer" always) + (const :tag "use args from buffer if it is current" current) + (const :tag "never use args from buffer" never))) (defcustom magit-region-highlight-hook '(magit-section-update-region magit-diff-update-hunk-region) @@ -354,7 +374,7 @@ starts complicating other things, then it will be removed." :group 'magit-miscellaneous :type 'boolean) -;;; Magit Mode +;;; Key Bindings (defvar magit-mode-map (let ((map (make-keymap))) @@ -371,10 +391,10 @@ starts complicating other things, then it will be removed." (define-key map (kbd "k") 'magit-section-forward) (define-key map (kbd "M-i") 'magit-section-backward-sibling) (define-key map (kbd "M-k") 'magit-section-forward-sibling) - (define-key map (kbd "p") 'magit-push-popup) + (define-key map (kbd "p") 'magit-push) (define-key map (kbd ",") 'magit-delete-thing) (define-key map (kbd ";") 'magit-file-untrack) - (define-key map (kbd "C-c C-i") 'magit-gitignore-popup)) + (define-key map (kbd "C-c C-i") 'magit-gitignore)) (t (define-key map [C-return] 'magit-visit-thing) (define-key map (kbd "C-m") 'magit-visit-thing) @@ -389,11 +409,11 @@ starts complicating other things, then it will be removed." (define-key map (kbd "n") 'magit-section-forward) (define-key map (kbd "M-p") 'magit-section-backward-sibling) (define-key map (kbd "M-n") 'magit-section-forward-sibling) - (define-key map (kbd "P") 'magit-push-popup) + (define-key map (kbd "P") 'magit-push) (define-key map (kbd "k") 'magit-delete-thing) (define-key map (kbd "K") 'magit-file-untrack) - (define-key map (kbd "i") 'magit-gitignore-popup) - (define-key map (kbd "I") 'magit-gitignore-popup))) + (define-key map (kbd "i") 'magit-gitignore) + (define-key map (kbd "I") 'magit-gitignore))) (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up) (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down) (define-key map "+" 'magit-diff-more-context) @@ -408,50 +428,51 @@ starts complicating other things, then it will be removed." (define-key map (kbd "M-3") 'magit-section-show-level-3-all) (define-key map (kbd "M-4") 'magit-section-show-level-4-all) (define-key map "$" 'magit-process-buffer) - (define-key map "%" 'magit-worktree-popup) + (define-key map "%" 'magit-worktree) (define-key map "a" 'magit-cherry-apply) - (define-key map "A" 'magit-cherry-pick-popup) - (define-key map "b" 'magit-branch-popup) - (define-key map "B" 'magit-bisect-popup) - (define-key map "c" 'magit-commit-popup) - (define-key map "d" 'magit-diff-popup) - (define-key map "D" 'magit-diff-refresh-popup) + (define-key map "A" 'magit-cherry-pick) + (define-key map "b" 'magit-branch) + (define-key map "B" 'magit-bisect) + (define-key map "c" 'magit-commit) + (define-key map "C" 'magit-clone) + (define-key map "d" 'magit-diff) + (define-key map "D" 'magit-diff-refresh) (define-key map "e" 'magit-ediff-dwim) - (define-key map "E" 'magit-ediff-popup) - (define-key map "f" 'magit-fetch-popup) - (define-key map "F" 'magit-pull-popup) + (define-key map "E" 'magit-ediff) + (define-key map "f" 'magit-fetch) + (define-key map "F" 'magit-pull) (define-key map "g" 'magit-refresh) (define-key map "G" 'magit-refresh-all) - (define-key map "h" 'magit-dispatch-popup) - (define-key map "?" 'magit-dispatch-popup) - (define-key map "l" 'magit-log-popup) - (define-key map "L" 'magit-log-refresh-popup) - (define-key map "m" 'magit-merge-popup) - (define-key map "M" 'magit-remote-popup) - (define-key map "o" 'magit-submodule-popup) - (define-key map "O" 'magit-subtree-popup) + (define-key map "h" 'magit-dispatch) + (define-key map "?" 'magit-dispatch) + (define-key map "l" 'magit-log) + (define-key map "L" 'magit-log-refresh) + (define-key map "m" 'magit-merge) + (define-key map "M" 'magit-remote) + (define-key map "o" 'magit-submodule) + (define-key map "O" 'magit-subtree) (define-key map "q" 'magit-mode-bury-buffer) - (define-key map "r" 'magit-rebase-popup) + (define-key map "r" 'magit-rebase) (define-key map "R" 'magit-file-rename) - (define-key map "t" 'magit-tag-popup) - (define-key map "T" 'magit-notes-popup) + (define-key map "t" 'magit-tag) + (define-key map "T" 'magit-notes) (define-key map "s" 'magit-stage-file) (define-key map "S" 'magit-stage-modified) (define-key map "u" 'magit-unstage-file) (define-key map "U" 'magit-unstage-all) (define-key map "v" 'magit-revert-no-commit) - (define-key map "V" 'magit-revert-popup) - (define-key map "w" 'magit-am-popup) - (define-key map "W" 'magit-patch-popup) + (define-key map "V" 'magit-revert) + (define-key map "w" 'magit-am) + (define-key map "W" 'magit-patch) (define-key map "x" 'magit-reset-quickly) - (define-key map "X" 'magit-reset-popup) - (define-key map "y" 'magit-show-refs-popup) + (define-key map "X" 'magit-reset) + (define-key map "y" 'magit-show-refs) (define-key map "Y" 'magit-cherry) - (define-key map "z" 'magit-stash-popup) - (define-key map "Z" 'magit-stash-popup) + (define-key map "z" 'magit-stash) + (define-key map "Z" 'magit-stash) (define-key map ":" 'magit-git-command) - (define-key map "!" 'magit-run-popup) - (define-key map (kbd "C-c C-c") 'magit-dispatch-popup) + (define-key map "!" 'magit-run) + (define-key map (kbd "C-c C-c") 'magit-dispatch) (define-key map (kbd "C-c C-e") 'magit-edit-thing) (define-key map (kbd "C-c C-o") 'magit-browse-thing) (define-key map (kbd "C-c C-w") 'magit-browse-thing) @@ -478,9 +499,8 @@ which deletes the thing at point." Where applicable, section-specific keymaps bind another command which visits the thing at point." (interactive) - (if (eq magit-current-popup 'magit-dispatch-popup) - (progn (setq magit-current-popup nil) - (call-interactively (key-binding (this-command-keys)))) + (if (eq current-transient-command 'magit-dispatch) + (call-interactively (key-binding (this-command-keys))) (user-error "There is no thing at point that could be visited"))) (defun magit-edit-thing () @@ -488,9 +508,8 @@ which visits the thing at point." Where applicable, section-specific keymaps bind another command which lets you edit the thing at point, likely in another buffer." (interactive) - (if (eq magit-current-popup 'magit-dispatch-popup) - (progn (setq magit-current-popup nil) - (call-interactively (key-binding (this-command-keys)))) + (if (eq current-transient-command 'magit-dispatch) + (call-interactively (key-binding (this-command-keys))) (user-error "There is no thing at point that could be edited"))) (defun magit-browse-thing () @@ -510,7 +529,7 @@ which visits the thing at point using `browse-url'." ["Stage modified" magit-stage-modified t] ["Unstage" magit-unstage t] ["Reset index" magit-reset-index t] - ["Commit" magit-commit-popup t] + ["Commit" magit-commit t] ["Add log entry" magit-commit-add-log t] ["Tag" magit-tag-create t] "---" @@ -519,10 +538,10 @@ which visits the thing at point using `browse-url'." ("Log" ["Log" magit-log-other t] ["Reflog" magit-reflog-other t] - ["Extended..." magit-log-popup t]) + ["Extended..." magit-log t]) "---" ["Cherry pick" magit-cherry-pick t] - ["Revert commit" magit-revert-popup t] + ["Revert commit" magit-revert t] "---" ["Ignore globally" magit-gitignore-globally t] ["Ignore locally" magit-gitignore-locally t] @@ -534,7 +553,7 @@ which visits the thing at point using `browse-url'." ["Branch..." magit-checkout t] ["Merge" magit-merge t] ["Ediff resolve" magit-ediff-resolve t] - ["Rebase..." magit-rebase-popup t] + ["Rebase..." magit-rebase t] "---" ["Push" magit-push t] ["Pull" magit-pull-branch t] @@ -550,6 +569,8 @@ which visits the thing at point using `browse-url'." ["Display Git output" magit-process-buffer t] ["Quit Magit" magit-mode-bury-buffer t])) +;;; Mode + (defun magit-load-config-extensions () "Load Magit extensions that are defined at the Git config layer." (dolist (ext (magit-get-all "magit.extension")) @@ -584,7 +605,10 @@ Magit is documented in info node `(magit)'." (when (and (fboundp 'display-line-numbers-mode) (bound-and-true-p global-display-line-numbers-mode)) (display-line-numbers-mode -1)) - (add-hook 'kill-buffer-hook 'magit-preserve-section-visibility-cache)) + (add-hook 'kill-buffer-hook 'magit-preserve-section-visibility-cache) + (setq-local bookmark-make-record-function 'magit--make-bookmark)) + +;;; Highlighting (defvar-local magit-region-overlays nil) @@ -610,23 +634,108 @@ Magit is documented in info node `(magit)'." (magit-delete-region-overlays) (funcall (default-value 'redisplay-unhighlight-region-function) rol)) +;;; Local Variables + +(defvar-local magit-buffer-arguments nil) +(defvar-local magit-buffer-diff-args nil) +(defvar-local magit-buffer-diff-files nil) +(defvar-local magit-buffer-diff-files-suspended nil) +(defvar-local magit-buffer-file-name nil) +(defvar-local magit-buffer-files nil) +(defvar-local magit-buffer-log-args nil) +(defvar-local magit-buffer-log-files nil) +(defvar-local magit-buffer-range nil) +(defvar-local magit-buffer-range-hashed nil) +(defvar-local magit-buffer-refname nil) +(defvar-local magit-buffer-revision nil) +(defvar-local magit-buffer-revision-hash nil) +(defvar-local magit-buffer-revisions nil) +(defvar-local magit-buffer-typearg nil) +(defvar-local magit-buffer-upstream nil) + +;; These variables are also used in file-visiting buffers. +;; Because the user may change the major-mode, they have +;; to be permanent buffer-local. +(put 'magit-buffer-file-name 'permanent-local t) +(put 'magit-buffer-refname 'permanent-local t) +(put 'magit-buffer-revision 'permanent-local t) +(put 'magit-buffer-revision-hash 'permanent-local t) + (defvar-local magit-refresh-args nil - "The arguments used to refresh the current buffer.") + "Obsolete. Possibly the arguments used to refresh the current buffer. +Some third-party packages might still use this, but Magit does not.") (put 'magit-refresh-args 'permanent-local t) +(make-obsolete-variable 'magit-refresh-args nil "Magit 2.91.0") + +(defvar magit-buffer-lock-functions nil + "Obsolete buffer-locking support for third-party modes. +Implement the generic function `magit-buffer-value' for +your mode instead of adding an entry to this variable.") +(make-obsolete-variable 'magit-buffer-lock-functions nil "Magit 2.91.0") + +(cl-defgeneric magit-buffer-value () + (when-let ((fn (cdr (assq major-mode magit-buffer-lock-functions)))) + (funcall fn (with-no-warnings magit-refresh-args)))) (defvar-local magit-previous-section nil) (put 'magit-previous-section 'permanent-local t) +;;; Setup Buffer + +(defmacro magit-setup-buffer (mode &optional locked &rest bindings) + (declare (indent 2)) + `(magit-setup-buffer-internal + ,mode ,locked + ,(cons 'list (mapcar (pcase-lambda (`(,var ,form)) + `(list ',var ,form)) + bindings)))) + +(defun magit-setup-buffer-internal (mode locked bindings) + (let* ((value (and locked + (with-temp-buffer + (pcase-dolist (`(,var ,val) bindings) + (set (make-local-variable var) val)) + (let ((major-mode mode)) + (magit-buffer-value))))) + (buffer (magit-get-mode-buffer mode value)) + (section (and buffer (magit-current-section))) + (created (not buffer))) + (unless buffer + (setq buffer (magit-with-toplevel + (magit-generate-new-buffer mode value)))) + (with-current-buffer buffer + (setq magit-previous-section section) + (funcall mode) + (magit-xref-setup 'magit-setup-buffer-internal bindings) + (pcase-dolist (`(,var ,val) bindings) + (set (make-local-variable var) val)) + (when created + (magit-status-goto-initial-section) + (run-hooks 'magit-create-buffer-hook))) + (magit-display-buffer buffer) + (with-current-buffer buffer + (run-hooks 'magit-setup-buffer-hook) + (magit-refresh-buffer)) + buffer)) + (defun magit-mode-setup (mode &rest args) "Setup up a MODE buffer using ARGS to generate its content." - (magit-mode-setup-internal mode args)) + (declare (obsolete magit-setup-buffer "Magit 2.91.0")) + (with-no-warnings + (magit-mode-setup-internal mode args))) (defun magit-mode-setup-internal (mode args &optional locked) "Setup up a MODE buffer using ARGS to generate its content. When optional LOCKED is non-nil, then create a buffer that is locked to its value, which is derived from MODE and ARGS." - (let* ((value (and locked (magit-buffer-lock-value mode args))) - (buffer (magit-mode-get-buffer mode nil nil value)) + (declare (obsolete magit-setup-buffer "Magit 2.91.0")) + (let* ((value (and locked + (with-temp-buffer + (with-no-warnings + (setq magit-refresh-args args)) + (let ((major-mode mode)) + (magit-buffer-value))))) + (buffer (magit-get-mode-buffer mode value)) (section (and buffer (magit-current-section))) (created (not buffer))) (unless buffer @@ -634,8 +743,10 @@ locked to its value, which is derived from MODE and ARGS." (magit-generate-new-buffer mode value)))) (with-current-buffer buffer (setq magit-previous-section section) - (setq magit-refresh-args args) + (with-no-warnings + (setq magit-refresh-args args)) (funcall mode) + (magit-xref-setup 'magit-mode-setup-internal args) (when created (magit-status-goto-initial-section) (run-hooks 'magit-create-buffer-hook))) @@ -644,6 +755,8 @@ locked to its value, which is derived from MODE and ARGS." (run-hooks 'magit-mode-setup-hook) (magit-refresh-buffer)))) +;;; Display Buffer + (defvar magit-display-buffer-noselect nil "If non-nil, then `magit-display-buffer' doesn't call `select-window'.") @@ -775,7 +888,9 @@ the mode of the current buffer derives from `magit-log-mode' or (display-buffer buffer (cond ((and (or git-commit-mode - (derived-mode-p 'magit-log-mode 'magit-cherry-mode)) + (derived-mode-p 'magit-log-mode + 'magit-cherry-mode + 'magit-reflog-mode)) (with-current-buffer buffer (derived-mode-p 'magit-diff-mode))) nil) @@ -797,11 +912,13 @@ Magit buffer is buried." (not (window-prev-buffers window))) (set-window-parameter window 'magit-dedicated t)))) +;;; Get Buffer + (defvar-local magit--default-directory nil "Value of `default-directory' when buffer is generated. This exists to prevent a let-bound `default-directory' from -tricking `magit-mode-get-buffer' or `magit-mode-get-buffers' into -thinking a buffer belongs to a repo that it doesn't.") +tricking `magit-get-mode-buffer' or `magit-mode-get-buffers' +into thinking a buffer belongs to a repo that it doesn't.") (put 'magit--default-directory 'permanent-local t) (defun magit-mode-get-buffers () @@ -814,7 +931,47 @@ thinking a buffer belongs to a repo that it doesn't.") (defvar-local magit-buffer-locked-p nil) (put 'magit-buffer-locked-p 'permanent-local t) +(defun magit-get-mode-buffer (mode &optional value frame) + "Return buffer belonging to the current repository whose major-mode is MODE. + +If no such buffer exists then return nil. Multiple buffers with +the same major-mode may exist for a repository but only one can +exist that hasn't been looked to its value. Return that buffer +\(or nil if there is no such buffer) unless VALUE is non-nil, in +which case return the buffer that has been looked to that value. + +If FRAME nil or omitted, then consider all buffers. Otherwise + only consider buffers that are displayed in some live window + on some frame. +If `all', then consider all buffers on all frames. +If `visible', then only consider buffers on all visible frames. +If `selected' or t, then only consider buffers on the selected + frame. +If a frame, then only consider buffers on that frame." + (if-let ((topdir (magit-toplevel))) + (cl-flet* ((b (buffer) + (with-current-buffer buffer + (and (eq major-mode mode) + (equal magit--default-directory topdir) + (if value + (and magit-buffer-locked-p + (equal (magit-buffer-value) value)) + (not magit-buffer-locked-p)) + buffer))) + (w (window) + (b (window-buffer window))) + (f (frame) + (-some #'w (window-list frame 'no-minibuf)))) + (pcase-exhaustive frame + (`nil (-some #'b (buffer-list))) + (`all (-some #'f (frame-list))) + (`visible (-some #'f (visible-frame-list))) + ((or `selected `t) (-some #'w (window-list (selected-frame)))) + ((guard (framep frame)) (-some #'w (window-list frame))))) + (magit--not-inside-repository-error))) + (defun magit-mode-get-buffer (mode &optional create frame value) + (declare (obsolete magit-get-mode-buffer "Magit 2.91.0")) (when create (error "`magit-mode-get-buffer's CREATE argument is obsolete")) (if-let ((topdir (magit-toplevel))) @@ -823,7 +980,7 @@ thinking a buffer belongs to a repo that it doesn't.") (equal magit--default-directory topdir) (if value (and magit-buffer-locked-p - (equal (magit-buffer-lock-value) value)) + (equal (magit-buffer-value) value)) (not magit-buffer-locked-p)))) (if frame (mapcar #'window-buffer @@ -872,6 +1029,8 @@ account." (?x . ,(if magit-uniquify-buffer-names "" "*")) (?T . ,(if magit-uniquify-buffer-names n (concat n "*"))))))) +;;; Buffer Lock + (defun magit-toggle-buffer-lock () "Lock the current buffer to its value or unlock it. @@ -890,15 +1049,15 @@ repository, then the former buffer is instead deleted and the latter is displayed in its place." (interactive) (if magit-buffer-locked-p - (if-let ((unlocked (magit-mode-get-buffer major-mode))) + (if-let ((unlocked (magit-get-mode-buffer major-mode))) (let ((locked (current-buffer))) (switch-to-buffer unlocked nil t) (kill-buffer locked)) (setq magit-buffer-locked-p nil) (rename-buffer (funcall magit-generate-buffer-name-function major-mode))) - (if-let ((value (magit-buffer-lock-value))) - (if-let ((locked (magit-mode-get-buffer major-mode nil nil value))) + (if-let ((value (magit-buffer-value))) + (if-let ((locked (magit-get-mode-buffer major-mode value))) (let ((unlocked (current-buffer))) (switch-to-buffer locked nil t) (kill-buffer unlocked)) @@ -907,72 +1066,21 @@ latter is displayed in its place." major-mode value))) (user-error "Buffer has no value it could be locked to")))) -(defvar magit-buffer-lock-functions '((forge-topic-mode . car)) - "Provide buffer-locking support for third-party modes. -An alist of symbols to functions. - -The symbol must be the major-mode the locked buffer will have. - -The function must take a single argument, a list of refresh -arguments (the value of `magit-refresh-args') and return a -value that identifies the buffer (i.e., its 'lock value'). -If the third-party mode is invoked as - - (magit-mode-setup-internal #\\='my-mode \\='(1 2 3) t) - -the function will be invoked as - - (funcall lock-func \\='(1 2 3)) - -if the cons (my-mode . lock-func) is in this list. - -This variable is intended for third-party extensions; -`magit-buffer-lock-value' implements all built-in behavior. - -See also `magit-toggle-buffer-lock'.") - -(cl-defun magit-buffer-lock-value - (&optional (mode major-mode) - (args magit-refresh-args)) - "Find an appropriate buffer lock value for MODE under ARGS. -See also `magit-buffer-lock-functions'." - (cl-case mode - (magit-cherry-mode - (pcase-let ((`(,upstream ,head) args)) - (concat head ".." upstream))) - (magit-diff-mode - (pcase-let ((`(,rev-or-range ,const ,_args ,files) args)) - (nconc (cons (or rev-or-range - (if (member "--cached" const) - (progn (setq const (delete "--cached" const)) - 'staged) - 'unstaged)) - const) - (and files (cons "--" files))))) - (magit-log-mode - (pcase-let ((`(,revs ,_args ,files) args)) - (if (and revs files) - (append revs (cons "--" files)) - (append revs files)))) - (magit-refs-mode - (pcase-let ((`(,ref ,args) args)) - (cons (or ref "HEAD") args))) - (magit-revision-mode - (pcase-let ((`(,rev ,_const ,_args ,files) args)) - (if files (cons rev files) (list rev)))) - ((magit-reflog-mode ; (ref ~args) - magit-stash-mode ; (stash _const _args _files) - magit-stashes-mode) ; (ref) - (car args)) - (t - (--when-let (cdr (assq mode magit-buffer-lock-functions)) - (funcall it args))))) +;;; Bury Buffer (defun magit-mode-bury-buffer (&optional kill-buffer) "Bury the current buffer. With a prefix argument, kill the buffer instead. +With two prefix arguments, also kill all Magit buffers associated +with this repository. This is done using `magit-bury-buffer-function'." (interactive "P") + ;; Kill all associated Magit buffers when a double prefix arg is given. + (when (>= (prefix-numeric-value kill-buffer) 16) + (let ((current (current-buffer))) + (dolist (buf (magit-mode-get-buffers)) + (unless (eq buf current) + (kill-buffer buf))))) (funcall magit-bury-buffer-function kill-buffer)) (defun magit-mode-quit-window (kill-buffer) @@ -998,7 +1106,7 @@ window." (when (window-live-p window) (delete-window window))))) -;;; Refresh Magit Buffers +;;; Refresh Buffers (defvar inhibit-magit-refresh nil) @@ -1022,7 +1130,7 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." (magit-refresh-buffer)) (--when-let (and magit-refresh-status-buffer (not (derived-mode-p 'magit-status-mode)) - (magit-mode-get-buffer 'magit-status-mode)) + (magit-get-mode-buffer 'magit-status-mode)) (with-current-buffer it (magit-refresh-buffer))) (magit-auto-revert-buffers) @@ -1088,7 +1196,7 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." (let ((inhibit-read-only t)) (erase-buffer) (save-excursion - (apply refresh magit-refresh-args))) + (apply refresh (with-no-warnings magit-refresh-args)))) (dolist (window windows) (with-selected-window (car window) (with-current-buffer buffer @@ -1154,7 +1262,7 @@ If you are not satisfied with Magit's performance, then you should obviously not add this function to that hook." (when (and (not disable-magit-save-buffers) (magit-inside-worktree-p t)) - (--when-let (ignore-errors (magit-mode-get-buffer 'magit-status-mode)) + (--when-let (ignore-errors (magit-get-mode-buffer 'magit-status-mode)) (add-to-list 'magit-after-save-refresh-buffers it) (add-hook 'post-command-hook 'magit-after-save-refresh-buffers)))) @@ -1259,7 +1367,7 @@ Later, when the buffer is buried, it may be restored by (help-xref-go-forward (current-buffer)) (user-error "No next entry in buffer's history"))) -(defun magit-insert-xref-buttons (&optional _) +(defun magit-insert-xref-buttons () "Insert xref buttons." (when (or help-xref-stack help-xref-forward-stack) (when help-xref-stack @@ -1284,14 +1392,15 @@ Later, when the buffer is buried, it may be restored by 'mouse-face 'magit-section-highlight 'help-echo (purecopy "mouse-2, RET: go back to next history entry")) -(defun magit-xref-setup () - "Insert backward/forward buttons if the major-mode supports it. -Currently `magit-log-mode', `magit-reflog-mode', -`magit-diff-mode', and `magit-revision-mode' support it" - (when (memq major-mode '(magit-log-mode - magit-reflog-mode - magit-diff-mode - magit-revision-mode)) +(defvar magit-xref-modes + '(magit-log-mode + magit-reflog-mode + magit-diff-mode + magit-revision-mode) + "List of modes for which to insert navigation buttons.") + +(defun magit-xref-setup (fn args) + (when (memq major-mode magit-xref-modes) (when help-xref-stack-item (push (cons (point) help-xref-stack-item) help-xref-stack) (setq help-xref-forward-stack nil)) @@ -1299,12 +1408,11 @@ Currently `magit-log-mode', `magit-reflog-mode', (--when-let (nthcdr 10 help-xref-stack) (setcdr it nil))) (setq help-xref-stack-item - `(magit-xref-restore ,default-directory ,@magit-refresh-args)))) + (list 'magit-xref-restore fn default-directory args)))) -(defun magit-xref-restore (&rest args) - (magit-xref-setup) - (setq default-directory (car args)) - (setq magit-refresh-args (cdr args)) +(defun magit-xref-restore (fn dir args) + (setq default-directory dir) + (funcall fn major-mode nil args) (magit-refresh-buffer)) ;;; Repository-Local Cache @@ -1390,7 +1498,8 @@ repository's Magit buffers." :key #'car :test #'equal))) (dolist (buffer (magit-mode-get-buffers)) (with-current-buffer buffer - (setq magit-section-visibility-cache nil)))) + (setq magit-section-visibility-cache nil))) + (setq magit--libgit-available-p eieio-unbound)) ;;; Utilities diff --git a/elpa/magit-20190122.503/magit-notes.el b/elpa/magit-20190514.1814/magit-notes.el similarity index 57% rename from elpa/magit-20190122.503/magit-notes.el rename to elpa/magit-20190514.1814/magit-notes.el index 9987bdd4..1bd1fd34 100644 --- a/elpa/magit-20190122.503/magit-notes.el +++ b/elpa/magit-20190514.1814/magit-notes.el @@ -29,59 +29,82 @@ (require 'magit) -;;; Popup +;;; Commands -;;;###autoload (autoload 'magit-notes-popup "magit" nil t) -(magit-define-popup magit-notes-popup - "Popup console for notes commands." +;;;###autoload (autoload 'magit-notes "magit" nil t) +(define-transient-command magit-notes () + "Edit notes attached to commits." :man-page "git-notes" - :variables '("Configure local settings" - (?c "core.notesRef" - magit-set-core.notesRef - magit-format-core.notesRef) - (?d "notes.displayRef" - magit-set-notes.displayRef - magit-format-notes.displayRef) - "Configure global settings" - (?C "core.notesRef" - magit-set-global-core.notesRef - magit-format-global-core.notesRef) - (?D "notes.displayRef" - magit-set-global-notes.displayRef - magit-format-global-notes.displayRef)) - :switches '("Switch for prune" - (?n "Dry run" "--dry-run")) - :options '("Option for edit and remove" - (?r "Manipulate ref" "--ref=" magit-notes-popup-read-ref) - "Option for merge" - (?s "Merge strategy" "--strategy=")) - :actions '((?T "Edit" magit-notes-edit) - (?r "Remove" magit-notes-remove) - (?m "Merge" magit-notes-merge) - (?p "Prune" magit-notes-prune)) - :sequence-actions '((?c "Commit merge" magit-notes-merge-commit) - (?a "Abort merge" magit-notes-merge-abort)) - :sequence-predicate 'magit-notes-merging-p - :default-action 'magit-notes-edit) + ["Configure local settings" + ("c" magit-core.notesRef) + ("d" magit-notes.displayRef)] + ["Configure global settings" + ("C" magit-global-core.notesRef) + ("D" magit-global-notes.displayRef)] + ["Arguments for prune" + :if-not magit-notes-merging-p + ("-n" "Dry run" ("-n" "--dry-run"))] + ["Arguments for edit and remove" + :if-not magit-notes-merging-p + (magit-notes:--ref)] + ["Arguments for merge" + :if-not magit-notes-merging-p + (magit-notes:--strategy)] + ["Actions" + :if-not magit-notes-merging-p + ("T" "Edit" magit-notes-edit) + ("r" "Remove" magit-notes-remove) + ("m" "Merge" magit-notes-merge) + ("p" "Prune" magit-notes-prune)] + ["Actions" + :if magit-notes-merging-p + ("c" "Commit merge" magit-notes-merge-commit) + ("a" "Abort merge" magit-notes-merge-abort)]) (defun magit-notes-merging-p () (let ((dir (magit-git-dir "NOTES_MERGE_WORKTREE"))) (and (file-directory-p dir) (directory-files dir nil "^[^.]")))) -(defun magit-format-core.notesRef () - (magit--format-popup-variable:value "core.notesRef" 22)) - -(defun magit-format-notes.displayRef () - (magit--format-popup-variable:values "notes.displayRef" 22)) - -(defun magit-format-global-core.notesRef () - (magit--format-popup-variable:value "core.notesRef" 22 t)) - -(defun magit-format-global-notes.displayRef () - (magit--format-popup-variable:values "notes.displayRef" 22 t)) - -;;; Commands +(define-infix-command magit-core.notesRef () + :class 'magit--git-variable + :variable "core.notesRef" + :reader 'magit-notes-read-ref + :prompt "Set local core.notesRef") + +(define-infix-command magit-notes.displayRef () + :class 'magit--git-variable + :variable "notes.displayRef" + :multi-value t + :reader 'magit-notes-read-refs + :prompt "Set local notes.displayRef") + +(define-infix-command magit-global-core.notesRef () + :class 'magit--git-variable + :variable "core.notesRef" + :reader 'magit-notes-read-ref + :prompt "Set global core.notesRef") + +(define-infix-command magit-global-notes.displayRef () + :class 'magit--git-variable + :variable "notes.displayRef" + :multi-value t + :reader 'magit-notes-read-refs + :prompt "Set global notes.displayRef") + +(define-infix-argument magit-notes:--ref () + :description "Merge strategy" + :class 'transient-option + :key "-r" + :argument "--ref=" + :reader 'magit-notes-read-ref) + +(define-infix-argument magit-notes:--strategy () + :description "Merge strategy" + :class 'transient-option + :shortarg "-s" + :argument "--strategy=" + :choices '("manual" "ours" "theirs" "union" "cat_sort_uniq")) (defun magit-notes-edit (commit &optional ref) "Edit the note attached to COMMIT. @@ -132,46 +155,21 @@ Also see `magit-notes-merge'." (defun magit-notes-prune (&optional dry-run) "Remove notes about unreachable commits." - (interactive (list (and (member "--dry-run" (magit-notes-arguments)) t))) + (interactive (list (and (member "--dry-run" (transient-args 'magit-notes)) t))) (when dry-run (magit-process-buffer)) (magit-run-git-with-editor "notes" "prune" (and dry-run "--dry-run"))) -(defun magit-set-core.notesRef (ref) - "Set the local value of `core.notesRef' to REF." - (interactive (list (magit-notes-read-ref "Set local core.notesRef"))) - (magit-set ref "core.notesRef") - (magit-with-pre-popup-buffer - (magit-refresh))) - -(defun magit-set-global-core.notesRef (ref) - "Set the global value of `core.notesRef' to REF." - (interactive (list (magit-notes-read-ref "Set global core.notesRef"))) - (magit-set ref "--global" "core.notesRef") - (magit-with-pre-popup-buffer - (magit-refresh))) - -(defun magit-set-notes.displayRef (refs) - "Set the local values of `notes.displayRef' to REFS." - (interactive (list (magit-notes-read-refs "Set local notes.displayRef"))) - (magit-set-all refs "notes.displayRef") - (magit-with-pre-popup-buffer - (magit-refresh))) - -(defun magit-set-global-notes.displayRef (refs) - "Set the global values of `notes.displayRef' to REFS." - (interactive (list (magit-notes-read-refs "Set global notes.displayRef"))) - (magit-set-all refs "--global" "notes.displayRef") - (magit-with-pre-popup-buffer - (magit-refresh))) - -(defun magit-notes-read-ref (prompt) +;;; Readers + +(defun magit-notes-read-ref (prompt _initial-input history) (--when-let (magit-completing-read prompt (magit-list-notes-refnames) nil nil (--when-let (magit-get "core.notesRef") (if (string-prefix-p "refs/notes/" it) (substring it 11) - it))) + it)) + history) (if (string-prefix-p "refs/" it) it (concat "refs/notes/" it)))) @@ -194,7 +192,7 @@ Also see `magit-notes-merge'." (defun magit-notes-read-args (prompt) (list (magit-read-branch-or-commit prompt (magit-stash-at-point)) (--when-let (--first (string-match "^--ref=\\(.+\\)" it) - (magit-notes-arguments)) + (transient-args 'magit-notes)) (match-string 1 it)))) ;;; _ diff --git a/elpa/magit-20190514.1814/magit-obsolete.el b/elpa/magit-20190514.1814/magit-obsolete.el new file mode 100644 index 00000000..8f45e594 --- /dev/null +++ b/elpa/magit-20190514.1814/magit-obsolete.el @@ -0,0 +1,103 @@ +;;; magit-obsolete.el --- obsolete definitions -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; 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. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library defines aliases for obsolete variables and functions. + +;;; Code: + +(require 'magit) + +;;; Obsolete since v2.91.0 + +(define-obsolete-function-alias 'magit-diff-visit-file-worktree + 'magit-diff-visit-worktree-file "Magit 2.91.0") + +(define-obsolete-function-alias 'magit-status-internal + 'magit-status-setup-buffer "Magit 2.91.0") + +(define-obsolete-variable-alias 'magit-mode-setup-hook + 'magit-setup-buffer-hook "Magit 2.91.0") + +(define-obsolete-variable-alias 'magit-branch-popup-show-variables + 'magit-branch-direct-configure "Magit 2.91.0") + +(define-obsolete-function-alias 'magit-dispatch-popup + 'magit-dispatch "Magit 2.91.0") + +(defun magit--magit-popup-warning () + (display-warning 'magit "\ +Magit no longer uses Magit-Popup. +It now uses Transient. +See https://emacsair.me/2019/02/14/transient-0.1. + +However your configuration and/or some third-party package that +you use still depends on the `magit-popup' package. But because +`magit' no longer depends on that, `package' has removed it from +your system. + +If some package that you use still depends on `magit-popup' but +does not declare it as a dependency, then please contact its +maintainer about that and install `magit-popup' explicitly. + +If you yourself use functions that are defined in `magit-popup' +in your configuration, then the next step depends on what you use +that for. + +* If you use `magit-popup' to define your own popups but do not + modify any of Magit's old popups, then you have to install + `magit-popup' explicitly. (You can also migrate to Transient, + but there is no need to rush that.) + +* If you add additional arguments and/or actions to Magit's popups, + then you have to port that to modify the new \"transients\" instead. + See https://github.com/magit/magit/wiki/\ +Converting-popup-modifications-to-transient-modifications + +To find installed packages that still use `magit-popup' you can +use e.g. \"M-x rgrep RET magit-popup RET RET ~/.emacs.d/ RET\".")) +(cl-eval-when (eval load) + (unless (require 'magit-popup nil t) + (defun magit-define-popup-switch (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-option (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-variable (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-action (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-sequence-action (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-key (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-keys-deferred (&rest _) + (magit--magit-popup-warning)) + (defun magit-change-popup-key (&rest _) + (magit--magit-popup-warning)) + (defun magit-remove-popup-key (&rest _) + (magit--magit-popup-warning)))) + +;;; _ +(provide 'magit-obsolete) +;;; magit-obsolete.el ends here diff --git a/elpa/magit-20190514.1814/magit-patch.el b/elpa/magit-20190514.1814/magit-patch.el new file mode 100644 index 00000000..95e3e569 --- /dev/null +++ b/elpa/magit-20190514.1814/magit-patch.el @@ -0,0 +1,267 @@ +;;; magit-patch.el --- creating and applying patches -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; 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. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements patch commands. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Options + +(defcustom magit-patch-save-arguments '(exclude "--stat") + "Control arguments used by the command `magit-patch-save'. + +`magit-patch-save' (which see) saves a diff for the changes +shown in the current buffer in a patch file. It may use the +same arguments as used in the buffer or a subset thereof, or +a constant list of arguments, depending on this option and +the prefix argument." + :package-version '(magit . "2.12.0") + :group 'magit-diff + :type '(choice (const :tag "use buffer arguments" buffer) + (cons :tag "use buffer arguments except" + (const :format "" exclude) + (repeat :format "%v%i\n" + (string :tag "Argument"))) + (repeat :tag "use constant arguments" + (string :tag "Argument")))) + +;;; Commands + +;;;###autoload (autoload 'magit-patch "magit-patch" nil t) +(define-transient-command magit-patch () + "Create or apply patches." + ["Actions" + ("c" "Create patches" magit-patch-create) + ("a" "Apply patch" magit-patch-apply) + ("s" "Save diff as patch" magit-patch-save) + ("r" "Request pull" magit-request-pull)]) + +;;;###autoload (autoload 'magit-patch-create "magit-patch" nil t) +(define-transient-command magit-patch-create (range args files) + "Create patches for the commits in RANGE. +When a single commit is given for RANGE, create a patch for the +changes introduced by that commit (unlike 'git format-patch' +which creates patches for all commits that are reachable from +`HEAD' but not from the specified commit)." + :man-page "git-format-patch" + ["Mail arguments" + (magit-format-patch:--in-reply-to) + (magit-format-patch:--thread) + (magit-format-patch:--reroll-count) + (magit-format-patch:--subject-prefix) + ("C-m l " "Add cover letter" "--cover-letter") + (magit-format-patch:--from) + (magit-format-patch:--to) + (magit-format-patch:--cc) + (magit-format-patch:--output-directory)] + ["Diff arguments" + (magit-diff:-U) + (magit-diff:-M) + (magit-diff:-C) + (magit-diff:--diff-algorithm) + (magit:--) + (7 "-b" "Ignore whitespace changes" ("-b" "--ignore-space-change")) + (7 "-w" "Ignore all whitespace" ("-w" "--ignore-all-space"))] + ["Actions" + ("c" "Create patches" magit-patch-create)] + (interactive + (if (not (eq current-transient-command 'magit-patch-create)) + (list nil nil nil) + (cons (if-let ((revs (magit-region-values 'commit t))) + (concat (car (last revs)) "^.." (car revs)) + (let ((range (magit-read-range-or-commit + "Format range or commit"))) + (if (string-match-p "\\.\\." range) + range + (format "%s~..%s" range range)))) + (let ((args (transient-args 'magit-patch-create))) + (list (-filter #'stringp args) + (cdr (assoc "--" args))))))) + (if (not range) + (transient-setup 'magit-patch-create) + (magit-run-git "format-patch" range args "--" files) + (when (member "--cover-letter" args) + (save-match-data + (find-file + (expand-file-name + (concat (--some (and (string-match "\\`--reroll-count=\\(.+\\)" it) + (format "v%s-" (match-string 1 it))) + args) + "0000-cover-letter.patch") + (let ((topdir (magit-toplevel))) + (or (--some (and (string-match "\\`--output-directory=\\(.+\\)" it) + (expand-file-name (match-string 1 it) topdir)) + args) + topdir)))))))) + +(define-infix-argument magit-format-patch:--in-reply-to () + :description "In reply to" + :class 'transient-option + :key "C-m r " + :argument "--in-reply-to=") + +(define-infix-argument magit-format-patch:--thread () + :description "Thread style" + :class 'transient-option + :key "C-m s " + :argument "--thread=") + +(define-infix-argument magit-format-patch:--reroll-count () + :description "Reroll count" + :class 'transient-option + :key "C-m v " + :shortarg "-v" + :argument "--reroll-count=" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-format-patch:--subject-prefix () + :description "Subject Prefix" + :class 'transient-option + :key "C-m p " + :argument "--subject-prefix=") + +(define-infix-argument magit-format-patch:--from () + :description "From" + :class 'transient-option + :key "C-m C-f" + :argument "--from=" + :reader 'magit-transient-read-person) + +(define-infix-argument magit-format-patch:--to () + :description "To" + :class 'transient-option + :key "C-m C-t" + :argument "--to=" + :reader 'magit-transient-read-person) + +(define-infix-argument magit-format-patch:--cc () + :description "CC" + :class 'transient-option + :key "C-m C-c" + :argument "--cc=" + :reader 'magit-transient-read-person) + +(define-infix-argument magit-format-patch:--output-directory () + :description "Output directory" + :class 'transient-option + :key "C-m o " + :shortarg "-o" + :argument "--output-directory=" + :reader 'transient-read-existing-directory) + +;;;###autoload (autoload 'magit-patch-apply "magit-patch" nil t) +(define-transient-command magit-patch-apply (file &rest args) + "Apply the patch file FILE." + :man-page "git-apply" + ["Arguments" + ("-i" "Also apply to index" "--index") + ("-c" "Only apply to index" "--cached") + ("-3" "Fall back on 3way merge" ("-3" "--3way"))] + ["Actions" + ("a" "Apply patch" magit-patch-apply)] + (interactive + (if (not (eq current-transient-command 'magit-patch-apply)) + (list nil) + (list (expand-file-name + (read-file-name "Apply patch: " + default-directory nil nil + (when-let ((file (magit-file-at-point))) + (file-relative-name file)))) + (transient-args 'magit-patch-apply)))) + (if (not file) + (transient-setup 'magit-patch-apply) + (magit-run-git "apply" args "--" (magit-convert-filename-for-git file)))) + +;;;###autoload +(defun magit-patch-save (file &optional arg) + "Write current diff into patch FILE. + +What arguments are used to create the patch depends on the value +of `magit-patch-save-arguments' and whether a prefix argument is +used. + +If the value is the symbol `buffer', then use the same arguments +as the buffer. With a prefix argument use no arguments. + +If the value is a list beginning with the symbol `exclude', then +use the same arguments as the buffer except for those matched by +entries in the cdr of the list. The comparison is done using +`string-prefix-p'. With a prefix argument use the same arguments +as the buffer. + +If the value is a list of strings (including the empty list), +then use those arguments. With a prefix argument use the same +arguments as the buffer. + +Of course the arguments that are required to actually show the +same differences as those shown in the buffer are always used." + (interactive (list (read-file-name "Write patch file: " default-directory) + current-prefix-arg)) + (unless (derived-mode-p 'magit-diff-mode) + (user-error "Only diff buffers can be saved as patches")) + (let ((rev magit-buffer-range) + (typearg magit-buffer-typearg) + (args magit-buffer-diff-args) + (files magit-buffer-diff-files)) + (cond ((eq magit-patch-save-arguments 'buffer) + (when arg + (setq args nil))) + ((eq (car-safe magit-patch-save-arguments) 'exclude) + (unless arg + (setq args (-difference args (cdr magit-patch-save-arguments))))) + ((not arg) + (setq args magit-patch-save-arguments))) + (with-temp-file file + (magit-git-insert "diff" rev "-p" typearg args "--" files))) + (magit-refresh)) + +;;;###autoload +(defun magit-request-pull (url start end) + "Request upstream to pull from you public repository. + +URL is the url of your publically accessible repository. +START is a commit that already is in the upstream repository. +END is the last commit, usually a branch name, which upstream +is asked to pull. START has to be reachable from that commit." + (interactive + (list (magit-get "remote" (magit-read-remote "Remote") "url") + (magit-read-branch-or-commit "Start" (magit-get-upstream-branch)) + (magit-read-branch-or-commit "End"))) + (let ((dir default-directory)) + ;; mu4e changes default-directory + (compose-mail) + (setq default-directory dir)) + (message-goto-body) + (magit-git-insert "request-pull" start url end) + (set-buffer-modified-p nil)) + +;;; _ +(provide 'magit-patch) +;;; magit-patch.el ends here diff --git a/elpa/magit-20190514.1814/magit-pkg.el b/elpa/magit-20190514.1814/magit-pkg.el new file mode 100644 index 00000000..df498cb9 --- /dev/null +++ b/elpa/magit-20190514.1814/magit-pkg.el @@ -0,0 +1,12 @@ +(define-package "magit" "20190514.1814" "A Git porcelain inside Emacs." + '((emacs "25.1") + (async "20180527") + (dash "20180910") + (git-commit "20181104") + (transient "0") + (with-editor "20181103")) + :keywords + '("git" "tools" "vc")) +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/magit-20190122.503/magit-process.el b/elpa/magit-20190514.1814/magit-process.el similarity index 94% rename from elpa/magit-20190122.503/magit-process.el rename to elpa/magit-20190514.1814/magit-process.el index a3013ede..863844dc 100644 --- a/elpa/magit-20190122.503/magit-process.el +++ b/elpa/magit-20190514.1814/magit-process.el @@ -195,6 +195,35 @@ non-nil, then the password is read from the user instead." :group 'magit-process :type '(repeat (regexp))) +(defcustom magit-process-prompt-functions nil + "List of functions used to forward arbitrary questions to the user. + +Magit has dedicated support for forwarding username and password +prompts and Yes-or-No questions asked by Git and its subprocesses +to the user. This can be customized using other options in the +`magit-process' customization group. + +If you encounter a new question that isn't handled by default, +then those options should be used instead of this hook. + +However subprocesses may also ask questions that differ too much +from what the code related to the above options assume, and this +hook allows users to deal with such questions explicitly. + +Each function is called with the process and the output string +as arguments until one of the functions returns non-nil. The +function is responsible for asking the user the appropriate +question using e.g. `read-char-choice' and then forwarding the +answer to the process using `process-send-string'. + +While functions such as `magit-process-yes-or-no-prompt' may not +be sufficient to handle some prompt, it may still be of benefit +to look at the implementations to gain some insights on how to +implement such functions." + :package-version '(magit . "2.91.0") + :group 'magit-process + :type 'hook) + (defcustom magit-process-ensure-unix-line-ending t "Whether Magit should ensure a unix coding system when talking to Git." :package-version '(magit . "2.6.0") @@ -420,13 +449,6 @@ flattened before use." magit-git-executable nil process-buf nil flat-args) process-buf nil default-directory section)))) -(defun magit-run-git-with-logfile (file &rest args) - "Call Git in a separate process and log its output to FILE. -This function might have a short halflive." - (apply #'magit-process-file magit-git-executable nil `(:file ,file) nil - (magit-process-git-arguments args)) - (magit-refresh)) - ;;; Asynchronous Processes (defun magit-run-git-async (&rest args) @@ -673,7 +695,7 @@ Magit status buffer." (when-let ((process-buf (process-buffer process))) (when (buffer-live-p process-buf) (when-let ((status-buf (with-current-buffer process-buf - (magit-mode-get-buffer 'magit-status-mode)))) + (magit-get-mode-buffer 'magit-status-mode)))) (with-current-buffer status-buf (--when-let (magit-get-section @@ -691,22 +713,21 @@ Magit status buffer." "Default filter used by `magit-start-process'." (with-current-buffer (process-buffer proc) (let ((inhibit-read-only t)) - (magit-process-yes-or-no-prompt proc string) - (magit-process-username-prompt proc string) - (magit-process-password-prompt proc string) (goto-char (process-mark proc)) - (setq string (propertize string 'magit-section - (process-get proc 'section))) ;; Find last ^M in string. If one was found, ignore ;; everything before it and delete the current line. - (let ((ret-pos (length string))) - (while (and (>= (cl-decf ret-pos) 0) - (/= ?\r (aref string ret-pos)))) - (if (< ret-pos 0) - (insert string) - (delete-region (line-beginning-position) (point)) - (insert (substring string (1+ ret-pos))))) - (set-marker (process-mark proc) (point))))) + (when-let ((ret-pos (cl-position ?\r string :from-end t))) + (cl-callf substring string (1+ ret-pos)) + (delete-region (line-beginning-position) (point))) + (insert (propertize string 'magit-section + (process-get proc 'section))) + (set-marker (process-mark proc) (point)) + ;; Make sure prompts are matched after removing ^M. + (magit-process-yes-or-no-prompt proc string) + (magit-process-username-prompt proc string) + (magit-process-password-prompt proc string) + (run-hook-with-args-until-success 'magit-process-prompt-functions + proc string)))) (defmacro magit-process-kill-on-abort (proc &rest body) (declare (indent 1) (debug (form body))) @@ -753,7 +774,7 @@ which matches the ~/.authinfo.gpg entry or iff that is undefined, for backward compatibility machine tarsius@bitbucket.org password 12345" (require 'auth-source) - (and (string-match "\\`\\([^@]+\\)@\\([^@]+\\)\\'" key) + (and (string-match "\\`\\(.+\\)@\\([^@]+\\)\\'" key) (let* ((user (match-string 1 key)) (host (match-string 2 key)) (secret @@ -949,13 +970,14 @@ If STR is supplied, it replaces the `mode-line-process' text." 'magit-mode-line-process-error)) (magit-process-unset-mode-line)))) -(defun magit-process-unset-mode-line () +(defun magit-process-unset-mode-line (&optional directory) "Remove the git command from the mode line." - (unless (magit-repository-local-get 'inhibit-magit-process-unset-mode-line) - (magit-repository-local-set 'mode-line-process nil) - (dolist (buf (magit-mode-get-buffers)) - (with-current-buffer buf (setq mode-line-process nil))) - (force-mode-line-update t))) + (let ((default-directory (or directory default-directory))) + (unless (magit-repository-local-get 'inhibit-magit-process-unset-mode-line) + (magit-repository-local-set 'mode-line-process nil) + (dolist (buf (magit-mode-get-buffers)) + (with-current-buffer buf (setq mode-line-process nil))) + (force-mode-line-update t)))) (defvar magit-process-error-message-regexps (list "^\\*ERROR\\*: Canceled by user$" @@ -1051,7 +1073,7 @@ Limited by `magit-process-error-tooltip-max-lines'." (magit-section-hide section))))))) (if (= arg 0) ;; Unset the `mode-line-process' value upon success. - (magit-process-unset-mode-line) + (magit-process-unset-mode-line default-dir) ;; Otherwise process the error. (let ((msg (magit-process-error-summary process-buf section))) ;; Change `mode-line-process' to an error face upon failure. @@ -1059,7 +1081,7 @@ Limited by `magit-process-error-tooltip-max-lines'." (magit-process-set-mode-line-error-status (or (magit-process-error-tooltip process-buf section) msg)) - (magit-process-unset-mode-line)) + (magit-process-unset-mode-line default-dir)) ;; Either signal the error, or else display the error summary in ;; the status buffer and with a message in the echo area. (cond @@ -1068,7 +1090,7 @@ Limited by `magit-process-error-tooltip-max-lines'." ((not (eq msg 'suppressed)) (when (buffer-live-p process-buf) (with-current-buffer process-buf - (when-let ((status-buf (magit-mode-get-buffer 'magit-status-mode))) + (when-let ((status-buf (magit-get-mode-buffer 'magit-status-mode))) (with-current-buffer status-buf (setq magit-this-error msg))))) (message "%s ... [%s buffer %s for details]" msg diff --git a/elpa/magit-20190514.1814/magit-pull.el b/elpa/magit-20190514.1814/magit-pull.el new file mode 100644 index 00000000..ba418313 --- /dev/null +++ b/elpa/magit-20190514.1814/magit-pull.el @@ -0,0 +1,163 @@ +;;; magit-pull.el --- update local objects and refs -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; 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. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements pull commands. + +;;; Code: + +(require 'magit) + +;;; Options + +(defcustom magit-pull-or-fetch nil + "Whether `magit-pull' also offers some fetch suffixes." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'boolean) + +;;; Commands + +;;;###autoload (autoload 'magit-pull "magit-pull" nil t) +(define-transient-command magit-pull () + "Pull from another repository." + :man-page "git-pull" + [:description + (lambda () (if magit-pull-or-fetch "Pull arguments" "Arguments")) + ("-r" "Rebase local commits" ("-r" "--rebase"))] + [:description + (lambda () + (if-let ((branch (magit-get-current-branch))) + (concat + (propertize "Pull into " 'face 'transient-heading) + (propertize branch 'face 'magit-branch-local) + (propertize " from" 'face 'transient-heading)) + (propertize "Pull from" 'face 'transient-heading))) + ("p" magit-pull-from-pushremote) + ("u" magit-pull-from-upstream) + ("e" "elsewhere" magit-pull-branch)] + ["Fetch from" + :if-non-nil magit-pull-or-fetch + ("f" "remotes" magit-fetch-all-no-prune) + ("F" "remotes and prune" magit-fetch-all-prune)] + ["Fetch" + :if-non-nil magit-pull-or-fetch + ("o" "another branch" magit-fetch-branch) + ("s" "explicit refspec" magit-fetch-refspec) + ("m" "submodules" magit-fetch-modules)] + ["Configure" + ("r" magit-branch..rebase :if magit-get-current-branch) + ("C" "variables..." magit-branch-configure)] + (interactive) + (transient-setup 'magit-pull nil nil :scope (magit-get-current-branch))) + +(defun magit-pull-arguments () + (transient-args 'magit-pull)) + +;;;###autoload (autoload 'magit-pull-from-pushremote "magit-pull" nil t) +(define-suffix-command magit-pull-from-pushremote (args) + "Pull from the push-remote of the current branch. + +When the push-remote is not configured, then read the push-remote +from the user, set it, and then pull from it. With a prefix +argument the push-remote can be changed before pulling from it." + :if 'magit-get-current-branch + :description 'magit-pull--pushbranch-description + (interactive (list (magit-pull-arguments))) + (pcase-let ((`(,branch ,remote) + (magit--select-push-remote "pull from there"))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "pull" args remote branch))) + +(defun magit-pull--pushbranch-description () + ;; Also used by `magit-rebase-onto-pushremote'. + (let* ((branch (magit-get-current-branch)) + (target (magit-get-push-branch branch t)) + (remote (magit-get-push-remote branch)) + (v (magit--push-remote-variable branch t))) + (cond + (target) + ((member remote (magit-list-remotes)) + (format "%s, replacing non-existent" v)) + (remote + (format "%s, replacing invalid" v)) + (t + (format "%s, setting that" v))))) + +;;;###autoload (autoload 'magit-pull-from-upstream "magit-pull" nil t) +(define-suffix-command magit-pull-from-upstream (args) + "Pull from the upstream of the current branch. + +With a prefix argument or when the upstream is either not +configured or unusable, then let the user first configure +the upstream." + :if 'magit-get-current-branch + :description 'magit-pull--upstream-description + (interactive (list (magit-pull-arguments))) + (let* ((branch (or (magit-get-current-branch) + (user-error "No branch is checked out"))) + (remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (when (or current-prefix-arg + (not (or (magit-get-upstream-branch branch) + (magit--unnamed-upstream-p remote merge)))) + (magit-set-upstream-branch + branch (magit-read-upstream-branch + branch (format "Set upstream of %s and pull from there" branch))) + (setq remote (magit-get "branch" branch "remote")) + (setq merge (magit-get "branch" branch "merge"))) + (run-hooks 'magit-credential-hook) + (magit-run-git-with-editor "pull" args remote merge))) + +(defun magit-pull--upstream-description () + (when-let ((branch (magit-get-current-branch))) + (or (magit-get-upstream-branch branch) + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge")) + (u (propertize "@{upstream}" 'face 'bold))) + (cond + ((magit--unnamed-upstream-p remote merge) + (format "%s of %s" + (propertize merge 'face 'magit-branch-remote) + (propertize remote 'face 'bold))) + ((magit--valid-upstream-p remote merge) + (concat u ", replacing non-existent")) + ((or remote merge) + (concat u ", replacing invalid")) + (t + (concat u ", setting that"))))))) + +;;;###autoload +(defun magit-pull-branch (source args) + "Pull from a branch read in the minibuffer." + (interactive (list (magit-read-remote-branch "Pull" nil nil nil t) + (magit-pull-arguments))) + (run-hooks 'magit-credential-hook) + (pcase-let ((`(,remote . ,branch) + (magit-get-tracked source))) + (magit-run-git-with-editor "pull" args remote branch))) + +;;; _ +(provide 'magit-pull) +;;; magit-pull.el ends here diff --git a/elpa/magit-20190122.503/magit-push.el b/elpa/magit-20190514.1814/magit-push.el similarity index 52% rename from elpa/magit-20190122.503/magit-push.el rename to elpa/magit-20190514.1814/magit-push.el index f34be472..25934145 100644 --- a/elpa/magit-20190122.503/magit-push.el +++ b/elpa/magit-20190514.1814/magit-push.el @@ -32,154 +32,142 @@ (require 'magit) -;;; Options - -(defcustom magit-push-current-set-remote-if-missing t - "Whether to configure missing remotes before pushing. - -When nil, then the command `magit-push-current-to-pushremote' and -`magit-push-current-to-upstream' do not appear in the push popup -if the push-remote resp. upstream is not configured. If the user -invokes one of these commands anyway, then it raises an error. - -When non-nil, then these commands always appear in the push -popup. But if the required configuration is missing, then they -do appear in a way that indicates that this is the case. If the -user invokes one of them, then it asks for the necessary -configuration, stores the configuration, and then uses it to push -a first time. - -This option also affects whether the argument `--set-upstream' is -available in the popup. If the value is t, then that argument is -redundant. But note that changing the value of this option does -not take affect immediately, the argument will only be added or -removed after restarting Emacs." - :package-version '(magit . "2.6.0") - :group 'magit-commands - :type '(choice (const :tag "don't set" nil) - (const :tag "set branch..pushRemote" t) - (const :tag "set remote.pushDefault" default))) - ;;; Commands -;;;###autoload (autoload 'magit-push-popup "magit-push" nil t) -(magit-define-popup magit-push-popup - "Popup console for push commands." +;;;###autoload (autoload 'magit-push "magit-push" nil t) +(define-transient-command magit-push () + "Push to another repository." :man-page "git-push" - :switches `((?f "Force with lease" "--force-with-lease") - (?F "Force" "--force") - (?h "Disable hooks" "--no-verify") - (?d "Dry run" "--dry-run") - ,@(and (not magit-push-current-set-remote-if-missing) - '((?u "Set upstream" "--set-upstream")))) - :actions '("Configure" - (?C "variables..." magit-branch-config-popup) - (lambda () - (--when-let (magit-get-current-branch) - (concat (propertize "Push " 'face 'magit-popup-heading) - (propertize it 'face 'magit-branch-local) - (propertize " to" 'face 'magit-popup-heading)))) - (?p magit--push-current-to-pushremote-desc - magit-push-current-to-pushremote) - (?u magit--push-current-to-upstream-desc - magit-push-current-to-upstream) - (?e "elsewhere\n" magit-push-current) - "Push" - (?o "another branch" magit-push-other) - (?T "a tag" magit-push-tag) - (?r "explicit refspecs" magit-push-refspecs) - (?t "all tags" magit-push-tags) - (?m "matching branches" magit-push-matching)) - :max-action-columns 2) + ["Arguments" + ("-f" "Force with lease" (nil "--force-with-lease")) + ("-F" "Force" ("-f" "--force")) + ("-h" "Disable hooks" "--no-verify") + ("-n" "Dry run" ("-n" "--dry-run")) + (5 "-u" "Set upstream" "--set-upstream") + (7 "-t" "Follow tags" "--follow-tags")] + [:if magit-get-current-branch + :description (lambda () + (format (propertize "Push %s to" 'face 'transient-heading) + (propertize (magit-get-current-branch) + 'face 'magit-branch-local))) + ("p" magit-push-current-to-pushremote) + ("u" magit-push-current-to-upstream) + ("e" "elsewhere" magit-push-current)] + ["Push" + [("o" "another branch" magit-push-other) + ("r" "explicit refspecs" magit-push-refspecs) + ("m" "matching branches" magit-push-matching)] + [("T" "a tag" magit-push-tag) + ("t" "all tags" magit-push-tags)]] + ["Configure" + ("C" "Set variables..." magit-branch-configure)]) + +(defun magit-push-arguments () + (transient-args 'magit-push)) (defun magit-git-push (branch target args) (run-hooks 'magit-credential-hook) - (pcase-let ((`(,remote . ,target) + ;; If the remote branch already exists, then we do not have to + ;; qualify the target, which we prefer to avoid doing because + ;; using the default namespace is wrong in obscure cases. + (pcase-let ((namespace (if (magit-get-tracked target) "" "refs/heads/")) + (`(,remote . ,target) (magit-split-branch-name target))) (magit-run-git-async "push" "-v" args remote - (format "%s:refs/heads/%s" branch target)))) + (format "%s:%s%s" branch namespace target)))) -;;;###autoload -(defun magit-push-current-to-pushremote (args &optional push-remote) - "Push the current branch to `branch..pushRemote'. -If that variable is unset, then push to `remote.pushDefault'. - -When `magit-push-current-set-remote-if-missing' is non-nil and -the push-remote is not configured, then read the push-remote from -the user, set it, and then push to it. With a prefix argument -the push-remote can be changed before pushed to it." - (interactive - (list (magit-push-arguments) - (and (magit--push-current-set-pushremote-p current-prefix-arg) - (magit-read-remote - (if (eq magit-push-current-set-remote-if-missing 'default) - "Set `remote.pushDefault' and push there" - (format "Set `branch.%s.pushRemote' and push there" - (magit-get-current-branch))))))) - (--if-let (magit-get-current-branch) - (progn (when push-remote - (setf (magit-get - (if (eq magit-push-current-set-remote-if-missing 'default) - "remote.pushDefault" - (format "branch.%s.pushRemote" it))) - push-remote)) - (if-let ((remote (magit-get-push-remote it))) - (if (member remote (magit-list-remotes)) - (magit-git-push it (concat remote "/" it) args) - (user-error "Remote `%s' doesn't exist" remote)) - (user-error "No push-remote is configured for %s" it))) - (user-error "No branch is checked out"))) - -(defun magit--push-current-set-pushremote-p (&optional change) - (and (or change - (and magit-push-current-set-remote-if-missing - (not (magit-get-push-remote)))) - (magit-get-current-branch))) - -(defun magit--push-current-to-pushremote-desc () - (--if-let (magit-get-push-branch) - (concat (magit-branch-set-face it) "\n") - (and (magit--push-current-set-pushremote-p) - (concat - (propertize (if (eq magit-push-current-set-remote-if-missing 'default) - "pushDefault" - "pushRemote") - 'face 'bold) - ", after setting that\n")))) +;;;###autoload (autoload 'magit-push-current-to-pushremote "magit-push" nil t) +(define-suffix-command magit-push-current-to-pushremote (args) + "Push the current branch to its push-remote. -;;;###autoload -(defun magit-push-current-to-upstream (args &optional upstream) +When the push-remote is not configured, then read the push-remote +from the user, set it, and then push to it. With a prefix +argument the push-remote can be changed before pushed to it." + :if 'magit-get-current-branch + :description 'magit-push--pushbranch-description + (interactive (list (magit-push-arguments))) + (pcase-let ((`(,branch ,remote) + (magit--select-push-remote "push there"))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" "-v" args remote + (format "refs/heads/%s:refs/heads/%s" + branch branch)))) ; see #3847 and #3872 + +(defun magit-push--pushbranch-description () + (let* ((branch (magit-get-current-branch)) + (target (magit-get-push-branch branch t)) + (remote (magit-get-push-remote branch)) + (v (magit--push-remote-variable branch t))) + (cond + (target) + ((member remote (magit-list-remotes)) + (format "%s, creating it" + (propertize (concat remote "/" branch) + 'face 'magit-branch-remote))) + (remote + (format "%s, replacing invalid" v)) + (t + (format "%s, setting that" v))))) + +;;;###autoload (autoload 'magit-push-current-to-upstream "magit-push" nil t) +(define-suffix-command magit-push-current-to-upstream (args) "Push the current branch to its upstream branch. -When `magit-push-current-set-remote-if-missing' is non-nil and -the upstream is not configured, then read the upstream from the -user, set it, and then push to it. With a prefix argument the -upstream can be changed before pushed to it." - (interactive - (list (magit-push-arguments) - (and (magit--push-current-set-upstream-p current-prefix-arg) - (magit-read-upstream-branch)))) - (--if-let (magit-get-current-branch) - (progn - (when upstream - (magit-set-upstream-branch it upstream)) - (if-let ((target (magit-get-upstream-branch it))) - (magit-git-push it target args) - (user-error "No upstream is configured for %s" it))) - (user-error "No branch is checked out"))) - -(defun magit--push-current-set-upstream-p (&optional change) - (and (or change - (and magit-push-current-set-remote-if-missing - (not (magit-get-upstream-branch)))) - (magit-get-current-branch))) - -(defun magit--push-current-to-upstream-desc () - (--if-let (magit-get-upstream-branch) - (concat (magit-branch-set-face it) "\n") - (and (magit--push-current-set-upstream-p) - (concat (propertize "@{upstream}" 'face 'bold) - ", after setting that\n")))) +With a prefix argument or when the upstream is either not +configured or unusable, then let the user first configure +the upstream." + :if 'magit-get-current-branch + :description 'magit-push--upstream-description + (interactive (list (magit-push-arguments))) + (let* ((branch (or (magit-get-current-branch) + (user-error "No branch is checked out"))) + (remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (when (or current-prefix-arg + (not (or (magit-get-upstream-branch branch) + (magit--unnamed-upstream-p remote merge) + (magit--valid-upstream-p remote merge)))) + (let* ((branches (-union (--map (concat it "/" branch) + (magit-list-remotes)) + (magit-list-remote-branch-names))) + (upstream (magit-completing-read + (format "Set upstream of %s and push there" branch) + branches nil nil nil 'magit-revision-history + (or (car (member (magit-remote-branch-at-point) branches)) + (car (member "origin/master" branches))))) + (upstream (or (magit-get-tracked upstream) + (magit-split-branch-name upstream)))) + (setq remote (car upstream)) + (setq merge (cdr upstream)) + (unless (string-prefix-p "refs/" merge) + ;; User selected a non-existent remote-tracking branch. + ;; It is very likely, but not certain, that this is the + ;; correct thing to do. It is even more likely that it + ;; is what the user wants to happen. + (setq merge (concat "refs/heads/" merge)))) + (cl-pushnew "--set-upstream" args :test #'equal)) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" "-v" args remote (concat branch ":" merge)))) + +(defun magit-push--upstream-description () + (when-let ((branch (magit-get-current-branch))) + (or (magit-get-upstream-branch branch) + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge")) + (u (propertize "@{upstream}" 'face 'bold))) + (cond + ((magit--unnamed-upstream-p remote merge) + (format "%s as %s" + (propertize remote 'face 'bold) + (propertize merge 'face 'magit-branch-remote))) + ((magit--valid-upstream-p remote merge) + (format "%s creating %s" + (propertize remote 'face 'magit-branch-remote) + (propertize merge 'face 'magit-branch-remote))) + ((or remote merge) + (concat u ", creating it and replacing invalid")) + (t + (concat u ", creating it"))))))) ;;;###autoload (defun magit-push-current (target args) @@ -273,13 +261,6 @@ these Git variables: `push.default', `remote.pushDefault', `branch..pushRemote', `branch..remote', `branch..merge', and `remote..push'. -To add this command to the push popup add this to your init file: - - (with-eval-after-load \\='magit-remote - (magit-define-popup-action \\='magit-push-popup ?P - \\='magit-push-implicitly--desc - \\='magit-push-implicitly ?p t)) - The function `magit-push-implicitly--desc' attempts to predict what this command will do. The value it returns is displayed in the popup buffer." @@ -324,14 +305,7 @@ are the arguments specified in the popup buffer. No refspec arguments are used. Instead the behavior depends on at least these Git variables: `push.default', `remote.pushDefault', `branch..pushRemote', `branch..remote', -`branch..merge', and `remote..push'. - -To add this command to the push popup add this to your init file: - - (with-eval-after-load \\='magit-remote - (magit-define-popup-action \\='magit-push-popup ?r - \\='magit-push-to-remote--desc - \\='magit-push-to-remote ?p t))" +`branch..merge', and `remote..push'." (interactive (list (magit-read-remote "Push to remote") (magit-push-arguments))) (run-hooks 'magit-credential-hook) diff --git a/elpa/magit-20190514.1814/magit-reflog.el b/elpa/magit-20190514.1814/magit-reflog.el new file mode 100644 index 00000000..ea3516d4 --- /dev/null +++ b/elpa/magit-20190514.1814/magit-reflog.el @@ -0,0 +1,211 @@ +;;; magit-reflog.el --- inspect ref history -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; 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. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for looking at Git reflogs. + +;;; Code: + +(require 'magit-core) +(require 'magit-log) + +(eval-when-compile + (require 'subr-x)) + +;;; Options + +(defcustom magit-reflog-limit 256 + "Maximal number of entries initially shown in reflog buffers. +The limit in the current buffer can be changed using \"+\" +and \"-\"." + :package-version '(magit . "2.91.0") + :group 'magit-git-arguments + :type 'number) + +(defcustom magit-reflog-margin + (list (nth 0 magit-log-margin) + (nth 1 magit-log-margin) + 'magit-log-margin-width nil + (nth 4 magit-log-margin)) + "Format of the margin in `magit-reflog-mode' buffers. + +The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). + +If INIT is non-nil, then the margin is shown initially. +STYLE controls how to format the committer date. It can be one + of `age' (to show the age of the commit), `age-abbreviated' (to + abbreviate the time unit to a character), or a string (suitable + for `format-time-string') to show the actual date. +WIDTH controls the width of the margin. This exists for forward + compatibility and currently the value should not be changed. +AUTHOR controls whether the name of the author is also shown by + default. +AUTHOR-WIDTH has to be an integer. When the name of the author + is shown, then this specifies how much space is used to do so." + :package-version '(magit . "2.9.0") + :group 'magit-log + :group 'magit-margin + :type magit-log-margin--custom-type + :initialize 'magit-custom-initialize-reset + :set-after '(magit-log-margin) + :set (apply-partially #'magit-margin-set-variable 'magit-reflog-mode)) + +;;; Faces + +(defface magit-reflog-commit '((t :foreground "green")) + "Face for commit commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-amend '((t :foreground "magenta")) + "Face for amend commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-merge '((t :foreground "green")) + "Face for merge, checkout and branch commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-checkout '((t :foreground "blue")) + "Face for checkout commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-reset '((t :foreground "red")) + "Face for reset commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-rebase '((t :foreground "magenta")) + "Face for rebase commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-cherry-pick '((t :foreground "green")) + "Face for cherry-pick commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-remote '((t :foreground "cyan")) + "Face for pull and clone commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-other '((t :foreground "cyan")) + "Face for other commands in reflogs." + :group 'magit-faces) + +;;; Commands + +;;;###autoload +(defun magit-reflog-current () + "Display the reflog of the current branch. +If `HEAD' is detached, then show the reflog for that instead." + (interactive) + (magit-reflog-setup-buffer (or (magit-get-current-branch) "HEAD"))) + +;;;###autoload +(defun magit-reflog-other (ref) + "Display the reflog of a branch or another ref." + (interactive (list (magit-read-local-branch-or-ref "Show reflog for"))) + (magit-reflog-setup-buffer ref)) + +;;;###autoload +(defun magit-reflog-head () + "Display the `HEAD' reflog." + (interactive) + (magit-reflog-setup-buffer "HEAD")) + +;;; Mode + +(defvar magit-reflog-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-log-mode-map) + (define-key map "\C-c\C-n" 'undefined) + (define-key map "L" 'magit-margin-settings) + map) + "Keymap for `magit-reflog-mode'.") + +(define-derived-mode magit-reflog-mode magit-mode "Magit Reflog" + "Mode for looking at Git reflog. + +This mode is documented in info node `(magit)Reflog'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +Type \\[magit-cherry-pick] to apply the commit at point. +Type \\[magit-reset] to reset `HEAD' to the commit at point. + +\\{magit-reflog-mode-map}" + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-reflog-setup-buffer (ref) + (require 'magit) + (magit-setup-buffer #'magit-reflog-mode nil + (magit-buffer-refname ref) + (magit-buffer-log-args (list (format "-n%s" magit-reflog-limit))))) + +(defun magit-reflog-refresh-buffer () + (magit-set-header-line-format (concat "Reflog for " magit-buffer-refname)) + (magit-insert-section (reflogbuf) + (magit-git-wash (apply-partially 'magit-log-wash-log 'reflog) + "reflog" "show" "--format=%h%x00%aN%x00%gd%x00%gs" "--date=raw" + magit-buffer-log-args magit-buffer-refname "--"))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-reflog-mode)) + magit-buffer-refname) + +(defvar magit-reflog-labels + '(("commit" . magit-reflog-commit) + ("amend" . magit-reflog-amend) + ("merge" . magit-reflog-merge) + ("checkout" . magit-reflog-checkout) + ("branch" . magit-reflog-checkout) + ("reset" . magit-reflog-reset) + ("rebase" . magit-reflog-rebase) + ("cherry-pick" . magit-reflog-cherry-pick) + ("initial" . magit-reflog-commit) + ("pull" . magit-reflog-remote) + ("clone" . magit-reflog-remote) + ("autosave" . magit-reflog-commit) + ("restart" . magit-reflog-reset))) + +(defun magit-reflog-format-subject (subject) + (let* ((match (string-match magit-reflog-subject-re subject)) + (command (and match (match-string 1 subject))) + (option (and match (match-string 2 subject))) + (type (and match (match-string 3 subject))) + (label (if (string= command "commit") + (or type command) + command)) + (text (if (string= command "commit") + label + (mapconcat #'identity + (delq nil (list command option type)) + " ")))) + (format "%-16s " + (propertize text 'face + (or (cdr (assoc label magit-reflog-labels)) + 'magit-reflog-other))))) + +;;; _ +(provide 'magit-reflog) +;;; magit-reflog.el ends here diff --git a/elpa/magit-20190122.503/magit-refs.el b/elpa/magit-20190514.1814/magit-refs.el similarity index 87% rename from elpa/magit-20190122.503/magit-refs.el rename to elpa/magit-20190514.1814/magit-refs.el index 4b814ff4..30c70dd4 100644 --- a/elpa/magit-20190122.503/magit-refs.el +++ b/elpa/magit-20190514.1814/magit-refs.el @@ -32,8 +32,6 @@ (require 'magit) -(defvar bookmark-make-record-function) - ;;; Options (defgroup magit-refs nil @@ -274,7 +272,7 @@ the outcome. (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-mode-map) (define-key map "\C-y" 'magit-refs-set-show-commit-count) - (define-key map "L" 'magit-margin-popup) + (define-key map "L" 'magit-margin-settings) map) "Keymap for `magit-refs-mode'.") @@ -289,117 +287,122 @@ Type \\[magit-section-toggle] to expand or hide the section at point. Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ to visit the commit or branch at point. -Type \\[magit-branch-popup] to see available branch commands. -Type \\[magit-merge-popup] to merge the branch or commit at point. -Type \\[magit-cherry-pick-popup] to apply the commit at point. +Type \\[magit-branch] to see available branch commands. +Type \\[magit-merge] to merge the branch or commit at point. +Type \\[magit-cherry-pick] to apply the commit at point. Type \\[magit-reset] to reset `HEAD' to the commit at point. \\{magit-refs-mode-map}" :group 'magit-refs (hack-dir-local-variables-non-file-buffer) (setq imenu-create-index-function - #'magit-imenu--refs-create-index-function) - (setq-local bookmark-make-record-function - #'magit-bookmark--refs-make-record)) + #'magit-imenu--refs-create-index-function)) + +(defun magit-refs-setup-buffer (ref args) + (magit-setup-buffer #'magit-refs-mode nil + (magit-buffer-upstream ref) + (magit-buffer-arguments args))) -(defun magit-refs-refresh-buffer (ref &optional args) +(defun magit-refs-refresh-buffer () (setq magit-set-buffer-margin-refresh (not (magit-buffer-margin-p))) - (unless ref - (setq ref "HEAD")) - (unless (magit-rev-verify ref) + (unless (magit-rev-verify magit-buffer-upstream) (setq magit-refs-show-commit-count nil)) (magit-set-header-line-format - (format "%s %s" ref (mapconcat #'identity args " "))) + (format "%s %s" magit-buffer-upstream + (mapconcat #'identity magit-buffer-arguments " "))) (magit-insert-section (branchbuf) (magit-run-section-hook 'magit-refs-sections-hook)) (add-hook 'kill-buffer-hook 'magit-preserve-section-visibility-cache)) +(cl-defmethod magit-buffer-value (&context (major-mode magit-refs-mode)) + (cons magit-buffer-upstream magit-buffer-arguments)) + ;;; Commands -(defcustom magit-show-refs-arguments nil - "The arguments used in `magit-refs-mode' buffers." - :group 'magit-git-arguments - :group 'magit-refs - :type '(repeat (string :tag "Argument"))) - -(defvar magit-show-refs-popup - (list - :variable 'magit-show-refs-arguments - :man-page "git-branch" - :switches '((?m "Merged to HEAD" "--merged") - (?M "Merged to master" "--merged=master") - (?n "Not merged to HEAD" "--no-merged") - (?N "Not merged to master" "--no-merged=master")) - :options '((?c "Contains" "--contains=" magit-read-branch-or-commit) - (?m "Merged" "--merged=" magit-read-branch-or-commit) - (?n "Not merged" "--no-merged=" magit-read-branch-or-commit) - (?s "Sort" "--sort=" magit-read-ref-sort)) - :actions '((?y "Show refs, comparing them with HEAD" - magit-show-refs-head) - (?c "Show refs, comparing them with current branch" - magit-show-refs-current) - (?o "Show refs, comparing them with other branch" - magit-show-refs)) - :default-action 'magit-show-refs-head - :max-action-columns 1 - :use-prefix (lambda () - (if (derived-mode-p 'magit-refs-mode) - (if current-prefix-arg 'popup 'default) - 'popup)))) - -(magit-define-popup-keys-deferred 'magit-show-refs-popup) - -(defun magit-read-ref-sort (prompt initial-input) +;;;###autoload (autoload 'magit-show-refs "magit-refs" nil t) +(define-transient-command magit-show-refs (&optional transient) + "List and compare references in a dedicated buffer." + :man-page "git-branch" + :value 'magit-show-refs-arguments + ["Arguments" + (magit-for-each-ref:--contains) + ("=m" "Merged" "--merged=" magit-transient-read-revision) + ("-m" "Merged to HEAD" "--merged") + ("-M" "Merged to master" "--merged=master") + ("=n" "Not merged" "--no-merged=" magit-transient-read-revision) + ("-n" "Not merged to HEAD" "--no-merged") + ("-N" "Not merged to master" "--no-merged=master") + (magit-for-each-ref:--sort)] + ["Actions" + ("y" "Show refs, comparing them with HEAD" magit-show-refs-head) + ("c" "Show refs, comparing them with current branch" magit-show-refs-current) + ("o" "Show refs, comparing them with other branch" magit-show-refs-other)] + (interactive (list (or (derived-mode-p 'magit-refs-mode) + current-prefix-arg))) + (if transient + (transient-setup 'magit-show-refs) + (magit-refs-setup-buffer "HEAD" (magit-show-refs-arguments)))) + +(defun magit-show-refs-arguments () + (let (args) + (cond + ((eq current-transient-command 'magit-show-refs) + (setq args (transient-args 'magit-show-refs))) + ((eq major-mode 'magit-show-refs-mode) + (setq args magit-buffer-arguments)) + ((and (memq magit-prefix-use-buffer-arguments '(always selected)) + (when-let ((buffer (magit-get-mode-buffer + 'magit-refs-mode nil + (or (eq magit-prefix-use-buffer-arguments + 'selected) + 'all)))) + (setq args (buffer-local-value 'magit-buffer-arguments buffer)) + t))) + (t + (setq args (alist-get 'magit-show-refs transient-values)))) + args)) + +(define-infix-argument magit-for-each-ref:--contains () + :description "Contains" + :class 'transient-option + :key "-c" + :argument "--contains=" + :reader 'magit-transient-read-revision) + +(define-infix-argument magit-for-each-ref:--sort () + :description "Sort" + :class 'transient-option + :key "-s" + :argument "--sort=" + :reader 'magit-read-ref-sort) + +(defun magit-read-ref-sort (prompt initial-input _history) (magit-completing-read prompt '("-committerdate" "-authordate" "committerdate" "authordate") nil nil initial-input)) -(defun magit-show-refs-get-buffer-args () - (cond ((and magit-use-sticky-arguments - (derived-mode-p 'magit-refs-mode)) - (cadr magit-refresh-args)) - ((and (eq magit-use-sticky-arguments t) - (--when-let (magit-mode-get-buffer 'magit-refs-mode) - (with-current-buffer it - (cadr magit-refresh-args))))) - (t - (default-value 'magit-show-refs-arguments)))) - -(defun magit-show-refs-arguments () - (if (eq magit-current-popup 'magit-show-refs-popup) - magit-current-popup-args - (magit-show-refs-get-buffer-args))) - -;;;###autoload -(defun magit-show-refs-popup (&optional arg) - "Popup console for `magit-show-refs'." - (interactive "P") - (let ((magit-show-refs-arguments (magit-show-refs-get-buffer-args))) - (magit-invoke-popup 'magit-show-refs-popup nil arg))) - ;;;###autoload (defun magit-show-refs-head (&optional args) "List and compare references in a dedicated buffer. -Refs are compared with `HEAD'." +Compared with `HEAD'." (interactive (list (magit-show-refs-arguments))) - (magit-show-refs nil args)) + (magit-refs-setup-buffer "HEAD" args)) ;;;###autoload (defun magit-show-refs-current (&optional args) "List and compare references in a dedicated buffer. -Refs are compared with the current branch or `HEAD' if -it is detached." +Compare with the current branch or `HEAD' if it is detached." (interactive (list (magit-show-refs-arguments))) - (magit-show-refs (magit-get-current-branch) args)) + (magit-refs-setup-buffer (magit-get-current-branch) args)) ;;;###autoload -(defun magit-show-refs (&optional ref args) +(defun magit-show-refs-other (&optional ref args) "List and compare references in a dedicated buffer. -Refs are compared with a branch read from the user." +Compared with a branch read from the user." (interactive (list (magit-read-other-branch "Compare with") (magit-show-refs-arguments))) - (magit-mode-setup #'magit-refs-mode ref args)) + (magit-refs-setup-buffer ref args)) (defun magit-refs-set-show-commit-count () "Change for which refs the commit count is shown." @@ -427,7 +430,7 @@ different, but only if you have customized the option (let ((ref (oref (magit-current-section) value))) (cond (current-prefix-arg (cond ((memq 'focus-on-ref magit-visit-ref-behavior) - (magit-show-refs ref)) + (magit-refs-setup-buffer ref (magit-show-refs-arguments))) (magit-visit-ref-behavior ;; Don't prompt for commit to visit. (let ((current-prefix-arg nil)) @@ -451,13 +454,13 @@ Branch %s already exists. (?r (magit-call-git "checkout" "-B" branch ref)) (?a (user-error "Abort")))) (magit-call-git "checkout" "-b" branch ref)) - (setcar magit-refresh-args branch) + (setq magit-buffer-upstream branch) (magit-refresh))) ((or (memq 'checkout-any magit-visit-ref-behavior) (and (memq 'checkout-branch magit-visit-ref-behavior) (magit-section-match [branch local]))) (magit-call-git "checkout" ref) - (setcar magit-refresh-args ref) + (setq magit-buffer-upstream ref) (magit-refresh)) (t (call-interactively #'magit-show-commit)))) @@ -506,8 +509,7 @@ line is inserted at all." (defun magit-insert-tags () "Insert sections showing all tags." - (when-let ((tags (magit-git-lines "tag" "--list" "-n" - (cadr magit-refresh-args)))) + (when-let ((tags (magit-git-lines "tag" "--list" "-n" magit-buffer-arguments))) (let ((_head (magit-rev-parse "HEAD"))) (magit-insert-section (tags) (magit-insert-heading "Tags:") @@ -544,7 +546,7 @@ line is inserted at all." (dolist (line (magit-git-lines "for-each-ref" "--format=\ %(symref:short)%00%(refname:short)%00%(refname)%00%(subject)" (concat "refs/remotes/" remote) - (cadr magit-refresh-args))) + magit-buffer-arguments)) (pcase-let ((`(,head-branch ,branch ,ref ,msg) (-replace "" nil (split-string line "\0")))) (if head-branch @@ -598,7 +600,7 @@ line is inserted at all." %(push:remotename)%00%(push)%00%(push:track)%00%(subject)" "%00%00%00%(subject)")) "refs/heads" - (cadr magit-refresh-args))))) + magit-buffer-arguments)))) (unless (magit-get-current-branch) (push (magit-refs--format-local-branch (concat "*\0\0\0\0\0\0\0\0" (magit-rev-format "%s"))) @@ -682,7 +684,7 @@ line is inserted at all." (and msg (magit-log-propertize-keywords nil msg))))))) (defun magit-refs--format-focus-column (ref &optional type) - (let ((focus (car magit-refresh-args)) + (let ((focus magit-buffer-upstream) (width (if magit-refs-show-commit-count magit-refs-focus-column-width 1))) @@ -698,9 +700,7 @@ line is inserted at all." (eq magit-refs-show-commit-count 'all) magit-refs-show-commit-count) (pcase-let ((`(,behind ,ahead) - (magit-rev-diff-count - (or (car magit-refresh-args) "HEAD") - ref))) + (magit-rev-diff-count magit-buffer-upstream ref))) (propertize (cond ((> ahead 0) (concat "<" (number-to-string ahead))) ((> behind 0) (concat (number-to-string behind) ">")) @@ -728,9 +728,7 @@ line is inserted at all." (let ((start (point)) (magit-insert-section--current nil)) (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) - "cherry" "-v" (magit-abbrev-arg) - (or (car magit-refresh-args) "HEAD") - ref magit-refresh-args) + "cherry" "-v" (magit-abbrev-arg) magit-buffer-upstream ref) (if (= (point) start) (message "No cherries for %s" ref) (magit-make-margin-overlay nil t))))) diff --git a/elpa/magit-20190122.503/magit-remote.el b/elpa/magit-20190514.1814/magit-remote.el similarity index 59% rename from elpa/magit-20190122.503/magit-remote.el rename to elpa/magit-20190514.1814/magit-remote.el index fa2d9219..54a7983e 100644 --- a/elpa/magit-20190122.503/magit-remote.el +++ b/elpa/magit-20190514.1814/magit-remote.el @@ -46,36 +46,48 @@ variable isn't already set." (string :tag "set if named") (const :tag "don't set"))) -(defcustom magit-remote-popup-show-variables t - "Whether the `magit-remote-popup' shows Git variables. -When set to nil, no variables are displayed directly in this -popup, instead the sub-popup `magit-remote-config-popup' has -to be used to view and change remote related variables." +(defcustom magit-remote-direct-configure t + "Whether the command `magit-remote' shows Git variables. +When set to nil, no variables are displayed by this transient +command, instead the sub-transient `magit-remote-configure' +has to be used to view and change remote related variables." :package-version '(magit . "2.12.0") :group 'magit-commands :type 'boolean) -;;; Commands +(defcustom magit-prefer-push-default nil + "Whether to prefer `remote.pushDefault' over per-branch variables." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'boolean) -(defvar magit-remote-config-variables) +;;; Commands -;;;###autoload (autoload 'magit-remote-popup "magit-remote" nil t) -(magit-define-popup magit-remote-popup - "Popup console for remote commands." +;;;###autoload (autoload 'magit-remote "magit-remote" nil t) +(define-transient-command magit-remote (remote) + "Add, configure or remove a remote." :man-page "git-remote" - :default-arguments '("-f") - :variables (lambda () - (and magit-remote-popup-show-variables - magit-remote-config-variables)) - :switches '("Switches for add" - (?f "Fetch after add" "-f")) - :actions '((?a "Add" magit-remote-add) - (?C "Configure..." magit-remote-config-popup) - (?r "Rename" magit-remote-rename) - (?p "Prune stale branches" magit-remote-prune) - (?k "Remove" magit-remote-remove) - (?P "Prune stale refspecs" magit-remote-prune-refspecs)) - :max-action-columns 2) + :value '("-f") + ["Variables" + :if (lambda () + (and magit-remote-direct-configure + (oref transient--prefix scope))) + ("u" magit-remote..url) + ("U" magit-remote..fetch) + ("s" magit-remote..pushurl) + ("S" magit-remote..push) + ("O" magit-remote..tagopt)] + ["Arguments for add" + ("-f" "Fetch after add" "-f")] + ["Actions" + [("a" "Add" magit-remote-add) + ("r" "Rename" magit-remote-rename) + ("k" "Remove" magit-remote-remove)] + [("C" "Configure..." magit-remote-configure) + ("p" "Prune stale branches" magit-remote-prune) + ("P" "Prune stale refspecs" magit-remote-prune-refspecs)]] + (interactive (list (magit-get-current-remote))) + (transient-setup 'magit-remote nil nil :scope remote)) (defun magit-read-url (prompt &optional initial-input) (let ((url (magit-read-string-ns prompt initial-input))) @@ -88,7 +100,7 @@ to be used to view and change remote related variables." "Add a remote named REMOTE and fetch it." (interactive (list (magit-read-string-ns "Remote name") (magit-read-url "Remote url") - (magit-remote-arguments))) + (transient-args 'magit-remote))) (if (pcase (list magit-remote-add-set-remote.pushDefault (magit-get "remote.pushDefault")) (`(,(pred stringp) ,_) t) @@ -238,138 +250,90 @@ Delete the symbolic-ref \"refs/remotes//HEAD\"." ;;; Configure -(defvar magit-remote-config--remote nil) - -;;;###autoload -(defun magit-remote-config-popup (remote) - "Popup console for setting remote variables." +;;;###autoload (autoload 'magit-remote-configure "magit-remote" nil t) +(define-transient-command magit-remote-configure (remote) + "Configure a remote." + :man-page "git-remote" + [:description + (lambda () + (concat + (propertize "Configure " 'face 'transient-heading) + (propertize (oref transient--prefix scope) 'face 'magit-branch-remote))) + ("u" magit-remote..url) + ("U" magit-remote..fetch) + ("s" magit-remote..pushurl) + ("S" magit-remote..push) + ("O" magit-remote..tagopt)] (interactive - (list (if (or current-prefix-arg - (and (eq magit-current-popup 'magit-remote-popup) - magit-remote-popup-show-variables)) - (magit-read-remote "Configure remote") - (magit-remote-config--remote-1)))) - (let ((magit-remote-config--remote remote)) - (magit-invoke-popup 'magit-remote-config-popup nil nil))) - -(defvar magit-remote-config-variables - '((lambda () - (concat - (propertize "Configure " 'face 'magit-popup-heading) - (propertize (magit-remote-config--remote) 'face 'magit-branch-remote))) - (?u "remote.%s.url" - magit-set-remote*url - magit-format-remote*url) - (?U "remote.%s.fetch" - magit-set-remote*fetch - magit-format-remote*fetch) - (?s "remote.%s.pushurl" - magit-set-remote*pushurl - magit-format-remote*pushurl) - (?S "remote.%s.push" - magit-set-remote*push - magit-format-remote*push) - (?O "remote.%s.tagOpt" - magit-cycle-remote*tagOpt - magit-format-remote*tagOpt))) - -(defvar magit-remote-config-popup - `(:man-page "git-remote" - :variables ,magit-remote-config-variables - :setup-function magit-remote-config-popup-setup)) - -(defun magit-remote-config-popup-setup (val def) - (magit-popup-default-setup val def) - (setq-local magit-remote-config--remote magit-remote-config--remote)) - -(defun magit-remote-config--remote (&optional prompt) - (if prompt - (or (and (not current-prefix-arg) - (or magit-remote-config--remote - (magit-remote-config--remote-1))) - (magit-read-remote prompt)) - (or magit-remote-config--remote - (magit-remote-config--remote-1) - ""))) - -(defun magit-remote-config--remote-1 () - (let ((remote (magit-get-upstream-remote))) - (if (or (not remote) - (equal remote ".")) - (and (magit-remote-p "origin") "origin") - remote))) - -(defun magit-set-remote*url (remote urls) - "Set the variable `url' for the remote named REMOTE to URLS." - (interactive (magit-remote-config--read-args "url" "Urls: ")) - (magit-remote-config--set-url remote "url" urls)) - -(defun magit-set-remote*fetch (remote values) - "Set the variable `fetch' for the remote named REMOTE to VALUES." - (interactive (magit-remote-config--read-args "fetch" "Fetch specs: ")) - (magit-set-all values "remote" remote "fetch") - (magit-refresh)) - -(defun magit-set-remote*pushurl (remote urls) - "Set the variable `pushurl' for the remote named REMOTE to URLS." - (interactive (magit-remote-config--read-args "pushurl" "Urls: ")) - (magit-remote-config--set-url remote "pushurl" urls "--push")) - -(defun magit-set-remote*push (remote values) - "Set the variable `push' for the remote named REMOTE to VALUES." - (interactive (magit-remote-config--read-args "push" "Push specs: ")) - (magit-set-all values "remote" remote "push") - (magit-refresh)) - -(defun magit-cycle-remote*tagOpt (remote) - (interactive (list (magit-remote-config--remote))) - (magit--set-popup-variable (format "remote.%s.tagOpt" remote) - '("--no-tags" "--tags") nil)) - -(defun magit-format-remote*url () - (magit-remote-config--format-variable "url")) - -(defun magit-format-remote*fetch () - (magit-remote-config--format-variable "fetch")) - -(defun magit-format-remote*pushurl () - (magit-remote-config--format-variable "pushurl")) - -(defun magit-format-remote*push () - (magit-remote-config--format-variable "push")) - -(defun magit-format-remote*tagOpt () - (let ((remote (magit-remote-config--remote))) - (magit--format-popup-variable:choices - (format "remote.%s.tagOpts" remote) - '("--no-tags" "--tags") nil nil - (+ (length remote) 16)))) - -(defun magit-remote-config--read-args (var prompt) - (let* ((remote (magit-remote-config--remote (format "Set `%s' of remote" var))) - (value (magit-get-all "remote" remote var))) - (list remote - (mapcar (lambda (url) - (if (string-prefix-p "~" url) - (expand-file-name url) - url)) - (completing-read-multiple - prompt nil nil nil - (and value (mapconcat #'identity value ","))))))) - -(defun magit-remote-config--set-url (remote var values &optional arg) - (let ((old (magit-get-all "remote" remote var))) - (dolist (v (-difference values old)) - (magit-call-git "remote" "set-url" arg "--add" remote v)) - (dolist (v (-difference old values)) - (magit-call-git "remote" "set-url" arg "--delete" remote - (concat "^" (regexp-quote v) "$")))) - (magit-refresh)) - -(defun magit-remote-config--format-variable (variable) - (magit--format-popup-variable:values - (format "remote.%s.%s" (magit-remote-config--remote) variable) - 25)) + (list (or (and (not current-prefix-arg) + (not (and magit-remote-direct-configure + (eq current-transient-command 'magit-remote))) + (magit-get-current-remote)) + (magit--read-remote-scope)))) + (transient-setup 'magit-remote-configure nil nil :scope remote)) + +(defun magit--read-remote-scope (&optional obj) + (magit-read-remote + (if obj + (format "Set %s for remote" + (format (oref obj variable) "")) + "Configure remote"))) + +(define-infix-command magit-remote..url () + :class 'magit--git-variable:urls + :scope 'magit--read-remote-scope + :variable "remote.%s.url" + :multi-value t + :history-key 'magit-remote..*url) + +(define-infix-command magit-remote..fetch () + :class 'magit--git-variable + :scope 'magit--read-remote-scope + :variable "remote.%s.fetch" + :multi-value t) + +(define-infix-command magit-remote..pushurl () + :class 'magit--git-variable:urls + :scope 'magit--read-remote-scope + :variable "remote.%s.pushurl" + :multi-value t + :history-key 'magit-remote..*url + :seturl-arg "--push") + +(define-infix-command magit-remote..push () + :class 'magit--git-variable + :scope 'magit--read-remote-scope + :variable "remote.%s.push") + +(define-infix-command magit-remote..tagopt () + :class 'magit--git-variable:choices + :scope 'magit--read-remote-scope + :variable "remote.%s.tagOpt" + :choices '("--no-tags" "--tags")) + +;;; Transfer Utilities + +(defun magit--push-remote-variable (&optional branch short) + (unless branch + (setq branch (magit-get-current-branch))) + (propertize (if (or (not branch) magit-prefer-push-default) + (if short "pushDefault" "remote.pushDefault") + (if short "pushRemote" (format "branch.%s.pushRemote" branch))) + 'face 'bold)) + +(defun magit--select-push-remote (prompt-suffix) + (let* ((branch (or (magit-get-current-branch) + (user-error "No branch is checked out"))) + (remote (magit-get-push-remote branch))) + (when (or current-prefix-arg + (not remote) + (not (member remote (magit-list-remotes)))) + (setq remote + (magit-read-remote (format "Set %s and %s" + (magit--push-remote-variable) + prompt-suffix))) + (setf (magit-get (magit--push-remote-variable branch)) remote)) + (list branch remote))) ;;; _ (provide 'magit-remote) diff --git a/elpa/magit-20190122.503/magit-repos.el b/elpa/magit-20190514.1814/magit-repos.el similarity index 95% rename from elpa/magit-20190122.503/magit-repos.el rename to elpa/magit-20190514.1814/magit-repos.el index 7e7a2eee..e4fdb4ee 100644 --- a/elpa/magit-20190122.503/magit-repos.el +++ b/elpa/magit-20190514.1814/magit-repos.el @@ -34,7 +34,7 @@ (require 'magit-core) -(declare-function magit-status-internal "magit-status" (directory)) +(declare-function magit-status-setup-buffer "magit-status" (directory)) (defvar x-stretch-cursor) @@ -136,7 +136,7 @@ repositories are displayed." "Show the status for the repository at point." (interactive) (--if-let (tabulated-list-get-id) - (magit-status-internal (expand-file-name it)) + (magit-status-setup-buffer (expand-file-name it)) (user-error "There is no repository at point"))) (define-derived-mode magit-repolist-mode tabulated-list-mode "Repos" @@ -213,7 +213,7 @@ Only one letter is shown, the first that applies." (defun magit-repolist-column-unpulled-from-upstream (_id) "Insert number of upstream commits not in the current branch." - (--when-let (magit-get-upstream-branch nil t) + (--when-let (magit-get-upstream-branch) (let ((n (cadr (magit-rev-diff-count "HEAD" it)))) (propertize (number-to-string n) 'face (if (> n 0) 'bold 'shadow))))) @@ -225,7 +225,7 @@ Only one letter is shown, the first that applies." (defun magit-repolist-column-unpushed-to-upstream (_id) "Insert number of commits in the current branch but not its upstream." - (--when-let (magit-get-upstream-branch nil t) + (--when-let (magit-get-upstream-branch) (let ((n (car (magit-rev-diff-count "HEAD" it)))) (propertize (number-to-string n) 'face (if (> n 0) 'bold 'shadow))))) @@ -263,11 +263,7 @@ then read an arbitrary directory using `read-directory-name' instead." (if-let ((repos (and (not read-directory-name) magit-repository-directories - (magit-list-repos-uniquify - (--map (cons (file-name-nondirectory - (directory-file-name it)) - it) - (magit-list-repos)))))) + (magit-repos-alist)))) (let ((reply (magit-completing-read "Git repository" repos))) (file-name-as-directory (or (cdr (assoc reply repos)) @@ -285,7 +281,7 @@ instead." (defun magit-list-repos-1 (directory depth) (cond ((file-readable-p (expand-file-name ".git" directory)) - (list directory)) + (list (file-name-as-directory directory))) ((and (> depth 0) (magit-file-accessible-directory-p directory)) (--mapcat (and (file-directory-p it) (magit-list-repos-1 it (1- depth))) @@ -313,6 +309,11 @@ instead." dict) result)) +(defun magit-repos-alist () + (magit-list-repos-uniquify + (--map (cons (file-name-nondirectory (directory-file-name it)) it) + (magit-list-repos)))) + ;;; _ (provide 'magit-repos) ;;; magit-repos.el ends here diff --git a/elpa/magit-20190122.503/magit-reset.el b/elpa/magit-20190514.1814/magit-reset.el similarity index 83% rename from elpa/magit-20190122.503/magit-reset.el rename to elpa/magit-20190514.1814/magit-reset.el index 063c86c6..6a24ba15 100644 --- a/elpa/magit-20190122.503/magit-reset.el +++ b/elpa/magit-20190514.1814/magit-reset.el @@ -29,18 +29,18 @@ (require 'magit) -;;;###autoload (autoload 'magit-reset-popup "magit" nil t) -(magit-define-popup magit-reset-popup - "Popup console for reset commands." +;;;###autoload (autoload 'magit-reset "magit" nil t) +(define-transient-command magit-reset () + "Reset the `HEAD', index and/or worktree to a previous state." :man-page "git-reset" - :actions '((?m "reset mixed (HEAD and index)" magit-reset-mixed) - (?s "reset soft (HEAD only)" magit-reset-soft) - (?h "reset hard (HEAD, index, and files)" magit-reset-hard) - (?i "reset index (only)" magit-reset-index) - (?w "reset worktree (only)" magit-reset-worktree) - nil - (?f "reset a file" magit-file-checkout)) - :max-action-columns 1) + ["Reset" + ("m" "mixed (HEAD and index)" magit-reset-mixed) + ("s" "soft (HEAD only)" magit-reset-soft) + ("h" "hard (HEAD, index and files)" magit-reset-hard) + ("i" "index (only)" magit-reset-index) + ("w" "worktree (only)" magit-reset-worktree) + ?\n + ("f" "a file" magit-file-checkout)]) ;;;###autoload (defun magit-reset-mixed (commit) @@ -79,10 +79,11 @@ head this effectively unstages all changes. "Reset the worktree to COMMIT. Keep the `HEAD' and index as-is." (interactive (list (magit-read-branch-or-commit "Reset worktree to"))) + (magit-wip-commit-before-change nil " before reset") (magit-with-temp-index commit nil - (magit-wip-commit-before-change nil " before reset") - (magit-run-git "checkout-index" "--all" "--force") - (magit-wip-commit-after-apply nil " after reset"))) + (magit-call-git "checkout-index" "--all" "--force")) + (magit-wip-commit-after-apply nil " after reset") + (magit-refresh)) ;;;###autoload (defun magit-reset-quickly (commit &optional hard) diff --git a/elpa/magit-20190122.503/magit-section.el b/elpa/magit-20190514.1814/magit-section.el similarity index 99% rename from elpa/magit-20190122.503/magit-section.el rename to elpa/magit-20190514.1814/magit-section.el index 11c34acb..f5491319 100644 --- a/elpa/magit-20190122.503/magit-section.el +++ b/elpa/magit-20190514.1814/magit-section.el @@ -171,10 +171,13 @@ Otherwise the value has to have one of these two forms: (EXPANDABLE-BITMAP . COLLAPSIBLE-BITMAP) - Both values have to by variables whose values are fringe + Both values have to be variables whose values are fringe bitmaps. In this case every section that can be expanded or collapsed gets an indicator in the left fringe. + To provide extra padding around the indicator, set + `left-fringe-width' in `magit-mode-hook'. + (STRING . BOOLEAN) In this case STRING (usually an ellipsis) is shown at the end @@ -258,7 +261,12 @@ Otherwise the value has to have one of these two forms: (header :initform nil))) (defclass magit-hunk-section (magit-section) - ((refined :initform nil))) + ((refined :initform nil) + (combined :initform nil) + (from-range :initform nil) + (from-ranges :initform nil) + (to-range :initform nil) + (about :initform nil))) (defclass magit-module-section (magit-file-section) ()) diff --git a/elpa/magit-20190122.503/magit-sequence.el b/elpa/magit-20190514.1814/magit-sequence.el similarity index 73% rename from elpa/magit-20190122.503/magit-sequence.el rename to elpa/magit-20190514.1814/magit-sequence.el index 82938457..25c7f6f7 100644 --- a/elpa/magit-20190122.503/magit-sequence.el +++ b/elpa/magit-20190514.1814/magit-sequence.el @@ -34,6 +34,14 @@ (require 'magit) +;; For `magit-rebase--todo'. +(declare-function git-rebase-current-line "git-rebase" ()) +(eval-when-compile + (cl-pushnew 'action-type eieio--known-slot-names) + (cl-pushnew 'action eieio--known-slot-names) + (cl-pushnew 'action-options eieio--known-slot-names) + (cl-pushnew 'target eieio--known-slot-names)) + ;;; Options ;;;; Faces @@ -122,34 +130,47 @@ This discards all changes made since the sequence started." (defvar magit-perl-executable "perl" "The Perl executable.") -;;;###autoload (autoload 'magit-cherry-pick-popup "magit-sequence" nil t) -(magit-define-popup magit-cherry-pick-popup - "Popup console for cherry-pick commands." +;;;###autoload (autoload 'magit-cherry-pick "magit-sequence" nil t) +(define-transient-command magit-cherry-pick () + "Apply or transplant commits." :man-page "git-cherry-pick" - :switches '((?s "Add Signed-off-by lines" "--signoff") - (?e "Edit commit messages" "--edit") - (?x "Reference cherry in commit message" "-x") - (?F "Attempt fast-forward" "--ff")) - :options '((?s "Strategy" "--strategy=") - (?m "Replay merge relative to parent" "--mainline=")) - :actions '("Apply here" - (?A "Pick" magit-cherry-copy) - (?a "Apply" magit-cherry-apply) - (?h "Harvest" magit-cherry-harvest) - "Apply elsewhere" - (?d "Donate" magit-cherry-donate) - (?n "Spinout" magit-cherry-spinout) - (?s "Spinoff" magit-cherry-spinoff)) - :sequence-actions '((?A "Continue" magit-sequencer-continue) - (?s "Skip" magit-sequencer-skip) - (?a "Abort" magit-sequencer-abort)) - :sequence-predicate 'magit-sequencer-in-progress-p - :default-arguments '("--ff")) + :value '("--ff") + :incompatible '(("--ff" "-x")) + ["Arguments" + :if-not magit-sequencer-in-progress-p + (magit-cherry-pick:--mainline) + ("=s" magit-merge:--strategy) + ("-F" "Attempt fast-forward" "--ff") + ("-x" "Reference cherry in commit message" "-x") + ("-e" "Edit commit messages" ("-e" "--edit")) + ("-s" "Add Signed-off-by lines" ("-s" "--signoff")) + (5 magit:--gpg-sign)] + [:if-not magit-sequencer-in-progress-p + ["Apply here" + ("A" "Pick" magit-cherry-copy) + ("a" "Apply" magit-cherry-apply) + ("h" "Harvest" magit-cherry-harvest)] + ["Apply elsewhere" + ("d" "Donate" magit-cherry-donate) + ("n" "Spinout" magit-cherry-spinout) + ("s" "Spinoff" magit-cherry-spinoff)]] + ["Actions" + :if magit-sequencer-in-progress-p + ("A" "Continue" magit-sequencer-continue) + ("s" "Skip" magit-sequencer-skip) + ("a" "Abort" magit-sequencer-abort)]) + +(define-infix-argument magit-cherry-pick:--mainline () + :description "Replay merge relative to parent" + :class 'transient-option + :shortarg "-m" + :argument "--mainline=" + :reader 'transient-read-number-N+) (defun magit-cherry-pick-read-args (prompt) (list (or (nreverse (magit-region-values 'commit)) (magit-read-other-branch-or-commit prompt)) - (magit-cherry-pick-arguments))) + (transient-args 'magit-cherry-pick))) (defun magit--cherry-move-read-args (verb away fn) (declare (indent defun)) @@ -168,13 +189,14 @@ This discards all changes made since the sequence started." (`(t nil) (user-error msg verb "are not")))) `(,commits ,@(funcall fn commits) - ,(magit-cherry-pick-arguments)))) + ,(transient-args 'magit-cherry-pick)))) (defun magit--cherry-spinoff-read-args (verb) (magit--cherry-move-read-args verb t (lambda (commits) - (butlast (magit-branch-read-args - (format "Create branch from %s cherries" commits)))))) + (magit-branch-read-args + (format "Create branch from %s cherries" (length commits)) + (magit-get-upstream-branch))))) ;;;###autoload (defun magit-cherry-copy (commits &optional args) @@ -328,28 +350,33 @@ the process manually." ;;; Revert -;;;###autoload (autoload 'magit-revert-popup "magit-sequence" nil t) -(magit-define-popup magit-revert-popup - "Popup console for revert commands." +;;;###autoload (autoload 'magit-revert "magit-sequence" nil t) +(define-transient-command magit-revert () + "Revert existing commits, with or without creating new commits." :man-page "git-revert" - :switches '((?s "Add Signed-off-by lines" "--signoff") - (?e "Edit commit message" "--edit") - (?E "Don't edit commit message" "--no-edit")) - :options '((?s "Strategy" "--strategy=") - (?S "Sign using gpg" "--gpg-sign=" magit-read-gpg-secret-key) - (?m "Replay merge relative to parent" "--mainline=")) - :actions '((?V "Revert commit(s)" magit-revert-and-commit) - (?v "Revert changes" magit-revert-no-commit)) - :sequence-actions '((?V "Continue" magit-sequencer-continue) - (?s "Skip" magit-sequencer-skip) - (?a "Abort" magit-sequencer-abort)) - :sequence-predicate 'magit-sequencer-in-progress-p - :default-arguments '("--edit")) + :value '("--edit") + ["Arguments" + :if-not magit-sequencer-in-progress-p + (magit-cherry-pick:--mainline) + ("-e" "Edit commit message" ("-e" "--edit")) + ("-E" "Don't edit commit message" "--no-edit") + ("=s" magit-merge:--strategy) + ("-s" "Add Signed-off-by lines" ("-s" "--signoff")) + (5 magit:--gpg-sign)] + ["Actions" + :if-not magit-sequencer-in-progress-p + ("V" "Revert commit(s)" magit-revert-and-commit) + ("v" "Revert changes" magit-revert-no-commit)] + ["Actions" + :if magit-sequencer-in-progress-p + ("V" "Continue" magit-sequencer-continue) + ("s" "Skip" magit-sequencer-skip) + ("a" "Abort" magit-sequencer-abort)]) (defun magit-revert-read-args (prompt) (list (or (magit-region-values 'commit) (magit-read-branch-or-commit prompt)) - (magit-revert-arguments))) + (transient-args 'magit-revert))) ;;;###autoload (defun magit-revert-and-commit (commit &optional args) @@ -375,30 +402,41 @@ without prompting." ;;; Patch -;;;###autoload (autoload 'magit-am-popup "magit-sequence" nil t) -(magit-define-popup magit-am-popup - "Popup console for mailbox commands." +;;;###autoload (autoload 'magit-am "magit-sequence" nil t) +(define-transient-command magit-am () + "Apply patches received by email." :man-page "git-am" - :switches '((?3 "Fall back on 3way merge" "--3way") - (?s "Add Signed-off-by lines" "--signoff") - (?c "Remove text before scissors line" "--scissors") - (?k "Inhibit removal of email cruft" "--keep") - (?b "Limit removal of email cruft" "--keep-non-patch") - (?d "Use author date as committer date" - "--committer-date-is-author-date") - (?D "Use committer date as author date" "--ignore-date")) - :options '((?p "Remove leading slashes from paths" "-p" - magit-read-number-string)) - :actions '((?m "Apply maildir" magit-am-apply-maildir) - (?w "Apply patches" magit-am-apply-patches) - (?a "Apply plain patch" magit-patch-apply-popup)) - :default-arguments '("--3way") - :default-actions 'magit-am-apply-patches - :max-action-columns 1 - :sequence-actions '((?w "Continue" magit-am-continue) - (?s "Skip" magit-am-skip) - (?a "Abort" magit-am-abort)) - :sequence-predicate 'magit-am-in-progress-p) + :value '("--3way") + ["Arguments" + :if-not magit-am-in-progress-p + ("-3" "Fall back on 3way merge" ("-3" "--3way")) + (magit-apply:-p) + ("-c" "Remove text before scissors line" ("-c" "--scissors")) + ("-k" "Inhibit removal of email cruft" ("-k" "--keep")) + ("-b" "Limit removal of email cruft" "--keep-non-patch") + ("-d" "Use author date as committer date" "--committer-date-is-author-date") + ("-D" "Use committer date as author date" "--ignore-date") + ("-s" "Add Signed-off-by lines" ("-s" "--signoff")) + (5 magit:--gpg-sign)] + ["Apply" + :if-not magit-am-in-progress-p + ("m" "maildir" magit-am-apply-maildir) + ("w" "patches" magit-am-apply-patches) + ("a" "plain patch" magit-patch-apply)] + ["Actions" + :if magit-am-in-progress-p + ("w" "Continue" magit-am-continue) + ("s" "Skip" magit-am-skip) + ("a" "Abort" magit-am-abort)]) + +(defun magit-am-arguments () + (transient-args 'magit-am)) + +(define-infix-argument magit-apply:-p () + :description "Remove leading slashes from paths" + :class 'transient-option + :argument "-p" + :reader 'transient-read-number-N+) ;;;###autoload (defun magit-am-apply-patches (&optional files args) @@ -456,68 +494,106 @@ This discards all changes made since the sequence started." ;;; Rebase -;;;###autoload (autoload 'magit-rebase-popup "magit-sequence" nil t) -(magit-define-popup magit-rebase-popup - "Key menu for rebasing." +;;;###autoload (autoload 'magit-rebase "magit-sequence" nil t) +(define-transient-command magit-rebase () + "Transplant commits and/or modify existing commits." :man-page "git-rebase" - :switches '((?k "Keep empty commits" "--keep-empty") - (?p "Preserve merges" "--preserve-merges") - (?c "Lie about committer date" "--committer-date-is-author-date") - (?a "Autosquash" "--autosquash") - (?A "Autostash" "--autostash") - (?i "Interactive" "--interactive") - (?h "Disable hooks" "--no-verify")) - :actions '((lambda () - (concat (propertize "Rebase " 'face 'magit-popup-heading) - (propertize (or (magit-get-current-branch) "HEAD") - 'face 'magit-branch-local) - (propertize " onto" 'face 'magit-popup-heading))) - (?p (lambda () - (--when-let (magit-get-push-branch) (concat it "\n"))) - magit-rebase-onto-pushremote) - (?u (lambda () - (--when-let (magit-get-upstream-branch) (concat it "\n"))) - magit-rebase-onto-upstream) - (?e "elsewhere" magit-rebase-branch) - "Rebase" - (?i "interactively" magit-rebase-interactive) - (?m "to modify a commit" magit-rebase-edit-commit) - (?s "a subset" magit-rebase-subset) - (?w "to reword a commit" magit-rebase-reword-commit) nil - (?k "to remove a commit" magit-rebase-remove-commit) nil - (?f "to autosquash" magit-rebase-autosquash)) - :sequence-actions '((?r "Continue" magit-rebase-continue) - (?s "Skip" magit-rebase-skip) - (?e "Edit" magit-rebase-edit) - (?a "Abort" magit-rebase-abort)) - :sequence-predicate 'magit-rebase-in-progress-p - :max-action-columns 2) + ["Arguments" + :if-not magit-rebase-in-progress-p + ("-k" "Keep empty commits" "--keep-empty") + ("-p" "Preserve merges" ("-p" "--preserve-merges")) + ("-d" "Lie about committer date" "--committer-date-is-author-date") + ("-a" "Autosquash" "--autosquash") + ("-A" "Autostash" "--autostash") + ("-i" "Interactive" ("-i" "--interactive")) + ("-h" "Disable hooks" "--no-verify") + (5 magit:--gpg-sign) + (5 "-r" "Rebase merges" "--rebase-merges=" magit-rebase-merges-select-mode)] + [:if-not magit-rebase-in-progress-p + :description (lambda () + (format (propertize "Rebase %s onto" 'face 'transient-heading) + (propertize (or (magit-get-current-branch) "HEAD") + 'face 'magit-branch-local))) + ("p" magit-rebase-onto-pushremote) + ("u" magit-rebase-onto-upstream) + ("e" "elsewhere" magit-rebase-branch)] + ["Rebase" + :if-not magit-rebase-in-progress-p + [("i" "interactively" magit-rebase-interactive) + ("s" "a subset" magit-rebase-subset)] + [("m" "to modify a commit" magit-rebase-edit-commit) + ("w" "to reword a commit" magit-rebase-reword-commit) + ("k" "to remove a commit" magit-rebase-remove-commit) + ("f" "to autosquash" magit-rebase-autosquash) + (6 "t" "to change dates" magit-reshelve-since)]] + ["Actions" + :if magit-rebase-in-progress-p + ("r" "Continue" magit-rebase-continue) + ("s" "Skip" magit-rebase-skip) + ("e" "Edit" magit-rebase-edit) + ("a" "Abort" magit-rebase-abort)]) + +(defun magit-rebase-merges-select-mode (&rest _ignore) + (magit-read-char-case nil t + (?n "[n]o-rebase-cousins" "no-rebase-cousins") + (?r "[r]ebase-cousins" "rebase-cousins"))) + +(defun magit-rebase-arguments () + (transient-args 'magit-rebase)) (defun magit-git-rebase (target args) - (magit-run-git-sequencer "rebase" target args)) - -;;;###autoload -(defun magit-rebase-onto-pushremote (args) - "Rebase the current branch onto `branch..pushRemote'. -If that variable is unset, then rebase onto `remote.pushDefault'." + (magit-run-git-sequencer "rebase" args target)) + +;;;###autoload (autoload 'magit-rebase-onto-pushremote "magit-sequence" nil t) +(define-suffix-command magit-rebase-onto-pushremote (args) + "Rebase the current branch onto its push-remote branch. + +When the push-remote is not configured, then read the push-remote +from the user, set it, and then rebase onto it. With a prefix +argument the push-remote can be changed before rebasing onto to +it." + :if 'magit-get-current-branch + :description 'magit-pull--pushbranch-description (interactive (list (magit-rebase-arguments))) - (--if-let (magit-get-current-branch) - (if-let ((remote (magit-get-push-remote it))) - (if (member remote (magit-list-remotes)) - (magit-git-rebase (concat remote "/" it) args) - (user-error "Remote `%s' doesn't exist" remote)) - (user-error "No push-remote is configured for %s" it)) - (user-error "No branch is checked out"))) - -;;;###autoload -(defun magit-rebase-onto-upstream (args) - "Rebase the current branch onto its upstream branch." + (pcase-let ((`(,branch ,remote) + (magit--select-push-remote "rebase onto that"))) + (magit-git-rebase (concat remote "/" branch) args))) + +;;;###autoload (autoload 'magit-rebase-onto-upstream "magit-sequence" nil t) +(define-suffix-command magit-rebase-onto-upstream (args) + "Rebase the current branch onto its upstream branch. + +With a prefix argument or when the upstream is either not +configured or unusable, then let the user first configure +the upstream." + :if 'magit-get-current-branch + :description 'magit-rebase--upstream-description (interactive (list (magit-rebase-arguments))) - (--if-let (magit-get-current-branch) - (if-let ((target (magit-get-upstream-branch it))) - (magit-git-rebase target args) - (user-error "No upstream is configured for %s" it)) - (user-error "No branch is checked out"))) + (let* ((branch (or (magit-get-current-branch) + (user-error "No branch is checked out"))) + (upstream (magit-get-upstream-branch branch))) + (when (or current-prefix-arg (not upstream)) + (setq upstream + (magit-read-upstream-branch + branch (format "Set upstream of %s and rebase onto that" branch))) + (magit-set-upstream-branch branch upstream)) + (magit-git-rebase upstream args))) + +(defun magit-rebase--upstream-description () + (when-let ((branch (magit-get-current-branch))) + (or (magit-get-upstream-branch branch) + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge")) + (u (propertize "@{upstream}" 'face 'bold))) + (cond + ((magit--unnamed-upstream-p remote merge) + (concat u ", replacing unnamed")) + ((magit--valid-upstream-p remote merge) + (concat u ", replacing non-existent")) + ((or remote merge) + (concat u ", replacing invalid")) + (t + (concat u ", setting that"))))))) ;;;###autoload (defun magit-rebase-branch (target args) @@ -564,11 +640,17 @@ START has to be selected from a list of recent commits." (setq commit (concat commit "^")) (setq args (cons "--root" args))))) (when (and commit (not noassert)) - (setq commit (magit-rebase-interactive-assert commit delay-edit-confirm))) + (setq commit (magit-rebase-interactive-assert + commit delay-edit-confirm + (--some (string-prefix-p "--rebase-merges" it) args)))) (if (and commit (not confirm)) (let ((process-environment process-environment)) (when editor - (push (concat "GIT_SEQUENCE_EDITOR=" editor) process-environment)) + (push (concat "GIT_SEQUENCE_EDITOR=" + (if (functionp editor) + (funcall editor commit) + editor)) + process-environment)) (magit-run-git-sequencer "rebase" "-i" args (unless (member "--root" args) commit))) (magit-log-select @@ -580,14 +662,9 @@ START has to be selected from a list of recent commits." (defvar magit--rebase-published-symbol nil) (defvar magit--rebase-public-edit-confirmed nil) -(defun magit-rebase-interactive-assert (since &optional delay-edit-confirm) - (let* ((commit (if (string-suffix-p "^" since) - ;; If SINCE is "REV^", then the user selected - ;; "REV", which is the first commit that will - ;; be replaced. (from^..to] <=> [from..to]. - (substring since 0 -1) - ;; The "--root" argument is being used. - since)) +(defun magit-rebase-interactive-assert + (since &optional delay-edit-confirm rebase-merges) + (let* ((commit (magit-rebase--target-commit since)) (branches (magit-list-publishing-branches commit))) (setq magit--rebase-public-edit-confirmed (delete (magit-toplevel) magit--rebase-public-edit-confirmed)) @@ -605,13 +682,23 @@ START has to be selected from a list of recent commits." (concat m1 "%i public branches" m2) nil branches)) (push (magit-toplevel) magit--rebase-public-edit-confirmed))) - (if (magit-git-lines "rev-list" "--merges" (concat since "..HEAD")) + (if (and (magit-git-lines "rev-list" "--merges" (concat since "..HEAD")) + (not rebase-merges)) (magit-read-char-case "Proceed despite merge in rebase range? " nil (?c "[c]ontinue" since) (?s "[s]elect other" nil) (?a "[a]bort" (user-error "Quit"))) since)) +(defun magit-rebase--target-commit (since) + (if (string-suffix-p "^" since) + ;; If SINCE is "REV^", then the user selected + ;; "REV", which is the first commit that will + ;; be replaced. (from^..to] <=> [from..to] + (substring since 0 -1) + ;; The "--root" argument is being used. + since)) + ;;;###autoload (defun magit-rebase-interactive (commit args) "Start an interactive rebase sequence." @@ -637,8 +724,7 @@ START has to be selected from a list of recent commits." (magit-rebase-arguments))) (magit-rebase-interactive-1 commit args "Type %p on a commit to edit it," - (concat magit-perl-executable - " -i -p -e '++$x if not $x and s/^pick/edit/'") + (apply-partially #'magit-rebase--perl-editor 'edit) t)) ;;;###autoload @@ -648,8 +734,7 @@ START has to be selected from a list of recent commits." (magit-rebase-arguments))) (magit-rebase-interactive-1 commit args "Type %p on a commit to reword its message," - (concat magit-perl-executable - " -i -p -e '++$x if not $x and s/^pick/reword/'"))) + (apply-partially #'magit-rebase--perl-editor 'reword))) ;;;###autoload (defun magit-rebase-remove-commit (commit args) @@ -658,10 +743,21 @@ START has to be selected from a list of recent commits." (magit-rebase-arguments))) (magit-rebase-interactive-1 commit args "Type %p on a commit to remove it," - (concat magit-perl-executable - " -i -p -e '++$x if not $x and s/^pick/# pick/'") + (apply-partially #'magit-rebase--perl-editor 'remove) nil nil t)) +(defun magit-rebase--perl-editor (action since) + (let ((commit (magit-rev-abbrev (magit-rebase--target-commit since)))) + (format "%s -i -p -e '++$x if not $x and s/^pick %s/%s %s/'" + magit-perl-executable + commit + (cl-case action + (edit "edit") + (remove "# pick") + (reword "reword") + (t (error "unknown action: %s" action))) + commit))) + ;;;###autoload (defun magit-rebase-continue (&optional noedit) "Restart the current rebasing operation. @@ -802,22 +898,40 @@ If no such sequence is in progress, do nothing." (magit-rebase-insert-apply-sequence onto)) (insert ?\n))))) +(defun magit-rebase--todo () + "Return `git-rebase-action' instances for remaining rebase actions. +These are ordered in that the same way they'll be sorted in the +status buffer (i.e. the reverse of how they will be applied)." + (let ((comment-start (or (magit-get "core.commentChar") "#")) + lines) + (with-temp-buffer + (insert-file-contents (magit-git-dir "rebase-merge/git-rebase-todo")) + (while (not (eobp)) + (let ((ln (git-rebase-current-line))) + (when (oref ln action-type) + (push ln lines))) + (forward-line))) + lines)) + (defun magit-rebase-insert-merge-sequence (onto) - (let (exec) - (dolist (line (nreverse - (magit-file-lines - (magit-git-dir "rebase-merge/git-rebase-todo")))) - (cond ((string-prefix-p "exec" line) - (setq exec (substring line 5))) - ((string-match (format "^\\([^%c ]+\\) \\([^ ]+\\) .*$" - (string-to-char - (or (magit-get "core.commentChar") "#"))) - line) - (magit-bind-match-strings (action hash) line - (unless (equal action "exec") - (magit-sequence-insert-commit - action hash 'magit-sequence-pick exec))) - (setq exec nil))))) + (dolist (line (magit-rebase--todo)) + (with-slots (action-type action action-options target) line + (pcase action-type + (`commit + (magit-sequence-insert-commit action target 'magit-sequence-pick)) + ((or (or `exec `label) + (and `merge (guard (not action-options)))) + (insert (propertize action 'face 'magit-sequence-onto) "\s" + (propertize target 'face 'git-rebase-label) "\n")) + (`merge + (if-let ((hash (and (string-match "-[cC] \\([^ ]+\\)" action-options) + (match-string 1 action-options)))) + (magit-insert-section (commit hash) + (magit-insert-heading + (propertize "merge" 'face 'magit-sequence-pick) + "\s" + (magit-format-rev-summary hash) "\n")) + (error "failed to parse merge message hash")))))) (magit-sequence-insert-sequence (magit-file-line (magit-git-dir "rebase-merge/stopped-sha")) onto @@ -845,7 +959,7 @@ If no such sequence is in progress, do nothing." (let ((head (magit-rev-parse "HEAD")) done) (setq onto (if onto (magit-rev-parse onto) head)) (setq done (magit-git-lines "log" "--format=%H" (concat onto "..HEAD"))) - (when (and stop (not (member stop done))) + (when (and stop (not (member (magit-rev-parse stop) done))) (let ((id (magit-patch-id stop))) (--if-let (--first (equal (magit-patch-id it) id) done) (setq stop it) @@ -903,13 +1017,11 @@ If no such sequence is in progress, do nothing." 'magit-sequence-head 'magit-sequence-onto)))) -(defun magit-sequence-insert-commit (type hash face &optional exec) - (magit-insert-section (commit hash) +(defun magit-sequence-insert-commit (type hash face) + (magit-insert-section (commit hash) (magit-insert-heading (propertize type 'face face) "\s" - (magit-format-rev-summary hash) "\n") - (when exec - (insert (propertize "exec" 'face 'magit-sequence-onto) "\s" exec "\n")))) + (magit-format-rev-summary hash) "\n"))) ;;; _ (provide 'magit-sequence) diff --git a/elpa/magit-20190122.503/magit-stash.el b/elpa/magit-20190514.1814/magit-stash.el similarity index 82% rename from elpa/magit-20190122.503/magit-stash.el rename to elpa/magit-20190514.1814/magit-stash.el index 3ad2cd26..21c202f1 100644 --- a/elpa/magit-20190122.503/magit-stash.el +++ b/elpa/magit-20190514.1814/magit-stash.el @@ -31,8 +31,7 @@ (require 'subr-x)) (require 'magit) - -(defvar bookmark-make-record-function) +(require 'magit-reflog) ;;; Options @@ -84,35 +83,42 @@ AUTHOR-WIDTH has to be an integer. When the name of the author ;;; Commands -;;;###autoload (autoload 'magit-stash-popup "magit-stash" nil t) -(magit-define-popup magit-stash-popup - "Popup console for stash commands." +;;;###autoload (autoload 'magit-stash "magit-stash" nil t) +(define-transient-command magit-stash () + "Stash uncommitted changes." :man-page "git-stash" - :switches '((?u "Also save untracked files" "--include-untracked") - (?a "Also save untracked and ignored files" "--all")) - :actions '((?z "Save" magit-stash-both) - (?Z "Snapshot" magit-snapshot-both) - (?p "Pop" magit-stash-pop) - (?i "Save index" magit-stash-index) - (?I "Snapshot index" magit-snapshot-index) - (?a "Apply" magit-stash-apply) - (?w "Save worktree" magit-stash-worktree) - (?W "Snapshot worktree" magit-snapshot-worktree) - (?l "List" magit-stash-list) - (?x "Save keeping index" magit-stash-keep-index) - (?r "Snapshot to wipref" magit-wip-commit) - (?v "Show" magit-stash-show) - (?b "Branch" magit-stash-branch) - (?k "Drop" magit-stash-drop) nil - (?B "Branch here" magit-stash-branch-here) nil nil - (?f "Format patch" magit-stash-format-patch)) - :default-action 'magit-stash - :max-action-columns 3) + ["Arguments" + ("-u" "Also save untracked files" ("-u" "--include-untracked")) + ("-a" "Also save untracked and ignored files" ("-a" "--all"))] + [["Stash" + ("z" "both" magit-stash-both) + ("i" "index" magit-stash-index) + ("w" "worktree" magit-stash-worktree) + ("x" "keeping index" magit-stash-keep-index)] + ["Snapshot" + ("Z" "both" magit-snapshot-both) + ("I" "index" magit-snapshot-index) + ("W" "worktree" magit-snapshot-worktree) + ("r" "to wip ref" magit-wip-commit)] + ["Use" + ("a" "Apply" magit-stash-apply) + ("p" "Pop" magit-stash-pop) + ("k" "Drop" magit-stash-drop)] + ["Inspect" + ("l" "List" magit-stash-list) + ("v" "Show" magit-stash-show)] + ["Transform" + ("b" "Branch" magit-stash-branch) + ("B" "Branch here" magit-stash-branch-here) + ("f" "Format patch" magit-stash-format-patch)]]) + +(defun magit-stash-arguments () + (transient-args 'magit-stash)) ;;;###autoload (defun magit-stash-both (message &optional include-untracked) "Create a stash of the index and working tree. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'." (interactive (magit-stash-read-args)) @@ -131,7 +137,7 @@ Applying the resulting stash has the inverse effect." ;;;###autoload (defun magit-stash-worktree (message &optional include-untracked) "Create a stash of unstaged changes in the working tree. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'." (interactive (magit-stash-read-args)) @@ -140,7 +146,7 @@ while two prefix arguments are equivalent to `--all'." ;;;###autoload (defun magit-stash-keep-index (message &optional include-untracked) "Create a stash of the index and working tree, keeping index intact. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'." (interactive (magit-stash-read-args)) @@ -167,7 +173,7 @@ while two prefix arguments are equivalent to `--all'." ;;;###autoload (defun magit-snapshot-both (&optional include-untracked) "Create a snapshot of the index and working tree. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'." (interactive (magit-snapshot-read-args)) @@ -183,7 +189,7 @@ Unstaged and untracked changes are not stashed." ;;;###autoload (defun magit-snapshot-worktree (&optional include-untracked) "Create a snapshot of unstaged changes in the working tree. -Untracked files are included according to popup arguments. +Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'." (interactive (magit-snapshot-read-args)) @@ -292,7 +298,7 @@ branch or `HEAD' as the string-point." (unless (eq keep t) (if (eq keep 'index) (magit-call-git "checkout" "--" ".") - (magit-call-git "reset" "--hard" "HEAD")) + (magit-call-git "reset" "--hard" "HEAD" "--")) (when untracked (magit-call-git "clean" "--force" "-d" (and (eq untracked 'all) "-x"))))) @@ -401,22 +407,27 @@ instead of \"Stashes:\"." (defun magit-stash-list () "List all stashes in a buffer." (interactive) - (magit-mode-setup #'magit-stashes-mode "refs/stash")) + (magit-stashes-setup-buffer)) (define-derived-mode magit-stashes-mode magit-reflog-mode "Magit Stashes" "Mode for looking at lists of stashes." :group 'magit-log - (hack-dir-local-variables-non-file-buffer) - (setq-local bookmark-make-record-function - #'magit-bookmark--stashes-make-record)) + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-stashes-setup-buffer () + (magit-setup-buffer #'magit-stashes-mode nil + (magit-buffer-refname "refs/stash"))) -(cl-defun magit-stashes-refresh-buffer (ref) +(defun magit-stashes-refresh-buffer () (magit-insert-section (stashesbuf) - (magit-insert-heading (if (equal ref "refs/stash") + (magit-insert-heading (if (equal magit-buffer-refname "refs/stash") "Stashes:" - (format "Stashes [%s]:" ref))) + (format "Stashes [%s]:" magit-buffer-refname))) (magit-git-wash (apply-partially 'magit-log-wash-log 'stash) - "reflog" "--format=%gd%x00%aN%x00%at%x00%gs" ref))) + "reflog" "--format=%gd%x00%aN%x00%at%x00%gs" magit-buffer-refname))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-stashes-mode)) + magit-buffer-refname) ;;; Show Stash @@ -426,33 +437,41 @@ instead of \"Stashes:\"." (interactive (cons (or (and (not current-prefix-arg) (magit-stash-at-point)) (magit-read-stash "Show stash")) - (pcase-let ((`(,args ,files) (magit-diff-arguments))) + (pcase-let ((`(,args ,files) + (magit-diff-arguments 'magit-stash-mode))) (list (delete "--stat" args) files)))) - (magit-mode-setup #'magit-stash-mode stash nil args files)) + (magit-stash-setup-buffer stash args files)) (define-derived-mode magit-stash-mode magit-diff-mode "Magit Stash" "Mode for looking at individual stashes." :group 'magit-diff - (hack-dir-local-variables-non-file-buffer) - (setq-local bookmark-make-record-function - #'magit-bookmark--stash-make-record)) + (hack-dir-local-variables-non-file-buffer)) -(defun magit-stash-refresh-buffer (stash _const _args _files) +(defun magit-stash-setup-buffer (stash args files) + (magit-setup-buffer #'magit-stash-mode nil + (magit-buffer-revision stash) + (magit-buffer-range (format "%s^..%s" stash stash)) + (magit-buffer-diff-args args) + (magit-buffer-diff-files files))) + +(defun magit-stash-refresh-buffer () (magit-set-header-line-format - (concat (propertize (capitalize stash) 'face 'magit-section-heading) - " " - (magit-rev-format "%s" stash))) - (setq magit-buffer-revision-hash (magit-rev-parse stash)) + (concat (capitalize magit-buffer-revision) " " + (propertize (magit-rev-format "%s" magit-buffer-revision) + 'face (list :weight 'normal :foreground + (face-attribute 'default :foreground))))) + (setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision)) (magit-insert-section (stash) (magit-run-section-hook 'magit-stash-sections-hook))) +(cl-defmethod magit-buffer-value (&context (major-mode magit-stash-mode)) + magit-buffer-revision) + (defun magit-stash-insert-section (commit range message &optional files) (magit-insert-section (commit commit) (magit-insert-heading message) - (magit-git-wash #'magit-diff-wash-diffs - "diff" range "-p" "--no-prefix" - (nth 2 magit-refresh-args) - "--" (or files (nth 3 magit-refresh-args))))) + (magit--insert-diff "diff" range "-p" "--no-prefix" magit-buffer-diff-args + "--" (or files magit-buffer-diff-files)))) (defun magit-insert-stash-notes () "Insert section showing notes for a stash. @@ -460,7 +479,7 @@ This shows the notes for stash@{N} but not for the other commits that make up the stash." (magit-insert-section section (note) (magit-insert-heading "Notes") - (magit-git-insert "notes" "show" (car magit-refresh-args)) + (magit-git-insert "notes" "show" magit-buffer-revision) (if (= (point) (oref section content)) (magit-cancel-section) @@ -468,22 +487,22 @@ that make up the stash." (defun magit-insert-stash-index () "Insert section showing staged changes of the stash." - (let ((stash (car magit-refresh-args))) - (magit-stash-insert-section (format "%s^2" stash) - (format "%s^..%s^2" stash stash) - "Staged"))) + (magit-stash-insert-section + (format "%s^2" magit-buffer-revision) + (format "%s^..%s^2" magit-buffer-revision magit-buffer-revision) + "Staged")) (defun magit-insert-stash-worktree () "Insert section showing unstaged changes of the stash." - (let ((stash (car magit-refresh-args))) - (magit-stash-insert-section stash - (format "%s^2..%s" stash stash) - "Unstaged"))) + (magit-stash-insert-section + magit-buffer-revision + (format "%s^2..%s" magit-buffer-revision magit-buffer-revision) + "Unstaged")) (defun magit-insert-stash-untracked () "Insert section showing the untracked files commit of the stash." - (let ((stash (car magit-refresh-args)) - (rev (concat (car magit-refresh-args) "^3"))) + (let ((stash magit-buffer-revision) + (rev (concat magit-buffer-revision "^3"))) (when (magit-rev-verify rev) (magit-stash-insert-section (format "%s^3" stash) (format "%s^..%s^3" stash stash) diff --git a/elpa/magit-20190122.503/magit-status.el b/elpa/magit-20190514.1814/magit-status.el similarity index 78% rename from elpa/magit-20190122.503/magit-status.el rename to elpa/magit-20190514.1814/magit-status.el index b6ff3895..9afa0fff 100644 --- a/elpa/magit-20190122.503/magit-status.el +++ b/elpa/magit-20190514.1814/magit-status.el @@ -32,8 +32,6 @@ (require 'magit) -(defvar bookmark-make-record-function) - ;;; Options (defgroup magit-status nil @@ -185,7 +183,7 @@ Non-interactively DIRECTORY is (re-)initialized unconditionally." ;; `git init' does not understand the meaning of "~"! (magit-call-git "init" (magit-convert-filename-for-git (expand-file-name directory))) - (magit-status-internal directory)) + (magit-status-setup-buffer directory)) ;;;###autoload (defun magit-status (&optional directory cache) @@ -232,7 +230,7 @@ prefix arguments: (setq directory (file-name-as-directory (expand-file-name directory))) (if (and toplevel (file-equal-p directory toplevel)) - (magit-status-internal directory) + (magit-status-setup-buffer directory) (when (y-or-n-p (if toplevel (format "%s is a repository. Create another in %s? " @@ -241,9 +239,9 @@ prefix arguments: ;; Creating a new repository invalidates cached values. (setq magit--refresh-cache nil) (magit-init directory)))) - (magit-status-internal default-directory)))) + (magit-status-setup-buffer default-directory)))) -(put 'magit-status 'interactive-only 'magit-status-internal) +(put 'magit-status 'interactive-only 'magit-status-setup-buffer) (defalias 'magit 'magit-status "An alias for `magit-status' for better discoverability. @@ -253,12 +251,6 @@ Instead of invoking this alias for `magit-status' using and read the info node `(magit)Getting Started', which also contains other useful hints.") -;;;###autoload -(defun magit-status-internal (directory) - (magit--tramp-asserts directory) - (let ((default-directory directory)) - (magit-mode-setup #'magit-status-mode))) - (defvar magit--remotes-using-recent-git nil) (defun magit--tramp-asserts (directory) @@ -322,7 +314,7 @@ Type \\[magit-refresh] to refresh the current buffer. Type \\[magit-section-toggle] to expand or hide the section at point. Type \\[magit-visit-thing] to visit the change or commit at point. -Type \\[magit-dispatch-popup] to see available prefix popups. +Type \\[magit-dispatch] to invoke major commands. Staging and applying changes is documented in info node `(magit)Staging and Unstaging' and info node `(magit)Applying'. @@ -335,15 +327,32 @@ Staging and applying changes is documented in info node \\[magit-reverse] to reverse it. \\\ -Type \\[magit-commit-popup] to create a commit. +Type \\[magit-commit] to create a commit. \\{magit-status-mode-map}" :group 'magit-status (hack-dir-local-variables-non-file-buffer) (setq imenu-create-index-function - 'magit-imenu--status-create-index-function) - (setq-local bookmark-make-record-function - #'magit-bookmark--status-make-record)) + 'magit-imenu--status-create-index-function)) + +(put 'magit-status-mode 'magit-diff-default-arguments + '("--no-ext-diff")) +(put 'magit-status-mode 'magit-log-default-arguments + '("-n256" "--decorate")) + +;;;###autoload +(defun magit-status-setup-buffer (&optional directory) + (unless directory + (setq directory default-directory)) + (magit--tramp-asserts directory) + (let* ((default-directory directory) + (d (magit-diff--get-value 'magit-status-mode)) + (l (magit-log--get-value 'magit-status-mode))) + (magit-setup-buffer #'magit-status-mode nil + (magit-buffer-diff-args (nth 0 d)) + (magit-buffer-diff-files (nth 1 d)) + (magit-buffer-log-args (nth 0 l)) + (magit-buffer-log-files (nth 1 l))))) (defun magit-status-refresh-buffer () (magit-git-exit-code "update-index" "--refresh") @@ -430,27 +439,29 @@ the status buffer causes this section to disappear again." "Insert a header line showing the effective diff filters." (let ((ignore-modules (magit-ignore-submodules-p))) (when (or ignore-modules - magit-diff-section-file-args) + magit-buffer-diff-files) (insert (propertize (format "%-10s" "Filter! ") 'face 'magit-section-heading)) (when ignore-modules (insert ignore-modules) - (when magit-diff-section-file-args + (when magit-buffer-diff-files (insert " -- "))) - (when magit-diff-section-file-args - (insert (mapconcat #'identity magit-diff-section-file-args " "))) + (when magit-buffer-diff-files + (insert (mapconcat #'identity magit-buffer-diff-files " "))) (insert ?\n)))) ;;;; Reference Headers -(cl-defun magit-insert-head-branch-header - (&optional (branch (magit-get-current-branch))) - "Insert a header line about BRANCH. -When BRANCH is nil, use the current branch or, if none, the -detached `HEAD'." - (let ((output (magit-rev-format "%h %s" (or branch "HEAD")))) +(defun magit-insert-head-branch-header (&optional branch) + "Insert a header line about the current branch. +If `HEAD' is detached, then insert information about that commit +instead. The optional BRANCH argument is for internal use only." + (let ((branch (or branch (magit-get-current-branch))) + (output (magit-rev-format "%h %s" (or branch "HEAD")))) (string-match "^\\([^ ]+\\) \\(.*\\)" output) (magit-bind-match-strings (commit summary) output + (when (equal summary "") + (setq summary "(no commit message)")) (if branch (magit-insert-section (branch branch) (insert (format "%-10s" "Head: ")) @@ -463,50 +474,83 @@ detached `HEAD'." (magit-insert-section (commit commit) (insert (format "%-10s" "Head: ")) (insert (propertize commit 'face 'magit-hash)) - (insert ?\s summary ?\n)))))) - -(cl-defun magit-insert-upstream-branch-header - (&optional (branch (magit-get-current-branch)) - (pull (magit-get-upstream-branch branch)) - keyword) - "Insert a header line about branch usually pulled into current branch." - (when pull - (magit-insert-section (branch pull) - (let ((rebase (magit-get "branch" branch "rebase"))) - (pcase rebase - ("true") - ("false" (setq rebase nil)) - (_ (setq rebase (magit-get-boolean "pull.rebase")))) - (insert (format "%-10s" (or keyword (if rebase "Rebase: " "Merge: "))))) - (--when-let (and magit-status-show-hashes-in-headers - (not (string-match-p " " pull)) - (magit-rev-format "%h" pull)) - (insert (propertize it 'face 'magit-hash) " ")) - (if (string-match-p " " pull) - (pcase-let ((`(,url ,branch) (split-string pull " "))) - (insert branch " from " url " ")) - (insert pull " ") - (--if-let (and (magit-rev-verify pull) - (magit-rev-format "%s" pull)) - (insert (funcall magit-log-format-message-function pull it)) - (insert (propertize "is missing" 'face 'font-lock-warning-face)))) - (insert ?\n)))) - -(cl-defun magit-insert-push-branch-header - (&optional (branch (magit-get-current-branch)) - (push (magit-get-push-branch branch))) + (insert ?\s) + (insert (funcall magit-log-format-message-function nil summary)) + (insert ?\n)))))) + +(defun magit-insert-upstream-branch-header (&optional branch upstream keyword) + "Insert a header line about the upstream of the current branch. +If no branch is checked out, then insert nothing. The optional +arguments are for internal use only." + (when-let ((branch (or branch (magit-get-current-branch)))) + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge")) + (rebase (magit-get "branch" branch "rebase"))) + (when (or remote merge) + (unless upstream + (setq upstream (magit-get-upstream-branch branch))) + (magit-insert-section (branch upstream) + (pcase rebase + ("true") + ("false" (setq rebase nil)) + (_ (setq rebase (magit-get-boolean "pull.rebase")))) + (insert (format "%-10s" (or keyword (if rebase "Rebase: " "Merge: ")))) + (insert + (if upstream + (concat (and magit-status-show-hashes-in-headers + (concat (propertize (magit-rev-format "%h" upstream) + 'face 'magit-hash) + " ")) + upstream " " + (funcall magit-log-format-message-function upstream + (funcall magit-log-format-message-function nil + (or (magit-rev-format "%s" upstream) + "(no commit message)")))) + (cond + ((magit--unnamed-upstream-p remote merge) + (concat (propertize merge 'face 'magit-branch-remote) " from " + (propertize remote 'face 'bold))) + ((magit--valid-upstream-p remote merge) + (if (equal remote ".") + (concat + (propertize merge 'face 'magit-branch-local) + (propertize " does not exist" + 'face 'font-lock-warning-face)) + (concat + (propertize merge 'face 'magit-branch-remote) + (propertize " does not exist on " + 'face 'font-lock-warning-face) + (propertize remote 'face 'magit-branch-remote)))) + (t + (propertize "invalid upstream configuration" + 'face 'font-lock-warning-face))))) + (insert ?\n)))))) + +(defun magit-insert-push-branch-header () "Insert a header line about the branch the current branch is pushed to." - (when push - (magit-insert-section (branch push) + (when-let ((branch (magit-get-current-branch)) + (target (magit-get-push-branch branch))) + (magit-insert-section (branch target) (insert (format "%-10s" "Push: ")) - (--when-let (and magit-status-show-hashes-in-headers - (magit-rev-format "%h" push)) - (insert (propertize it 'face 'magit-hash) ?\s)) - (insert (propertize push 'face 'magit-branch-remote) ?\s) - (--if-let (and (magit-rev-verify push) - (magit-rev-format "%s" push)) - (insert (funcall magit-log-format-message-function push it)) - (insert (propertize "is missing" 'face 'font-lock-warning-face))) + (insert + (if (magit-rev-verify target) + (concat target " " + (and magit-status-show-hashes-in-headers + (concat (propertize (magit-rev-format "%h" target) + 'face 'magit-hash) + " ")) + (funcall magit-log-format-message-function target + (funcall magit-log-format-message-function nil + (or (magit-rev-format "%s" target) + "(no commit message)")))) + (let ((remote (magit-get-push-remote branch))) + (if (magit-remote-p remote) + (concat target + (propertize " does not exist" + 'face 'font-lock-warning-face)) + (concat remote + (propertize " remote does not exist" + 'face 'font-lock-warning-face)))))) (insert ?\n)))) (defun magit-insert-tags-header () @@ -585,11 +629,11 @@ Note that even if the value is `all', Magit still initially only shows directories. But the directory sections can then be expanded using \"TAB\". -If the first element of `magit-diff-section-arguments' is a +If the first element of `magit-buffer-diff-files' is a directory, then limit the list to files below that. The value -value of that variable can be set using \"D = f DIRECTORY RET g\"." +value of that variable can be set using \"D -- DIRECTORY RET g\"." (let* ((show (or (magit-get "status.showUntrackedFiles") "normal")) - (base (car magit-diff-section-file-args)) + (base (car magit-buffer-diff-files)) (base (and base (file-directory-p base) base))) (unless (equal show "no") (if (equal show "all") @@ -616,11 +660,11 @@ value of that variable can be set using \"D = f DIRECTORY RET g\"." (defun magit-insert-tracked-files () "Insert a tree of tracked files. -If the first element of `magit-diff-section-arguments' is a +If the first element of `magit-buffer-diff-files' is a directory, then limit the list to files below that. The value -value of that variable can be set using \"D = f DIRECTORY RET g\"." +value of that variable can be set using \"D -- DIRECTORY RET g\"." (when-let ((files (magit-list-files))) - (let* ((base (car magit-diff-section-file-args)) + (let* ((base (car magit-buffer-diff-files)) (base (and base (file-directory-p base) base))) (magit-insert-section (tracked nil t) (magit-insert-heading "Tracked files:") @@ -630,17 +674,31 @@ value of that variable can be set using \"D = f DIRECTORY RET g\"." (defun magit-insert-ignored-files () "Insert a tree of ignored files. -If the first element of `magit-diff-section-arguments' is a +If the first element of `magit-buffer-diff-files' is a directory, then limit the list to files below that. The value -of that variable can be set using \"D = f DIRECTORY RET g\"." +of that variable can be set using \"D -- DIRECTORY RET g\"." (when-let ((files (magit-ignored-files))) - (let* ((base (car magit-diff-section-file-args)) + (let* ((base (car magit-buffer-diff-files)) (base (and base (file-directory-p base) base))) (magit-insert-section (tracked nil t) (magit-insert-heading "Ignored files:") (magit-insert-files files base) (insert ?\n))))) +(defun magit-insert-skip-worktree-files () + "Insert a tree of skip-worktree files. + +If the first element of `magit-buffer-diff-files' is a +directory, then limit the list to files below that. The value +of that variable can be set using \"D -- DIRECTORY RET g\"." + (when-let ((files (magit-skip-worktree-files))) + (let* ((base (car magit-buffer-diff-files)) + (base (and base (file-directory-p base) base))) + (magit-insert-section (skip-worktree nil t) + (magit-insert-heading "Skip-worktree files:") + (magit-insert-files files base) + (insert ?\n))))) + (defun magit-insert-files (files directory) (while (and files (string-prefix-p (or directory "") (car files))) (let ((dir (file-name-directory (car files)))) diff --git a/elpa/magit-20190122.503/magit-submodule.el b/elpa/magit-20190514.1814/magit-submodule.el similarity index 87% rename from elpa/magit-20190122.503/magit-submodule.el rename to elpa/magit-20190514.1814/magit-submodule.el index 7a7f340d..d86e7521 100644 --- a/elpa/magit-20190122.503/magit-submodule.el +++ b/elpa/magit-20190514.1814/magit-submodule.el @@ -29,8 +29,6 @@ (require 'magit) (defvar x-stretch-cursor) -(defvar bookmark-make-record-function) - ;;; Options (defcustom magit-module-sections-hook @@ -115,49 +113,63 @@ and also setting this variable to t will lead to tears." ;;; Popup -;;;###autoload (autoload 'magit-submodule-popup "magit-submodule" nil t) -(magit-define-popup magit-submodule-popup - "Popup console for submodule commands." +;;;###autoload (autoload 'magit-submodule "magit-submodule" nil t) +(define-transient-command magit-submodule () + "Act on a submodule." :man-page "git-submodule" - :switches '((?f "Force" "--force") - (?r "Recursive" "--recursive") - (?N "Do not fetch" "--no-fetch") - (?C "Checkout tip" "--checkout") - (?R "Rebase onto tip" "--rebase") - (?M "Merge tip" "--merge") - (?U "Use upstream tip" "--remote")) - :actions - '((?a "Add git submodule add [--force]" - magit-submodule-add) - (?r "Register git submodule init" - magit-submodule-register) - (?p "Populate git submodule update --init" - magit-submodule-populate) - (?u "Update git submodule update [--force] [--no-fetch] - [--remote] [--recursive] [--checkout|--rebase|--merge]" - magit-submodule-update) - (?s "Synchronize git submodule sync [--recursive]" - magit-submodule-synchronize) - (?d "Unpopulate git submodule deinit [--force]" - magit-submodule-unpopulate) - (?k "Remove" magit-submodule-remove) - nil - (?l "List all modules" magit-list-submodules) - (?f "Fetch all modules" magit-fetch-modules)) - :max-action-columns 1) - -(defun magit-submodule-filtered-arguments (&rest filters) + ["Arguments" + ("-f" "Force" ("-f" "--force")) + ("-r" "Recursive" "--recursive") + ("-N" "Do not fetch" ("-N" "--no-fetch")) + ("-C" "Checkout tip" "--checkout") + ("-R" "Rebase onto tip" "--rebase") + ("-M" "Merge tip" "--merge") + ("-U" "Use upstream tip" "--remote")] + ["One module actions" + ("a" magit-submodule-add) + ("r" magit-submodule-register) + ("p" magit-submodule-populate) + ("u" magit-submodule-update) + ("s" magit-submodule-synchronize) + ("d" magit-submodule-unpopulate) + ("k" "Remove" magit-submodule-remove)] + ["All modules actions" + ("l" "List all modules" magit-list-submodules) + ("f" "Fetch all modules" magit-fetch-modules)]) + +(defun magit-submodule-arguments (&rest filters) (--filter (and (member it filters) it) - (magit-submodule-arguments))) - -;;;###autoload -(defun magit-submodule-add (url &optional path name args) + (transient-args 'magit-submodule))) + +(defclass magit--git-submodule-suffix (transient-suffix) + ()) + +(cl-defmethod transient-format-description ((obj magit--git-submodule-suffix)) + (let ((value (transient-args transient--prefix))) + (replace-regexp-in-string + "\\[--[^]]+\\]" + (lambda (match) + (format (propertize "[%s]" 'face 'transient-inactive-argument) + (mapconcat (lambda (arg) + (propertize arg 'face + (if (member arg value) + 'transient-argument + 'transient-inactive-argument))) + (save-match-data + (split-string (substring match 1 -1) "|")) + (propertize "|" 'face 'transient-inactive-argument)))) + (cl-call-next-method obj)))) + +;;;###autoload (autoload 'magit-submodule-add "magit-submodule" nil t) +(define-suffix-command magit-submodule-add (url &optional path name args) "Add the repository at URL as a module. Optional PATH is the path to the module relative to the root of the superproject. If it is nil, then the path is determined based on the URL. Optional NAME is the name of the module. If it is nil, then PATH also becomes the name." + :class 'magit--git-submodule-suffix + :description "Add git submodule add [--force]" (interactive (magit-with-toplevel (let* ((url (magit-read-string-ns "Add submodule (remote url)")) @@ -178,7 +190,10 @@ it is nil, then PATH also becomes the name." (list url (directory-file-name path) (magit-submodule-read-name-for-path path) - (magit-submodule-filtered-arguments "--force"))))) + (magit-submodule-arguments "--force"))))) + (magit-submodule-add-1 url path name args)) + +(defun magit-submodule-add-1 (url &optional path name args) (magit-with-toplevel (magit-submodule--maybe-reuse-gitdir name path) (magit-run-git-async "submodule" "add" @@ -209,8 +224,8 @@ it is nil, then PATH also becomes the name." (magit-git-lines "config" "--list" "-f" ".gitmodules")) (if prefer-short name path))))) -;;;###autoload -(defun magit-submodule-register (modules) +;;;###autoload (autoload 'magit-submodule-register "magit-submodule" nil t) +(define-suffix-command magit-submodule-register (modules) "Register MODULES. With a prefix argument act on all suitable modules. Otherwise, @@ -222,13 +237,14 @@ single module from the user." ;; super-projects $GIT_DIR/config file, the purpose of which is to ;; allow users to change such values before actually initializing ;; the modules. + :description "Register git submodule init" (interactive (list (magit-module-confirm "Register" 'magit-module-no-worktree-p))) (magit-with-toplevel (magit-run-git-async "submodule" "init" "--" modules))) -;;;###autoload -(defun magit-submodule-populate (modules) +;;;###autoload (autoload 'magit-submodule-populate "magit-submodule" nil t) +(define-suffix-command magit-submodule-populate (modules) "Create MODULES working directories, checking out the recorded commits. With a prefix argument act on all suitable modules. Otherwise, @@ -238,13 +254,14 @@ single module from the user." ;; This is the command that actually "initializes" modules. ;; A module is initialized when it has a working directory, ;; a gitlink, and a .gitmodules entry. + :description "Populate git submodule update --init" (interactive (list (magit-module-confirm "Populate" 'magit-module-no-worktree-p))) (magit-with-toplevel (magit-run-git-async "submodule" "update" "--init" "--" modules))) -;;;###autoload -(defun magit-submodule-update (modules args) +;;;###autoload (autoload 'magit-submodule-update "magit-submodule" nil t) +(define-suffix-command magit-submodule-update (modules args) "Update MODULES by checking out the recorded commits. With a prefix argument act on all suitable modules. Otherwise, @@ -255,30 +272,35 @@ single module from the user." ;; "initialized" modules by checking out other commits but not ;; "initialize" modules by creating the working directories. ;; To do the latter we provide the "setup" command. + :class 'magit--git-submodule-suffix + :description "Update git submodule update [--force] [--no-fetch] + [--remote] [--recursive] [--checkout|--rebase|--merge]" (interactive (list (magit-module-confirm "Update" 'magit-module-worktree-p) - (magit-submodule-filtered-arguments + (magit-submodule-arguments "--force" "--remote" "--recursive" "--checkout" "--rebase" "--merge" "--no-fetch"))) (magit-with-toplevel (magit-run-git-async "submodule" "update" args "--" modules))) -;;;###autoload -(defun magit-submodule-synchronize (modules args) +;;;###autoload (autoload 'magit-submodule-synchronize "magit-submodule" nil t) +(define-suffix-command magit-submodule-synchronize (modules args) "Synchronize url configuration of MODULES. With a prefix argument act on all suitable modules. Otherwise, if the region selects modules, then act on those. Otherwise, if there is a module at point, then act on that. Otherwise read a single module from the user." + :class 'magit--git-submodule-suffix + :description "Synchronize git submodule sync [--recursive]" (interactive (list (magit-module-confirm "Synchronize" 'magit-module-worktree-p) - (magit-submodule-filtered-arguments "--recursive"))) + (magit-submodule-arguments "--recursive"))) (magit-with-toplevel (magit-run-git-async "submodule" "sync" args "--" modules))) -;;;###autoload -(defun magit-submodule-unpopulate (modules args) +;;;###autoload (autoload 'magit-submodule-unpopulate "magit-submodule" nil t) +(define-suffix-command magit-submodule-unpopulate (modules args) "Remove working directories of MODULES. With a prefix argument act on all suitable modules. Otherwise, @@ -292,9 +314,11 @@ single module from the user." ;; is to remove the working directory AND to remove the url, this ;; command does not limit itself to modules that have no working ;; directory. + :class 'magit--git-submodule-suffix + :description "Unpopulate git submodule deinit [--force]" (interactive (list (magit-module-confirm "Unpopulate") - (magit-submodule-filtered-arguments "--force"))) + (magit-submodule-arguments "--force"))) (magit-with-toplevel (magit-run-git-async "submodule" "deinit" args "--" modules))) @@ -316,7 +340,7 @@ to recover from making a mistake here, but don't count on it." (list (if-let ((modules (magit-region-values 'magit-module-section t))) (magit-confirm 'remove-modules nil "Remove %i modules" nil modules) (list (magit-read-module-path "Remove module"))) - (magit-submodule-filtered-arguments "--force") + (magit-submodule-arguments "--force") current-prefix-arg)) (when (version< (magit-git-version) "2.12.0") (error "This command requires Git v2.12.0")) @@ -553,7 +577,7 @@ These sections can be expanded to show the respective commits." "Display a list of the current repository's submodules." (interactive) (magit-display-buffer - (or (magit-mode-get-buffer 'magit-submodule-list-mode) + (or (magit-get-mode-buffer 'magit-submodule-list-mode) (magit-with-toplevel (magit-generate-new-buffer 'magit-submodule-list-mode)))) (magit-submodule-list-mode) @@ -582,9 +606,7 @@ These sections can be expanded to show the respective commits." (setq imenu-prev-index-position-function #'magit-imenu--submodule-prev-index-position-function) (setq imenu-extract-index-name-function - #'magit-imenu--submodule-extract-index-name-function) - (setq-local bookmark-make-record-function - #'magit-bookmark--submodules-make-record)) + #'magit-imenu--submodule-extract-index-name-function)) (defun magit-submodule-list-refresh () (setq tabulated-list-entries @@ -627,7 +649,7 @@ These sections can be expanded to show the respective commits." (with-temp-file (expand-file-name ".git" worktree) (insert "gitdir: " (file-relative-name gitdir worktree) "\n")) (let ((default-directory worktree)) - (magit-call-git "reset" "--hard" "HEAD"))) + (magit-call-git "reset" "--hard" "HEAD" "--"))) ;;; _ (provide 'magit-submodule) diff --git a/elpa/magit-20190122.503/magit-subtree.el b/elpa/magit-20190514.1814/magit-subtree.el similarity index 51% rename from elpa/magit-20190122.503/magit-subtree.el rename to elpa/magit-20190514.1814/magit-subtree.el index d7aa3a20..b8375f71 100644 --- a/elpa/magit-20190122.503/magit-subtree.el +++ b/elpa/magit-20190514.1814/magit-subtree.el @@ -25,34 +25,53 @@ (require 'magit) -;;; Popup +;;; Commands + +;;;###autoload (autoload 'magit-subtree "magit-subtree" nil t) +(define-transient-command magit-subtree () + "Import or export subtrees." + :man-page "git-subtree" + ["Actions" + ("i" "Import" magit-subtree-import) + ("e" "Export" magit-subtree-export)]) -;;;###autoload (autoload 'magit-subtree-popup "magit-subtree" nil t) -(magit-define-popup magit-subtree-popup - "Popup console for subtree commands." +;;;###autoload (autoload 'magit-subtree-import "magit-subtree" nil t) +(define-transient-command magit-subtree-import () + "Import subtrees." :man-page "git-subtree" - :switches '("Switches for add, merge, push, and pull" - (?s "Squash" "--squash") - "Switches for split" - (?i "Ignore joins" "--ignore-joins") - (?j "Rejoin" "--rejoin")) - :options '("Options" - (?p "Prefix" "--prefix=" magit-subtree-read-prefix) - "Options for add, merge, and pull" - (?m "Message" "--message=") - "Options for split" - (?a "Annotate" "--annotate=") - (?b "Branch" "--branch=") - (?o "Onto" "--onto=" magit-read-branch-or-commit)) - :actions '((?a "Add" magit-subtree-add) - (?m "Merge" magit-subtree-merge) - (?p "Push" magit-subtree-push) - (?c "Add commit" magit-subtree-add-commit) - (?f "Pull" magit-subtree-pull) - (?s "Split" magit-subtree-split)) - :max-action-columns 3) - -(defun magit-subtree-read-prefix (prompt &optional default) + ["Arguments" + (magit-subtree:--prefix) + (magit-subtree:--message) + ("-s" "Squash" "--squash")] + ["Actions" + [("a" "Add" magit-subtree-add) + ("c" "Add commit" magit-subtree-add-commit)] + [("m" "Merge" magit-subtree-merge) + ("f" "Pull" magit-subtree-pull)]]) + +;;;###autoload (autoload 'magit-subtree-export "magit-subtree" nil t) +(define-transient-command magit-subtree-export () + "Export subtrees." + :man-page "git-subtree" + ["Arguments" + (magit-subtree:--prefix) + (magit-subtree:--annotate) + (magit-subtree:--branch) + (magit-subtree:--onto) + ("-i" "Ignore joins" "--ignore-joins") + ("-j" "Rejoin" "--rejoin")] + ["Actions" + ("p" "Push" magit-subtree-push) + ("s" "Split" magit-subtree-split)]) + +(define-infix-argument magit-subtree:--prefix () + :description "Prefix" + :class 'transient-option + :shortarg "-P" + :argument "--prefix=" + :reader 'magit-subtree-read-prefix) + +(defun magit-subtree-read-prefix (prompt &optional default _history) (let* ((insert-default-directory nil) (topdir (magit-toplevel)) (prefix (read-directory-name (concat prompt ": ") topdir default))) @@ -63,26 +82,40 @@ (user-error "%s isn't inside the repository at %s" prefix topdir)) prefix))) -;;; Commands - -(defun magit-subtree-prefix (prompt) +(define-infix-argument magit-subtree:--message () + :description "Message" + :class 'transient-option + :shortarg "-m" + :argument "--message=") + +(define-infix-argument magit-subtree:--annotate () + :description "Annotate" + :class 'transient-option + :key "-a" + :argument "--annotate=") + +(define-infix-argument magit-subtree:--branch () + :description "Branch" + :class 'transient-option + :shortarg "-b" + :argument "--branch=") + +(define-infix-argument magit-subtree:--onto () + :description "Onto" + :class 'transient-option + :key "-o" + :argument "--onto=" + :reader 'magit-transient-read-revision) + +(defun magit-subtree-prefix (transient prompt) (--if-let (--first (string-prefix-p "--prefix=" it) - (magit-subtree-arguments)) + (transient-args transient)) (substring it 9) (magit-subtree-read-prefix prompt))) -(defun magit-subtree-args () - (-filter (lambda (arg) - (if (eq this-command 'magit-subtree-split) - (or (equal arg "--ignore-joins") - (equal arg "--rejoin") - (string-prefix-p "--annotate=" arg) - (string-prefix-p "--branch=" arg) - (string-prefix-p "--onto=" arg)) - (or (equal arg "--squash") - (and (string-prefix-p "--message=" arg) - (not (eq this-command 'magit-subtree-push)))))) - (magit-subtree-arguments))) +(defun magit-subtree-arguments (transient) + (--remove (string-prefix-p "--prefix=" it) + (transient-args transient))) (defun magit-git-subtree (subcmd prefix &rest args) (magit-run-git-async "subtree" subcmd (concat "--prefix=" prefix) args)) @@ -91,55 +124,57 @@ (defun magit-subtree-add (prefix repository ref args) "Add REF from REPOSITORY as a new subtree at PREFIX." (interactive - (cons (magit-subtree-prefix "Add subtree") + (cons (magit-subtree-prefix 'magit-subtree-import "Add subtree") (let ((remote (magit-read-remote-or-url "From repository"))) (list remote (magit-read-refspec "Ref" remote) - (magit-subtree-args))))) + (magit-subtree-arguments 'magit-subtree-import))))) (magit-git-subtree "add" prefix args repository ref)) ;;;###autoload (defun magit-subtree-add-commit (prefix commit args) "Add COMMIT as a new subtree at PREFIX." - (interactive (list (magit-subtree-prefix "Add subtree") - (magit-read-string-ns "Commit") - (magit-subtree-args))) + (interactive + (list (magit-subtree-prefix 'magit-subtree-import "Add subtree") + (magit-read-string-ns "Commit") + (magit-subtree-arguments 'magit-subtree-import))) (magit-git-subtree "add" prefix args commit)) ;;;###autoload (defun magit-subtree-merge (prefix commit args) "Merge COMMIT into the PREFIX subtree." - (interactive (list (magit-subtree-prefix "Merge into subtree") - (magit-read-string-ns "Commit") - (magit-subtree-args))) + (interactive + (list (magit-subtree-prefix 'magit-subtree-import "Merge into subtree") + (magit-read-string-ns "Commit") + (magit-subtree-arguments 'magit-subtree-import))) (magit-git-subtree "merge" prefix args commit)) ;;;###autoload (defun magit-subtree-pull (prefix repository ref args) "Pull REF from REPOSITORY into the PREFIX subtree." (interactive - (cons (magit-subtree-prefix "Pull into subtree") + (cons (magit-subtree-prefix 'magit-subtree-import "Pull into subtree") (let ((remote (magit-read-remote-or-url "From repository"))) (list remote (magit-read-refspec "Ref" remote) - (magit-subtree-args))))) + (magit-subtree-arguments 'magit-subtree-import))))) (magit-git-subtree "pull" prefix args repository ref)) ;;;###autoload (defun magit-subtree-push (prefix repository ref args) "Extract the history of the subtree PREFIX and push it to REF on REPOSITORY." - (interactive (list (magit-subtree-prefix "Push subtree") + (interactive (list (magit-subtree-prefix 'magit-subtree-export "Push subtree") (magit-read-remote-or-url "To repository") (magit-read-string-ns "To reference") - (magit-subtree-args))) + (magit-subtree-arguments 'magit-subtree-export))) (magit-git-subtree "push" prefix args repository ref)) ;;;###autoload (defun magit-subtree-split (prefix commit args) "Extract the history of the subtree PREFIX." - (interactive (list (magit-subtree-prefix "Split subtree") + (interactive (list (magit-subtree-prefix 'magit-subtree-export "Split subtree") (magit-read-string-ns "Commit") - (magit-subtree-args))) + (magit-subtree-arguments 'magit-subtree-export))) (magit-git-subtree "split" prefix args commit)) ;;; _ diff --git a/elpa/magit-20190122.503/magit-tag.el b/elpa/magit-20190514.1814/magit-tag.el similarity index 86% rename from elpa/magit-20190122.503/magit-tag.el rename to elpa/magit-20190514.1814/magit-tag.el index 7187d017..9a4859c6 100644 --- a/elpa/magit-20190122.503/magit-tag.el +++ b/elpa/magit-20190514.1814/magit-tag.el @@ -29,19 +29,32 @@ (require 'magit) -;;;###autoload (autoload 'magit-tag-popup "magit" nil t) -(magit-define-popup magit-tag-popup - "Popup console for tag commands." +;;;###autoload (autoload 'magit-tag "magit" nil t) +(define-transient-command magit-tag () + "Create or delete a tag." :man-page "git-tag" - :switches '((?a "Annotate" "--annotate") - (?f "Force" "--force") - (?s "Sign" "--sign")) - :options '((?f "Sign" "--local-user=" magit-read-gpg-secret-key)) - :actions '((?t "Create" magit-tag-create) - (?r "Create release" magit-tag-release) - (?k "Delete" magit-tag-delete) - (?p "Prune" magit-tag-prune)) - :default-action 'magit-tag-create) + ["Arguments" + ("-f" "Force" ("-f" "--force")) + ("-a" "Annotate" ("-a" "--annotate")) + ("-s" "Sign" ("-s" "--sign")) + (magit-tag:--local-user)] + [["Create" + ("t" "tag" magit-tag-create) + ("r" "release" magit-tag-release)] + ["Do" + ("k" "delete" magit-tag-delete) + ("p" "prune" magit-tag-prune)]]) + +(defun magit-tag-arguments () + (transient-args 'magit-tag)) + +(define-infix-argument magit-tag:--local-user () + :description "Sign as" + :class 'transient-option + :shortarg "-u" + :argument "--local-user=" + :reader 'magit-read-gpg-secret-key + :history-key 'magit:--gpg-sign) ;;;###autoload (defun magit-tag-create (name rev &optional args) @@ -142,8 +155,13 @@ review the result." (directory-file-name (magit-toplevel)))) ver))))) (list tag (read-string (format "Message for %S: " tag) msg))))) - (magit-run-git "tag" "--annotate" "--sign" "-m" msg tag) - (magit-show-refs)) + (magit-run-git-async "tag" "--annotate" "--sign" "-m" msg tag) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (magit-process-sentinel process event) + (magit-refs-setup-buffer "HEAD" (magit-show-refs-arguments)))))) (defun magit--list-releases () "Return a list of releases. diff --git a/elpa/magit-20190514.1814/magit-transient.el b/elpa/magit-20190514.1814/magit-transient.el new file mode 100644 index 00000000..f877432a --- /dev/null +++ b/elpa/magit-20190514.1814/magit-transient.el @@ -0,0 +1,198 @@ +;;; magit-transient.el --- support for transients -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; 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. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements Magit-specific prefix and suffix classes, +;; and their methods. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'transient) + +(require 'magit-git) +(require 'magit-mode) +(require 'magit-process) + +;;; Classes + +(defclass magit--git-variable (transient-variable) + ((scope :initarg :scope))) + +(defclass magit--git-variable:choices (magit--git-variable) + ((choices :initarg :choices) + (fallback :initarg :fallback :initform nil) + (default :initarg :default :initform nil))) + +(defclass magit--git-variable:urls (magit--git-variable) + ((seturl-arg :initarg :seturl-arg :initform nil))) + +;;; Methods +;;;; Init + +(cl-defmethod transient-init-scope ((obj magit--git-variable)) + (oset obj scope + (cond (transient--prefix + (oref transient--prefix scope)) + ((slot-boundp obj 'scope) + (funcall (oref obj scope) obj))))) + +(cl-defmethod transient-init-value ((obj magit--git-variable)) + (let ((variable (format (oref obj variable) + (oref obj scope)))) + (oset obj variable variable) + (oset obj value + (cond ((oref obj multi-value) + (magit-get-all variable)) + (t + (magit-git-string "config" "--local" variable)))))) + +;;;; Read + +(cl-defmethod transient-infix-read :around ((obj magit--git-variable:urls)) + (mapcar (lambda (url) + (if (string-prefix-p "~" url) + (expand-file-name url) + url)) + (cl-call-next-method obj))) + +(cl-defmethod transient-infix-read ((obj magit--git-variable:choices)) + (let ((choices (oref obj choices))) + (when (functionp choices) + (setq choices (funcall choices))) + (if-let ((value (oref obj value))) + (cadr (member value choices)) + (car choices)))) + +;;;; Readers + +(defun magit-transient-read-person (prompt initial-input history) + (magit-completing-read + prompt + (mapcar (lambda (line) + (save-excursion + (and (string-match "\\`[\s\t]+[0-9]+\t" line) + (list (substring line (match-end 0)))))) + (magit-git-lines "shortlog" "-n" "-s" "-e" "HEAD")) + nil nil initial-input history)) + +(defun magit-transient-read-revision (prompt initial-input history) + (or (magit-completing-read prompt (cons "HEAD" (magit-list-refnames)) + nil nil initial-input history + (or (magit-branch-or-commit-at-point) + (magit-get-current-branch))) + (user-error "Nothing selected"))) + +;;;; Set + +(cl-defmethod transient-infix-set ((obj magit--git-variable) value) + (let ((variable (oref obj variable))) + (oset obj value value) + (if (oref obj multi-value) + (magit-set-all value variable) + (magit-set value variable)) + (magit-refresh) + (unless (or value transient--prefix) + (message "Unset %s" variable)))) + +(cl-defmethod transient-infix-set ((obj magit--git-variable:urls) values) + (let ((previous (oref obj value)) + (seturl (oref obj seturl-arg)) + (remote (oref transient--prefix scope))) + (oset obj value values) + (dolist (v (-difference values previous)) + (magit-call-git "remote" "set-url" seturl "--add" remote v)) + (dolist (v (-difference previous values)) + (magit-call-git "remote" "set-url" seturl "--delete" remote + (concat "^" (regexp-quote v) "$"))) + (magit-refresh))) + +;;;; Draw + +(cl-defmethod transient-format-description ((obj magit--git-variable)) + (or (oref obj description) + (oref obj variable))) + +(cl-defmethod transient-format-value ((obj magit--git-variable)) + (if-let ((value (oref obj value))) + (if (oref obj multi-value) + (if (cdr value) + (mapconcat (lambda (v) + (concat "\n " + (propertize v 'face 'transient-value))) + value "") + (propertize (car value) 'face 'transient-value)) + (propertize (car (split-string value "\n")) + 'face 'transient-value)) + (propertize "unset" 'face 'transient-inactive-value))) + +(cl-defmethod transient-format-value ((obj magit--git-variable:choices)) + (let* ((variable (oref obj variable)) + (choices (oref obj choices)) + (local (magit-git-string "config" "--local" variable)) + (global (magit-git-string "config" "--global" variable)) + (default (oref obj default)) + (fallback (oref obj fallback)) + (fallback (and fallback + (when-let ((val (magit-get fallback))) + (concat fallback ":" val))))) + (when (functionp choices) + (setq choices (funcall choices))) + (concat + (propertize "[" 'face 'transient-inactive-value) + (mapconcat (lambda (choice) + (propertize choice 'face (if (equal choice local) + 'transient-value + 'transient-inactive-value))) + choices + (propertize "|" 'face 'transient-inactive-value)) + (and (or global fallback default) + (concat + (propertize "|" 'face 'transient-inactive-value) + (cond (global + (propertize (concat "global:" global) + 'face (cond (local + 'transient-inactive-value) + ((member global choices) + 'transient-value) + (t + 'font-lock-warning-face)))) + (fallback + (propertize fallback + 'face (if local + 'transient-inactive-value + 'transient-value))) + (default + (propertize (concat "default:" default) + 'face (if local + 'transient-inactive-value + 'transient-value)))))) + (propertize "]" 'face 'transient-inactive-value)))) + +;;; _ +(provide 'magit-transient) +;;; magit-transient.el ends here + diff --git a/elpa/magit-20190122.503/magit-utils.el b/elpa/magit-20190514.1814/magit-utils.el similarity index 94% rename from elpa/magit-20190122.503/magit-utils.el rename to elpa/magit-20190514.1814/magit-utils.el index c3a18b00..5ead657b 100644 --- a/elpa/magit-20190122.503/magit-utils.el +++ b/elpa/magit-20190514.1814/magit-utils.el @@ -61,8 +61,6 @@ (defvar magit-wip-before-change-mode) -(require 'magit-popup) - ;;; Options (defcustom magit-completing-read-function 'magit-builtin-completing-read @@ -223,8 +221,8 @@ References: choice (or selecting another branch), but when a branch has not been merged yet, also make sure the user is aware of that. - `delete-pr-branch' When deleting a branch that was created from - a pull request and if no other branches still exist on that + `delete-pr-remote' When deleting a branch that was created from + a pull-request and if no other branches still exist on that remote, then `magit-branch-delete' offers to delete the remote as well. This should be safe because it only happens if no other refs exist in the remotes namespace, and you can recreate @@ -648,12 +646,13 @@ This is similar to `read-string', but (defmacro magit-read-char-case (prompt verbose &rest clauses) (declare (indent 2) (debug (form form &rest (characterp form body)))) - `(pcase (read-char-choice - (concat ,prompt - ,(concat (mapconcat 'cadr clauses ", ") - (and verbose ", or [C-g] to abort") " ")) - ',(mapcar 'car clauses)) - ,@(--map `(,(car it) ,@(cddr it)) clauses))) + `(prog1 (pcase (read-char-choice + (concat ,prompt + ,(concat (mapconcat 'cadr clauses ", ") + (and verbose ", or [C-g] to abort") " ")) + ',(mapcar 'car clauses)) + ,@(--map `(,(car it) ,@(cddr it)) clauses)) + (message ""))) (defun magit-y-or-n-p (prompt &optional action) "Ask user a \"y or n\" or a \"yes or no\" question using PROMPT. @@ -711,7 +710,7 @@ ACTION is a member of option `magit-slow-confirm'." (replace-regexp-in-string "-" " " (concat (upcase (substring prompt 0 1)) (substring prompt 1))))) -(defun magit-read-number-string (prompt &optional default) +(defun magit-read-number-string (prompt &optional default _history) "Like `read-number' but return value is a string. DEFAULT may be a number or a numeric string." (number-to-string @@ -739,12 +738,11 @@ See info node `(magit)Debugging Tools' for more information." (cond (path (list (file-name-directory path))) - ((not (member lib '("lv" "transient"))) + ((not (equal lib "libgit")) (error "Cannot find mandatory dependency %s" lib))))) '(;; Like `LOAD_PATH' in `default.mk'. "dash" - "lv" - "magit-popup" + "libgit" "transient" "with-editor" ;; Obviously `magit' itself is needed too. @@ -806,34 +804,23 @@ Unless optional argument KEEP-EMPTY-LINES is t, trim all empty lines." (defun magit-set-header-line-format (string) "Set the header-line using STRING. -Propertize STRING with the `magit-header-line' face if no face is -present, and pad the left and right sides of STRING equally such -that it will align with the text area." - (let* ((header-line - (concat (propertize " " - 'display - '(space :align-to 0)) - string - (propertize - " " - 'display - `(space :width (+ left-fringe - left-margin - ,@(and (eq (car (window-current-scroll-bars)) - 'left) - '(scroll-bar))))))) - (len (length header-line))) - (setq header-line-format - (if (text-property-not-all 0 len 'face nil header-line) - (let ((face (get-text-property 0 'face string))) - (when (and (atom face) - (magit-face-property-all face string)) - (add-face-text-property 0 1 face nil header-line) - (add-face-text-property (1- len) len face nil header-line)) - header-line) - (propertize header-line - 'face - 'magit-header-line))))) +Propertize STRING with the `magit-header-line'. If the `face' +property of any part of STRING is already set, then that takes +precedence. Also pad the left and right sides of STRING so that +it aligns with the text area." + (setq header-line-format + (concat + (propertize " " 'display '(space :align-to 0)) + string + (propertize " " 'display + `(space :width + (+ left-fringe + left-margin + ,@(and (eq (car (window-current-scroll-bars)) + 'left) + '(scroll-bar))))))) + (add-face-text-property 0 (1- (length header-line-format)) + 'magit-header-line t header-line-format)) (defun magit-face-property-all (face string) "Return non-nil if FACE is present in all of STRING." @@ -1082,20 +1069,19 @@ or (last of all) the value of EXP." ;;;###autoload (defun Info-follow-nearest-node--magit-gitman (fn &optional fork) - (if magit-view-git-manual-method - (let ((node (Info-get-token - (point) "\\*note[ \n\t]+" - "\\*note[ \n\t]+\\([^:]*\\):\\(:\\|[ \n\t]*(\\)?"))) - (if (and node (string-match "^(gitman)\\(.+\\)" node)) - (pcase magit-view-git-manual-method - (`man (require 'man) - (man (match-string 1 node))) - (`woman (require 'woman) - (woman (match-string 1 node))) - (_ - (user-error "Invalid value for `magit-view-git-manual-method'"))) - (funcall fn fork))) - (funcall fn fork))) + (let ((node (Info-get-token + (point) "\\*note[ \n\t]+" + "\\*note[ \n\t]+\\([^:]*\\):\\(:\\|[ \n\t]*(\\)?"))) + (if (and node (string-match "^(gitman)\\(.+\\)" node)) + (pcase magit-view-git-manual-method + (`info (funcall fn fork)) + (`man (require 'man) + (man (match-string 1 node))) + (`woman (require 'woman) + (woman (match-string 1 node))) + (_ + (user-error "Invalid value for `magit-view-git-manual-method'"))) + (funcall fn fork)))) ;;;###autoload (advice-add 'Info-follow-nearest-node :around @@ -1126,7 +1112,7 @@ the %s(1) manpage. ;;; Bitmaps -(when (window-system) +(when (fboundp 'define-fringe-bitmap) (define-fringe-bitmap 'magit-fringe-bitmap+ [#b00000000 #b00011000 @@ -1201,6 +1187,15 @@ Like `message', except that `message-log-max' is bound to nil." (let ((message-log-max nil)) (apply #'message format-string args))) +(defmacro magit--with-temp-position (buf pos &rest body) + (declare (indent 2)) + `(with-current-buffer ,buf + (save-excursion + (save-restriction + (widen) + (goto-char ,pos) + ,@body)))) + ;;; _ (provide 'magit-utils) ;;; magit-utils.el ends here diff --git a/elpa/magit-20190122.503/magit-wip.el b/elpa/magit-20190514.1814/magit-wip.el similarity index 96% rename from elpa/magit-20190122.503/magit-wip.el rename to elpa/magit-20190514.1814/magit-wip.el index b291cd0d..6f6ab3be 100644 --- a/elpa/magit-20190122.503/magit-wip.el +++ b/elpa/magit-20190514.1814/magit-wip.el @@ -371,12 +371,12 @@ commit message." (defun magit-wip-log-index (args files) "Show log for the index wip ref of the current branch." (interactive (magit-log-arguments)) - (magit-git-log (list (magit--wip-index-ref)) args files)) + (magit-log-setup-buffer (list (magit--wip-index-ref)) args files)) (defun magit-wip-log-worktree (args files) "Show log for the worktree wip ref of the current branch." (interactive (magit-log-arguments)) - (magit-git-log (list (magit--wip-wtree-ref)) args files)) + (magit-log-setup-buffer (list (magit--wip-wtree-ref)) args files)) (defun magit-wip-log-current (branch args files count) "Show log for the current branch and its wip refs. @@ -404,15 +404,15 @@ many \"branches\" of each wip ref are shown." "HEAD"))) (magit-log-arguments) (list (prefix-numeric-value current-prefix-arg)))) - (magit-git-log (nconc (list branch) - (magit-wip-log-get-tips - (magit--wip-wtree-ref branch) - (abs count)) - (and (>= count 0) - (magit-wip-log-get-tips - (magit--wip-index-ref branch) - (abs count)))) - args files)) + (magit-log-setup-buffer (nconc (list branch) + (magit-wip-log-get-tips + (magit--wip-wtree-ref branch) + (abs count)) + (and (>= count 0) + (magit-wip-log-get-tips + (magit--wip-index-ref branch) + (abs count)))) + args files)) (defun magit-wip-log-get-tips (wipref count) (when-let ((reflog (magit-git-lines "reflog" wipref))) diff --git a/elpa/magit-20190122.503/magit-worktree.el b/elpa/magit-20190514.1814/magit-worktree.el similarity index 81% rename from elpa/magit-20190122.503/magit-worktree.el rename to elpa/magit-20190514.1814/magit-worktree.el index d6d46a84..fd40eb98 100644 --- a/elpa/magit-20190122.503/magit-worktree.el +++ b/elpa/magit-20190514.1814/magit-worktree.el @@ -29,24 +29,37 @@ (require 'magit) +;;; Options + +(defcustom magit-worktree-read-directory-name-function 'read-directory-name + "Function used to read a directory for worktree commands. +This is called with one argument, the prompt, and can be used +to e.g. use a base directory other than `default-directory'. +Used by `magit-worktree-checkout' and `magit-worktree-branch'." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'function) + ;;; Commands -;;;###autoload (autoload 'magit-worktree-popup "magit-worktree" nil t) -(magit-define-popup magit-worktree-popup - "Popup console for worktree commands." +;;;###autoload (autoload 'magit-worktree "magit-worktree" nil t) +(define-transient-command magit-worktree () + "Act on a worktree." :man-page "git-worktree" - :actions '((?b "Create new worktree" magit-worktree-checkout) - (?c "Create new branch and worktree" magit-worktree-branch) - (?k "Delete worktree" magit-worktree-delete) - (?g "Show status for worktree" magit-worktree-status)) - :max-action-columns 1) + [["Create new" + ("b" "worktree" magit-worktree-checkout) + ("c" "branch and worktree" magit-worktree-branch)] + ["Commands" + ("k" "Delete worktree" magit-worktree-delete) + ("g" "Visit worktree" magit-worktree-status)]]) ;;;###autoload (defun magit-worktree-checkout (path branch) "Checkout BRANCH in a new worktree at PATH." (interactive (let ((branch (magit-read-branch-or-commit "Checkout"))) - (list (read-directory-name (format "Checkout %s in new worktree: " branch)) + (list (funcall magit-worktree-read-directory-name-function + (format "Checkout %s in new worktree: " branch)) branch))) (magit-run-git "worktree" "add" (expand-file-name path) branch) (magit-diff-visit-directory path)) @@ -55,8 +68,9 @@ (defun magit-worktree-branch (path branch start-point &optional force) "Create a new BRANCH and check it out in a new worktree at PATH." (interactive - `(,(read-directory-name "Create worktree: ") - ,@(butlast (magit-branch-read-args "Create and checkout branch")) + `(,(funcall magit-worktree-read-directory-name-function + "Create worktree: ") + ,@(magit-branch-read-args "Create and checkout branch") ,current-prefix-arg)) (magit-run-git "worktree" "add" (if force "-B" "-b") branch (expand-file-name path) start-point) @@ -84,7 +98,7 @@ The primary worktree cannot be deleted." (magit-run-git "worktree" "prune")) (when (derived-mode-p 'magit-status-mode) (kill-buffer) - (magit-status-internal primary)))))) + (magit-status-setup-buffer primary)))))) (defun magit-worktree-status (worktree) "Show the status for the worktree at point. diff --git a/elpa/magit-20190122.503/magit.el b/elpa/magit-20190514.1814/magit.el similarity index 78% rename from elpa/magit-20190122.503/magit.el rename to elpa/magit-20190514.1814/magit.el index 050d8cf5..9f26c71f 100644 --- a/elpa/magit-20190122.503/magit.el +++ b/elpa/magit-20190514.1814/magit.el @@ -19,7 +19,7 @@ ;; Keywords: git tools vc ;; Homepage: https://github.com/magit/magit -;; Magit requires at least GNU Emacs 25.1 and Git 2.0.0. +;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0. ;; Magit is free software; you can redistribute it and/or modify it ;; under the terms of the GNU General Public License as published by @@ -50,21 +50,21 @@ (require 'cl-lib) (require 'dash) -(eval-when-compile - (require 'subr-x)) +(require 'subr-x) (require 'with-editor) (require 'git-commit) (require 'magit-core) (require 'magit-diff) -(require 'magit-apply) (require 'magit-log) +(require 'magit-wip) +(require 'magit-apply) (require 'magit-repos) (require 'format-spec) (require 'package nil t) ; used in `magit-version' -(defconst magit--minimal-git "2.0.0") +(defconst magit--minimal-git "2.2.0") (defconst magit--minimal-emacs "25.1") ;;; Faces @@ -221,91 +221,55 @@ and/or `magit-branch-remote-head'." ;;; Dispatch Popup -;;;###autoload (autoload 'magit-dispatch-popup "magit" nil t) -(magit-define-popup magit-dispatch-popup - "Popup console for dispatching other popups." - :actions '("Popup and dwim commands" - (?A "Cherry-picking" magit-cherry-pick-popup) - (?b "Branching" magit-branch-popup) - (?B "Bisecting" magit-bisect-popup) - (?c "Committing" magit-commit-popup) - (?d "Diffing" magit-diff-popup) - (?D "Change diffs" magit-diff-refresh-popup) - (?e "Ediff dwimming" magit-ediff-dwim) - (?E "Ediffing" magit-ediff-popup) - (?f "Fetching" magit-fetch-popup) - (?F "Pulling" magit-pull-popup) - (?l "Logging" magit-log-popup) - (?L "Change logs" magit-log-refresh-popup) - (?m "Merging" magit-merge-popup) - (?M "Remoting" magit-remote-popup) - (?o "Submodules" magit-submodule-popup) - (?O "Subtrees" magit-subtree-popup) - (?P "Pushing" magit-push-popup) - (?r "Rebasing" magit-rebase-popup) - (?t "Tagging" magit-tag-popup) - (?T "Notes" magit-notes-popup) - (?V "Reverting" magit-revert-popup) - (?w "Apply patches" magit-am-popup) - (?W "Format patches" magit-patch-popup) - (?X "Resetting" magit-reset-popup) - (?y "Show Refs" magit-show-refs-popup) - (?z "Stashing" magit-stash-popup) - (?! "Running" magit-run-popup) - (?% "Worktree" magit-worktree-popup) - (lambda () - (and (with-current-buffer magit-pre-popup-buffer - (derived-mode-p 'magit-mode)) - (propertize "Applying changes" 'face 'magit-popup-heading))) - (?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) - (lambda () - (and (with-current-buffer magit-pre-popup-buffer - (derived-mode-p 'magit-mode)) - (propertize "Essential commands" 'face 'magit-popup-heading))) - (?g " refresh current buffer" magit-refresh) - ;; These bindings only work because of :setup-function. - (?\t " toggle section at point" magit-section-toggle) - (?\r " visit thing at point" magit-visit-thing) - ;; This binding has no effect and only appears to do - ;; so because it is identical to the global binding. - ("C-h m" "show all key bindings" describe-mode)) - :setup-function 'magit-dispatch-popup-setup - :max-action-columns (lambda (heading) - (pcase heading - ("Popup and dwim commands" 4) - ("Applying changes" 3) - ("Essential commands" 1)))) - -(defvar magit-dispatch-popup-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map magit-popup-mode-map) - (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))) - map) - "Keymap used by `magit-dispatch-popup'.") - -(defun magit-dispatch-popup-setup (val def) - (magit-popup-default-setup val def) - (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. - (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 - :fun 'magit-visit-thing))))) +;;;###autoload (autoload 'magit-dispatch "magit" nil t) +(define-transient-command magit-dispatch () + "Invoke a Magit command from a list of available commands." + ["Transient and dwim commands" + [("A" "Apply" magit-cherry-pick) + ("b" "Branch" magit-branch) + ("B" "Bisect" magit-bisect) + ("c" "Commit" magit-commit) + ("C" "Clone" magit-clone) + ("d" "Diff" magit-diff) + ("D" "Diff (change)" magit-diff-refresh) + ("e" "Ediff (dwim)" magit-ediff-dwim) + ("E" "Ediff" magit-ediff)] + [("f" "Fetch" magit-fetch) + ("F" "Pull" magit-pull) + ("l" "Log" magit-log) + ("L" "Log (change)" magit-log-refresh) + ("m" "Merge" magit-merge) + ("M" "Remote" magit-remote) + ("o" "Submodule" magit-submodule) + ("O" "Subtree" magit-subtree)] + [("P" "Push" magit-push) + ("r" "Rebase" magit-rebase) + ("t" "Tag" magit-tag) + ("T" "Note" magit-notes) + ("V" "Revert" magit-revert) + ("w" "Apply patches" magit-am) + ("W" "Format patches" magit-patch) + ("X" "Reset" magit-reset)] + [("y" "Show Refs" magit-show-refs) + ("Y" "Cherries" magit-cherry) + ("z" "Stash" magit-stash) + ("!" "Run" magit-run) + ("%" "Worktree" magit-worktree)]] + ["Applying changes" + :if-derived magit-mode + [("a" "Apply" magit-apply) + ("v" "Reverse" magit-reverse) + ("k" "Discard" magit-discard)] + [("s" "Stage" magit-stage) + ("u" "Unstage" magit-unstage)] + [("S" "Stage all" magit-stage-modified) + ("U" "Unstage all" magit-unstage-all)]] + ["Essential commands" + :if-derived magit-mode + ("g" " refresh current buffer" magit-refresh) + ("" " toggle section at point" magit-section-toggle) + ("" "visit thing at point" magit-visit-thing) + ("C-h m" " show all key bindings" describe-mode)]) ;;; Git Popup @@ -319,19 +283,20 @@ This affects `magit-git-command', `magit-git-command-topdir', (defvar magit-git-command-history nil) -;;;###autoload (autoload 'magit-run-popup "magit" nil t) -(magit-define-popup magit-run-popup - "Popup console for running raw Git commands." - :actions '((?! "Git Subcommand (in topdir)" magit-git-command-topdir) - (?k "Gitk" magit-run-gitk) - (?p "Git Subcommand (in pwd)" magit-git-command) - (?a "Gitk --all" magit-run-gitk-all) - (?s "Shell command (in topdir)" magit-shell-command-topdir) - (?b "Gitk --branches" magit-run-gitk-branches) - (?S "Shell command (in pwd)" magit-shell-command) - (?g "Git Gui" magit-run-git-gui)) - :default-action 'magit-git-command - :max-action-columns 2) +;;;###autoload (autoload 'magit-run "magit" nil t) +(define-transient-command magit-run () + "Run git or another command, or launch a graphical utility." + [["Run git subcommand" + ("!" "in repository root" magit-git-command-topdir) + ("p" "in working directory" magit-git-command)] + ["Run shell command" + ("s" "in repository root" magit-shell-command-topdir) + ("S" "in working directory" magit-shell-command)] + ["Launch" + ("k" "gitk" magit-run-gitk) + ("a" "gitk --all" magit-run-gitk-all) + ("b" "gitk --branches" magit-run-gitk-branches) + ("g" "git gui" magit-run-git-gui)]]) ;;;###autoload (defun magit-git-command (command) @@ -610,8 +575,10 @@ For X11 something like ~/.xinitrc should work.\n" (require 'magit-obsolete) (require 'magit-submodule) (unless (load "magit-autoloads" t t) + (require 'magit-patch) (require 'magit-subtree) (require 'magit-ediff) + (require 'magit-gitignore) (require 'magit-extras) (require 'git-rebase) (require 'magit-imenu) diff --git a/elpa/magit-20190514.1814/magit.info b/elpa/magit-20190514.1814/magit.info new file mode 100644 index 00000000..828b23c9 --- /dev/null +++ b/elpa/magit-20190514.1814/magit.info @@ -0,0 +1,191 @@ +This is magit.info, produced by makeinfo version 6.5 from magit.texi. + + Copyright (C) 2015-2019 Jonas Bernoulli + + You can redistribute this document and/or modify it under the terms + of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. + + This document is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Magit: (magit). Using Git from Emacs with Magit. +END-INFO-DIR-ENTRY + + +Indirect: +magit.info-1: 754 +magit.info-2: 303558 + +Tag Table: +(Indirect) +Node: Top754 +Node: Introduction6475 +Node: Installation11198 +Node: Installing from Melpa11528 +Node: Installing from the Git Repository12601 +Node: Post-Installation Tasks14949 +Node: Getting Started16234 +Node: Interface Concepts21683 +Node: Modes and Buffers22044 +Node: Switching Buffers23793 +Node: Naming Buffers28563 +Node: Quitting Windows31870 +Node: Automatic Refreshing of Magit Buffers33616 +Node: Automatic Saving of File-Visiting Buffers36468 +Node: Automatic Reverting of File-Visiting Buffers37653 +Node: Risk of Reverting Automatically42648 +Node: Sections45030 +Node: Section Movement45956 +Node: Section Visibility50053 +Node: Section Hooks56130 +Node: Section Types and Values58537 +Node: Section Options59840 +Node: Transient Commands60312 +Node: Transient Arguments and Buffer Variables61549 +Node: Completion Confirmation and the Selection68567 +Node: Action Confirmation69011 +Node: Completion and Confirmation76361 +Node: The Selection79547 +Node: The hunk-internal region82446 +Node: Support for Completion Frameworks83535 +Node: Additional Completion Options88351 +Node: Running Git88950 +Node: Viewing Git Output89223 +Node: Git Process Status90356 +Node: Running Git Manually91321 +Node: Git Executable93795 +Node: Global Git Arguments96077 +Node: Inspecting96883 +Node: Status Buffer98040 +Node: Status Sections102030 +Node: Status Header Sections106833 +Node: Status Module Sections109463 +Node: Status Options111968 +Node: Repository List113722 +Node: Logging115880 +Node: Refreshing Logs118443 +Node: Log Buffer119889 +Node: Log Margin123745 +Node: Select from Log126434 +Node: Reflog128538 +Node: Cherries130074 +Node: Diffing131801 +Node: Refreshing Diffs134882 +Node: Commands Available in Diffs138461 +Node: Diff Options140996 +Node: Revision Buffer146034 +Node: Ediffing149363 +Node: References Buffer153011 +Node: References Sections163172 +Node: Bisecting164033 +Node: Visiting Files and Blobs165846 +Node: General-Purpose Visit Commands166316 +Node: Visiting Files and Blobs from a Diff167272 +Node: Blaming170731 +Node: Manipulating177294 +Node: Creating Repository177636 +Node: Cloning Repository178191 +Node: Staging and Unstaging183434 +Node: Staging from File-Visiting Buffers187517 +Node: Applying188685 +Node: Committing190578 +Node: Initiating a Commit191161 +Node: Editing Commit Messages194546 +Node: Branching204938 +Node: The Two Remotes205164 +Node: Branch Commands207817 +Node: Branch Git Variables220201 +Node: Auxiliary Branch Commands225592 +Node: Merging226710 +Node: Resolving Conflicts230718 +Node: Rebasing235719 +Node: Editing Rebase Sequences240729 +Node: Information About In-Progress Rebase245057 +Ref: Information About In-Progress Rebase-Footnote-1253939 +Node: Cherry Picking254535 +Node: Reverting258866 +Node: Resetting260315 +Node: Stashing261969 +Node: Transferring266549 +Node: Remotes266771 +Node: Remote Commands266923 +Node: Remote Git Variables271004 +Node: Fetching273383 +Node: Pulling275737 +Node: Pushing276930 +Node: Plain Patches280538 +Node: Maildir Patches282035 +Node: Miscellaneous283549 +Node: Tagging283865 +Node: Notes285793 +Node: Submodules288165 +Node: Listing Submodules288383 +Node: Submodule Transient290311 +Node: Subtree292833 +Node: Worktree294809 +Node: Common Commands295824 +Node: Wip Modes297871 +Node: Wip Graph303558 +Node: Legacy Wip Modes305872 +Node: Minor Mode for Buffers Visiting Files308767 +Node: Minor Mode for Buffers Visiting Blobs315879 +Node: Customizing316692 +Node: Per-Repository Configuration318288 +Node: Essential Settings319937 +Node: Safety320261 +Node: Performance322026 +Node: Microsoft Windows Performance328874 +Node: MacOS Performance330065 +Ref: MacOS Performance-Footnote-1331301 +Ref: MacOS Performance-Footnote-2331383 +Ref: MacOS Performance-Footnote-3331443 +Node: Plumbing331609 +Node: Calling Git332438 +Node: Getting a Value from Git333963 +Node: Calling Git for Effect337049 +Node: Section Plumbing343569 +Node: Creating Sections343797 +Node: Section Selection347697 +Node: Matching Sections349496 +Node: Refreshing Buffers355469 +Node: Conventions358617 +Node: Theming Faces358809 +Node: FAQ366924 +Node: FAQ - How to ...?367366 +Node: How to show git's output?367726 +Node: How to install the gitman info manual?368480 +Node: How to show diffs for gpg-encrypted files?369450 +Node: How does branching and pushing work?370046 +Node: Can Magit be used as ediff-version-control-package?370409 +Node: FAQ - Issues and Errors372398 +Node: Magit is slow373330 +Node: I changed several thousand files at once and now Magit is unusable373544 +Node: I am having problems committing374273 +Node: I am using MS Windows and cannot push with Magit374754 +Node: I am using OS X and SOMETHING works in shell but not in Magit375371 +Node: Diffs contain control sequences376177 +Node: Expanding a file to show the diff causes it to disappear377290 +Node: Point is wrong in the COMMIT_EDITMSG buffer377841 +Node: The mode-line information isn't always up-to-date378887 +Node: A branch and tag sharing the same name breaks SOMETHING379969 +Node: My Git hooks work on the command-line but not inside Magit380857 +Node: git-commit-mode isn't used when committing from the command-line381694 +Node: Point ends up inside invisible text when jumping to a file-visiting buffer383961 +Node: Debugging Tools384759 +Node: Keystroke Index386646 +Node: Command Index420360 +Node: Function Index457115 +Node: Variable Index472677 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/magit-20190122.503/magit.info-1 b/elpa/magit-20190514.1814/magit.info-1 similarity index 80% rename from elpa/magit-20190122.503/magit.info-1 rename to elpa/magit-20190514.1814/magit.info-1 index cb2ee676..f6040881 100644 --- a/elpa/magit-20190122.503/magit.info-1 +++ b/elpa/magit-20190514.1814/magit.info-1 @@ -31,7 +31,7 @@ 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. -This manual is for Magit version 2.90.1 (v2.90.1-96-g8a87e935+1). +This manual is for Magit version 2.90.1 (v2.90.1-655-ge2308d9f4+1). Copyright (C) 2015-2019 Jonas Bernoulli @@ -76,7 +76,8 @@ Interface Concepts * Modes and Buffers:: * Sections:: -* Popup Buffers and Prefix Commands:: +* Transient Commands:: +* Transient Arguments and Buffer Variables:: * Completion, Confirmation and the Selection: Completion Confirmation and the Selection. * Running Git:: @@ -127,7 +128,7 @@ Inspecting * Ediffing:: * References Buffer:: * Bisecting:: -* Visiting Blobs:: +* Visiting Files and Blobs:: * Blaming:: Status Buffer @@ -151,7 +152,7 @@ Logging Diffing * Refreshing Diffs:: -* Diff Buffer:: +* Commands Available in Diffs:: * Diff Options:: * Revision Buffer:: @@ -161,9 +162,16 @@ References Buffer * References Sections:: +Visiting Files and Blobs + +* General-Purpose Visit Commands:: +* Visiting Files and Blobs from a Diff:: + + Manipulating -* Repository Setup:: +* Creating Repository:: +* Cloning Repository:: * Staging and Unstaging:: * Applying:: * Committing:: @@ -189,8 +197,8 @@ Committing Branching * The Two Remotes:: -* The Branch Popup:: -* The Branch Config Popup:: +* Branch Commands:: +* Branch Git Variables:: * Auxiliary Branch Commands:: @@ -211,13 +219,13 @@ Transferring * Fetching:: * Pulling:: * Pushing:: -* Creating and Sending Patches:: -* Applying Patches:: +* Plain Patches:: +* Maildir Patches:: Remotes -* The Remote Popup:: -* The Remote Config Popup:: +* Remote Commands:: +* Remote Git Variables:: Miscellaneous @@ -235,7 +243,7 @@ Miscellaneous Submodules * Listing Submodules:: -* Submodule Popup:: +* Submodule Transient:: Wip Modes @@ -453,7 +461,7 @@ File: magit.info, Node: Installing from the Git Repository, Next: Post-Install 2.2 Installing from the Git Repository ====================================== -Magit depends on the ‘dash’, ‘magit-popup’, and ‘with-editor’ libraries +Magit depends on the ‘dash’, ‘transient’ and ‘with-editor’ libraries which are available from Melpa and Melpa-Stable. Install them using ‘M-x package-install RET RET’. Of course you may also install them manually from their repository. @@ -467,14 +475,14 @@ them manually from their repository. $ make - If you haven’t installed ‘dash’, ‘magit-popup’ and ‘with-editor’ from + If you haven’t installed ‘dash’, ‘transient’ and ‘with-editor’ from Melpa or at ‘/path/to/magit/../’, then you have to tell ‘make’ where to find them. To do so create the file ‘/path/to/magit/config.mk’ with the following content before running ‘make’: LOAD_PATH = -L /path/to/magit/lisp LOAD_PATH += -L /path/to/dash - LOAD_PATH += -L /path/to/magit-popup + LOAD_PATH += -L /path/to/transient LOAD_PATH += -L /path/to/with-editor Finally add this to your init file: @@ -578,7 +586,7 @@ into origin/master", "Unpushed to origin/master", and many others. Since we are starting from a safe state, which you can easily return to (by doing a ‘git reset --hard PRE-MAGIT-STATE’), there currently are -not staged or unstaged changes. Edit some files and save the changes. +no staged or unstaged changes. Edit some files and save the changes. Then go back to the status buffer, while at the same time refreshing it, by typing ‘C-x g’. (When the status buffer, or any Magit buffer for that matter, is the current buffer, then you can also use just ‘g’ to @@ -610,10 +618,10 @@ looks like it does in other buffers, then it doesn’t select Magit sections that can be acted on as a unit. And then of course you want to commit your changes. Type ‘c’. This -shows the committing popup buffer featuring various commit variants and -arguments that can be passed to ‘git commit’. Do not worry about those -for now. We want to create a "normal" commit, which is done by typing -‘c’ again. +shows the available commit commands and arguments in a buffer at the +bottom of the frame. Each command and argument is prefixed with the key +that invokes/sets it. Do not worry about this for now. We want to +create a "normal" commit, which is done by typing ‘c’ again. Now two new buffers appear. One is for writing the commit message, the other shows a diff with the changes that you are about to committed. @@ -621,26 +629,28 @@ Write a message and then type ‘C-c C-c’ to actually create the commit. You probably don’t want to push the commit you just created because you just committed some random changes, but if that is not the case you -could push it by typing ‘P’ to bring up the push popup and then ‘p’ to -push to a branch with the same name as the local branch onto the remote -configured as the push-remote. (If the push-remote is not configured -yet, then you would first be prompted for the remote to push to.) - - So far we have mentioned the commit, push, and log popups. These are -probably among the popups you will be using the most, but many others -exist. To show a popup that lists all other popups (as well as the -various apply commands and some other fundamental commands), type ‘h’. -Try a few. - - The key bindings in that popup correspond to the bindings in Magit -buffers, including but not limited to the status buffer. So you could -type ‘h d’ to bring up the diff popup, but once you remember that "d" -stands for "diff", you would usually do so by just typing ‘d’. But the -"popup of popups" is useful even once you have memorized all the -bindings, as it can provide easy access to Magit commands from non-Magit -buffers. You should create a global key binding for this command too: - - (global-set-key (kbd "C-x M-g") 'magit-dispatch-popup) +could push it by typing ‘P’ to show all the available push commands and +arguments and then ‘p’ to push to a branch with the same name as the +local branch onto the remote configured as the push-remote. (If the +push-remote is not configured yet, then you would first be prompted for +the remote to push to.) + + So far we have mentioned the commit, push, and log transient prefix +commands. These are probably among the transients you will be using the +most, but many others exist. To show a transient that lists all other +transients (as well as the various apply commands and some other +essential commands), type ‘h’. Try a few. + + The key bindings in that transient correspond to the bindings in +Magit buffers, including but not limited to the status buffer. So you +could type ‘h d’ to bring up the diff transient, but once you remember +that "d" stands for "diff", you would usually do so by just typing ‘d’. +But this "prefix of prefixes" is useful even once you have memorized all +the bindings, as it can provide easy access to Magit commands from +non-Magit buffers. You should create a global key binding for this +command too: + + (global-set-key (kbd "C-x M-g") 'magit-dispatch) In the same vein, you might also want to enable ‘global-magit-file-mode’ to get some more Magit key bindings in regular @@ -660,7 +670,8 @@ File: magit.info, Node: Interface Concepts, Next: Inspecting, Prev: Getting S * Modes and Buffers:: * Sections:: -* Popup Buffers and Prefix Commands:: +* Transient Commands:: +* Transient Arguments and Buffer Variables:: * Completion, Confirmation and the Selection: Completion Confirmation and the Selection. * Running Git:: @@ -913,8 +924,11 @@ File: magit.info, Node: Quitting Windows, Next: Automatic Refreshing of Magit ‘q’ (‘magit-mode-bury-buffer’) - This command buries the current Magit buffer. With a prefix - argument, it instead kills the buffer. + This command buries the current Magit buffer. + + With a prefix argument, it instead kills the buffer. With a double + prefix argument, also kills all other Magit buffers associated with + the current project. -- User Option: magit-bury-buffer-function @@ -954,9 +968,11 @@ File: magit.info, Node: Automatic Refreshing of Magit Buffers, Next: Automatic After running a command which may change the state of the current repository, the current Magit buffer and the corresponding status buffer -are refreshed. The status buffer may optionally be automatically -refreshed whenever a buffer is saved to a file inside the respective -repository. +are refreshed. The status buffer can be automatically refreshed +whenever a buffer is saved to a file inside the respective repository by +adding a hook, like so: + + (add-hook 'after-save-hook 'magit-after-save-refresh-status t) Automatically refreshing Magit buffers ensures that the displayed information is up-to-date most of the time but can lead to a noticeable @@ -1046,7 +1062,7 @@ File: magit.info, Node: Automatic Reverting of File-Visiting Buffers, Prev: Au By default Magit automatically reverts buffers that are visiting files that are being tracked in a Git repository, after they have changed on -disk. When using Magit one often changes files on disk by running git, +disk. When using Magit one often changes files on disk by running Git, i.e. "outside Emacs", making this a rather important feature. For example, if you discard a change in the status buffer, then that @@ -1057,13 +1073,13 @@ the visiting buffer before you could continue making changes. -- User Option: magit-auto-revert-mode - When this mode is enabled, then buffers that visit tracked files, - are automatically reverted after the visited files changed on disk. + When this mode is enabled, then buffers that visit tracked files + are automatically reverted after the visited files change on disk. -- User Option: global-auto-revert-mode When this mode is enabled, then any file-visiting buffer is - automatically reverted after the visited file changed on disk. + automatically reverted after the visited file changes on disk. If you like buffers that visit tracked files to be automatically reverted, then you might also like any buffer to be reverted, not @@ -1077,7 +1093,7 @@ the visiting buffer before you could continue making changes. If this is non-nil and either ‘global-auto-revert-mode’ or ‘magit-auto-revert-mode’ is enabled, then Magit immediately reverts buffers by explicitly calling ‘auto-revert-buffers’ after running - git for side-effects. + Git for side-effects. If ‘auto-revert-use-notify’ is non-nil (and file notifications are actually supported), then ‘magit-auto-revert-immediately’ does not @@ -1100,7 +1116,7 @@ the visiting buffer before you could continue making changes. repositories, including untracked files and files located inside Git’s control directory. - -- Command: auto-revert-mode + -- User Option: auto-revert-mode The global mode ‘magit-auto-revert-mode’ works by turning on this local mode in the appropriate buffers (but @@ -1116,7 +1132,7 @@ the visiting buffer before you could continue making changes. -- User Option: auto-revert-interval - This option controls for how many seconds Emacs waits before + This option controls how many seconds Emacs waits for before resuming suspended reverts. -- User Option: auto-revert-buffer-list-filter @@ -1125,15 +1141,15 @@ the visiting buffer before you could continue making changes. ‘auto-revert-buffers’ to determine whether a buffer should be reverted or not. - This option is provided by ‘magit’, which also redefines + This option is provided by Magit, which also advises ‘auto-revert-buffers’ to respect it. Magit users who do not turn on the local mode ‘auto-revert-mode’ themselves, are best served by - setting the value to ‘magit-auto-revert-repository-buffers-p’. + setting the value to ‘magit-auto-revert-repository-buffer-p’. - However the default is nil, to not disturb users who do use the - local mode directly. If you experience delays when running Magit - commands, then you should consider using one of the predicates - provided by Magit - especially if you also use Tramp. + However the default is nil, so as not to disturb users who do use + the local mode directly. If you experience delays when running + Magit commands, then you should consider using one of the + predicates provided by Magit - especially if you also use Tramp. Users who do turn on ‘auto-revert-mode’ in buffers in which Magit doesn’t do that for them, should likely not use any filter. Users @@ -1147,7 +1163,7 @@ the visiting buffer before you could continue making changes. reverted. The options with the ‘auto-revert-’ prefix are located in the Custom -group named ‘auto-revert’. The other, magit-specific, options are +group named ‘auto-revert’. The other, Magit-specific, options are located in the ‘magit’ group. * Menu: @@ -1160,20 +1176,20 @@ File: magit.info, Node: Risk of Reverting Automatically, Up: Automatic Reverti Risk of Reverting Automatically ............................... -For the vast majority users automatically reverting file-visiting +For the vast majority of users, automatically reverting file-visiting buffers after they have changed on disk is harmless. If a buffer is modified (i.e. it contains changes that haven’t been -saved yet), then Emacs would refuse to automatically revert it. If you +saved yet), then Emacs will refuse to automatically revert it. If you save a previously modified buffer, then that results in what is seen by -Git as an uncommitted change. Git would then refuse to carry out any +Git as an uncommitted change. Git will then refuse to carry out any commands that would cause these changes to be lost. In other words, if -there is anything that could be lost, then either Git or Emacs would +there is anything that could be lost, then either Git or Emacs will refuse to discard the changes. - However if you do use file-visiting buffers as a sort of ad hoc + However, if you use file-visiting buffers as a sort of ad hoc "staging area", then the automatic reverts could potentially cause data -loss. So far I have only heard from one user who uses such a workflow. +loss. So far I have heard from only one user who uses such a workflow. An example: You visit some file in a buffer, edit it, and save the changes. Then, outside of Emacs (or at least not using Magit or by @@ -1192,14 +1208,14 @@ get it back using the ‘undo’ command.) in the buffer, then you have to disable all Auto-Revert modes. But please consider that such a workflow would be dangerous even without using an Auto-Revert mode, and should therefore be avoided. If Emacs -crashed or if you quit Emacs by mistake, then you would also lose the +crashes or if you quit Emacs by mistake, then you would also lose the buffer content. There would be no autosave file still containing the intermediate version (because that was deleted when you saved the buffer) and you would not be asked whether you want to save the buffer (because it isn’t modified).  -File: magit.info, Node: Sections, Next: Popup Buffers and Prefix Commands, Prev: Modes and Buffers, Up: Interface Concepts +File: magit.info, Node: Sections, Next: Transient Commands, Prev: Modes and Buffers, Up: Interface Concepts 4.2 Sections ============ @@ -1463,10 +1479,16 @@ certain sections can also be overwritten using the hook • ‘(EXPANDABLE-BITMAP . COLLAPSIBLE-BITMAP)’ - Both values have to by variables whose values are fringe + Both values have to be variables whose values are fringe bitmaps. In this case every section that can be expanded or collapsed gets an indicator in the left fringe. + To provide extra padding around the indicator, set + ‘left-fringe-width’ in ‘magit-mode-hook’, e.g.: + + (add-hook 'magit-mode-hook (lambda () + (setq left-fringe-width 20))) + • ‘(STRING . BOOLEAN)’ In this case STRING (usually an ellipsis) is shown at the end @@ -1570,63 +1592,174 @@ certain type of sections. As you can see there are not many of those. only affects sections that could benefit from this information.  -File: magit.info, Node: Popup Buffers and Prefix Commands, Next: Completion Confirmation and the Selection, Prev: Sections, Up: Interface Concepts +File: magit.info, Node: Transient Commands, Next: Transient Arguments and Buffer Variables, Prev: Sections, Up: Interface Concepts -4.3 Popup Buffers and Prefix Commands -===================================== +4.3 Transient Commands +====================== -Many Magit commands are implemented using *popup buffers*. First the -user invokes a *popup* or *prefix* command, which causes a popup buffer -with the available *infix* arguments and *suffix* commands to be -displayed. The user then optionally toggles/sets some arguments and -finally invokes one of the suffix commands. +Many Magit commands are implemented as *transient* commands. First the +user invokes a *prefix* command, which causes its *infix* arguments and +*suffix* commands to be displayed in the echo area. The user then +optionally sets some infix arguments and finally invokes one of the +suffix commands. - This is implemented in the library ‘magit-popup’. Earlier releases -used the library ‘magit-key-mode’. A future release will switch to a -yet-to-be-written successor, which will likely be named ‘transient’. + This is implemented in the library ‘transient’. Earlier Magit +releases used the package ‘magit-popup’ and even earlier versions +library ‘magit-key-mode’. - Because ‘magit-popup’ can also be used by other packages without -having to depend on all of Magit, it is documented in its own manual. -See *note (magit-popup)Top::. + Transient is documented in *note (transient)Top::. -‘C-c C-c’ (‘magit-dispatch-popup’) +‘C-c C-c’ (‘magit-dispatch’) - This popup command shows a buffer featuring all other Magit popup - commands as well as some other commands that are not popup commands - themselves. + This transient prefix command binds most of Magit’s other prefix + commands as suffix commands and displays them in a temporary buffer + until one of them is invoked. Invoking such a sub-prefix causes + the suffixes of that command to be bound and displayed instead of + those of ‘magit-dispatch’. This command is also, or especially, useful outside Magit buffers, so you should setup a global binding: - (global-set-key (kbd "C-x M-g") 'magit-dispatch-popup) - - Most popups set their initial arguments according to the -corresponding ‘magit-*-arguments’ variable. Two popups, the log and -diff popups (see *note Logging:: and *note Diffing::), may behave a bit -differently, depending on the value of ‘magit-use-sticky-arguments’. - - -- User Option: magit-use-sticky-arguments - - This option controls how diff and log commands reuse arguments from - existing buffers. - - When ‘t’ (the default value), the log or diff popup reuses the - arguments from the current repository’s log or diff buffer, - respectively. When no log or diff buffer exists for the current - repository, these popups use the default value of - ‘magit-log-arguments’ or ‘magit-diff-arguments’. - - When ‘current’, log and diff popups will only reuse the arguments - if the current buffer is derived from ‘magit-log-mode’ or - ‘magit-diff-mode’, respectively. + (global-set-key (kbd "C-x M-g") 'magit-dispatch) - When ‘nil’, the default value of ‘magit-log-arguments’ or - ‘magit-diff-arguments’ is always used. + +File: magit.info, Node: Transient Arguments and Buffer Variables, Next: Completion Confirmation and the Selection, Prev: Transient Commands, Up: Interface Concepts + +4.4 Transient Arguments and Buffer Variables +============================================ + +The infix arguments of many of Magit’s transient prefix commands cease +to have an effect once the ‘git’ command that is called with those +arguments has returned. Commands that create a commit are a good +example for this. If the user changes the arguments, then that only +affects the next invocation of a suffix command. If the same transient +prefix command is later invoked again, then the arguments are initially +reset to the default value. This default value can be set for the +current Emacs session or saved permanently, see *note (transient)Saving +Values::. It is also possible to cycle through previously used sets of +arguments using ‘M-p’ and ‘M-n’, see *note (transient)Using History::. + + However the infix arguments of many other transient commands continue +to have an effect even after the ‘git’ command that was called with +those arguments has returned. The most important commands like this are +those that display a diff or log in a dedicated buffer. Their arguments +obviously continue to have an effect for as long as the respective diff +or log is being displayed. Furthermore the used arguments are stored in +buffer-local variables for future reference. + + For commands in the second group it isn’t always desirable to reset +their arguments to the global value when the transient prefix command is +invoked again. + + As mentioned above, it is possible to cycle through previously used +sets of arguments while a transient popup is visible. That means that +we could always reset the infix arguments to the default because the set +of arguments that is active in the existing buffer is only a few ‘M-p’ +away. Magit can be configured to behave like that, but because I expect +that most users would not find that very convenient, it is not the +default. + + Also note that it is possible to change the diff and log arguments +used in the current buffer (including the status buffer, which contains +both diff and log sections) using the respective "refresh" transient +prefix commands on ‘D’ and ‘L’. (‘d’ and ‘l’ on the other hand are +intended to change *what* diff or log is being displayed. It is +possible to also change *how* the diff or log is being displayed at the +same time, but if you only want to do the latter, then you should use +the refresh variants.) Because these secondary diff and log transient +prefixes are about *changing* the arguments used in the current buffer, +they *always* start out with the set of arguments that are currently in +effect in that buffer. + + Some commands are usually invoked directly even though they can also +be invoked as the suffix of a transient prefix command. Most +prominently ‘magit-show-commit’ is usually invoked by typing ‘RET’ while +point is on a commit in a log, but it can also be invoked from the +‘magit-diff’ transient prefix. + + When such a command is invoked directly, then it is important to +reuse the arguments as specified by the respective buffer-local values, +instead of using the default arguments. Imagine you press ‘RET’ in a +log to display the commit at point in a different buffer and then use +‘D’ to change how the diff is displayed in that buffer. And then you +press ‘RET’ on another commit to show that instead and the diff +arguments are reset to the default. Not cool; so Magit does not do that +by default. + + -- User Option: magit-prefix-use-buffer-arguments + + This option controls whether the infix arguments initially shown in + certain transient prefix commands are based on the arguments that + are currently in effect in the buffer that their suffixes update. + + The ‘magit-diff’ and ‘magit-log’ transient prefix commands are + affected by this option. + + -- User Option: magit-direct-use-buffer-arguments + + This option controls whether certain commands, when invoked + directly (i.e. not as the suffix of a transient prefix command), + use the arguments that are currently active in the buffer that they + are about to update. The alternative is to use the default value + for these arguments, which might change the arguments that are used + in the buffer. + +Valid values for both of the above options are: + + • ‘always’: Always use the set of arguments that is currently active + in the respective buffer, provided that buffer exists of course. + + • ‘selected’ or ‘t’: Use the set of arguments from the respective + buffer, but only if it is displayed in a window of the current + frame. This is the default for both variables. + + • ‘current’: Use the set of arguments from the respective buffer, but + only if it is the current buffer. + + • ‘never’: Never use the set of arguments from the respective buffer. + +I am afraid it gets more complicated still: + + • The global diff and log arguments are set for each support mode + individually. The diff arguments for example have different values + in ‘magit-diff-mode’, ‘magit-revision-mode’, + ‘magit-merge-preview-mode’ and ‘magit-status-mode’ buffers. + Setting or saving the value for one mode does not change the value + for other modes. The history however is shared. + + • When ‘magit-show-commit’ is invoked directly from a log buffer, + then the file filter is picked up from that buffer, not from the + revision buffer and or the mode’s global diff arguments. + + • Even though they are suffixes of the diff prefix + ‘magit-show-commit’ and ‘magit-stash-show’ do not use the diff + buffer used by the diff commands, instead they use the dedicated + revision and stash buffers. + + At the time you invoke the diff prefix it is unknown to Magit which + of the suffix commands you are going to invoke. While not certain, + more often than not users invoke one of the commands that use the + diff buffer, so the initial infix arguments are those used in that + buffer. However if you invoke one of these commands directly, then + Magit knows that it should use the arguments from the revision + resp. stash buffer. + + • The log prefix also features reflog commands, but these commands do + not use the log arguments. + + • If ‘magit-show-refs’ is invoked from a ‘magit-refs-mode’ buffer, + then it acts as a refresh prefix and therefore unconditionally uses + the buffer’s arguments as initial arguments. If it is invoked + elsewhere with a prefix argument, then it acts as regular prefix + and therefore respects ‘magit-prefix-use-buffer-arguments’. If it + is invoked elsewhere without a prefix argument, then it acts as a + direct command and therefore respects + ‘magit-direct-use-buffer-arguments’.  -File: magit.info, Node: Completion Confirmation and the Selection, Next: Running Git, Prev: Popup Buffers and Prefix Commands, Up: Interface Concepts +File: magit.info, Node: Completion Confirmation and the Selection, Next: Running Git, Prev: Transient Arguments and Buffer Variables, Up: Interface Concepts -4.4 Completion, Confirmation and the Selection +4.5 Completion, Confirmation and the Selection ============================================== * Menu: @@ -1641,7 +1774,7 @@ File: magit.info, Node: Completion Confirmation and the Selection, Next: Runni  File: magit.info, Node: Action Confirmation, Next: Completion and Confirmation, Up: Completion Confirmation and the Selection -4.4.1 Action Confirmation +4.5.1 Action Confirmation ------------------------- By default many actions that could potentially lead to data loss have to @@ -1734,8 +1867,8 @@ telling Magit to ask fewer questions. branch), but when a branch has not been merged yet, also make sure the user is aware of that. - • ‘delete-pr-branch’ When deleting a branch that was - created from a pull request and if no other branches + • ‘delete-pr-remote’ When deleting a branch that was + created from a pull-request and if no other branches still exist on that remote, then ‘magit-branch-delete’ offers to delete the remote as well. This should be safe because it only happens if no other refs exist in the @@ -1761,7 +1894,7 @@ telling Magit to ask fewer questions. • ‘rebase-published’ Affects commands that perform interactive rebases. This includes commands from the - commit popup that modify a commit other than "HEAD", + commit transient that modify a commit other than "HEAD", namely the various fixup and squash variants. • ‘edit-published’ Affects the commands @@ -1799,7 +1932,7 @@ telling Magit to ask fewer questions.  File: magit.info, Node: Completion and Confirmation, Next: The Selection, Prev: Action Confirmation, Up: Completion Confirmation and the Selection -4.4.2 Completion and Confirmation +4.5.2 Completion and Confirmation --------------------------------- Many Magit commands ask the user to select from a list of possible @@ -1865,7 +1998,7 @@ or without confirmation.  File: magit.info, Node: The Selection, Next: The hunk-internal region, Prev: Completion and Confirmation, Up: Completion Confirmation and the Selection -4.4.3 The Selection +4.5.3 The Selection ------------------- If the region is active, then many Magit commands act on the things that @@ -1923,7 +2056,7 @@ happen.  File: magit.info, Node: The hunk-internal region, Next: Support for Completion Frameworks, Prev: The Selection, Up: Completion Confirmation and the Selection -4.4.4 The hunk-internal region +4.5.4 The hunk-internal region ------------------------------ Somewhat related to the Magit selection described in the previous @@ -1947,7 +2080,7 @@ instead of on the complete hunk.  File: magit.info, Node: Support for Completion Frameworks, Next: Additional Completion Options, Prev: The hunk-internal region, Up: Completion Confirmation and the Selection -4.4.5 Support for Completion Frameworks +4.5.5 Support for Completion Frameworks --------------------------------------- The built-in option ‘completing-read-function’ specifies the low-level @@ -2045,7 +2178,7 @@ You will also have to install the ‘ido-completing-read+’ package and use  File: magit.info, Node: Additional Completion Options, Prev: Support for Completion Frameworks, Up: Completion Confirmation and the Selection -4.4.6 Additional Completion Options +4.5.6 Additional Completion Options ----------------------------------- -- User Option: magit-list-refs-sortby @@ -2059,7 +2192,7 @@ File: magit.info, Node: Additional Completion Options, Prev: Support for Compl  File: magit.info, Node: Running Git, Prev: Completion Confirmation and the Selection, Up: Interface Concepts -4.5 Running Git +4.6 Running Git =============== * Menu: @@ -2073,7 +2206,7 @@ File: magit.info, Node: Running Git, Prev: Completion Confirmation and the Sel  File: magit.info, Node: Viewing Git Output, Next: Git Process Status, Up: Running Git -4.5.1 Viewing Git Output +4.6.1 Viewing Git Output ------------------------ Magit runs Git either for side-effects (e.g. when pushing) or to get @@ -2107,7 +2240,7 @@ sections are available. There is one additional command.  File: magit.info, Node: Git Process Status, Next: Running Git Manually, Prev: Viewing Git Output, Up: Running Git -4.5.2 Git Process Status +4.6.2 Git Process Status ------------------------ When a Git process is running for side-effects, Magit displays an @@ -2131,7 +2264,7 @@ buffer.  File: magit.info, Node: Running Git Manually, Next: Git Executable, Prev: Git Process Status, Up: Running Git -4.5.3 Running Git Manually +4.6.3 Running Git Manually -------------------------- While Magit provides many Emacs commands to interact with Git, it does @@ -2140,9 +2273,10 @@ come in handy. Magit provides some commands for running arbitrary Git commands by typing them into the minibuffer, instead of having to switch to a shell. -‘!’ (‘magit-run-popup’) +‘!’ (‘magit-run’) - Shows the popup buffer featuring the below suffix commands. + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. ‘! !’ (‘magit-git-command-topdir’) @@ -2200,7 +2334,7 @@ to a shell.  File: magit.info, Node: Git Executable, Next: Global Git Arguments, Prev: Running Git Manually, Up: Running Git -4.5.4 Git Executable +4.6.4 Git Executable -------------------- Except on MS Windows, Magit defaults to running Git without specifying @@ -2249,7 +2383,7 @@ machine, then you must change the value to "git".  File: magit.info, Node: Global Git Arguments, Prev: Git Executable, Up: Running Git -4.5.5 Global Git Arguments +4.6.5 Global Git Arguments -------------------------- -- User Option: magit-git-global-arguments @@ -2296,7 +2430,7 @@ described later. * Ediffing:: * References Buffer:: * Bisecting:: -* Visiting Blobs:: +* Visiting Files and Blobs:: * Blaming::  @@ -2808,16 +2942,17 @@ File: magit.info, Node: Logging, Next: Diffing, Prev: Repository List, Up: I =========== The status buffer contains logs for the unpushed and unpulled commits, -but that obviously isn’t enough. The prefix command ‘magit-log-popup’, -on ‘l’, features several suffix commands, which show a specific log in a -separate log buffer. - - Like other popups, the log popup also features several arguments that -can be changed before invoking one of the suffix commands. However, in -the case of the log popup, these arguments may be taken from those -currently in use in the current repository’s log buffer, depending on -the value of ‘magit-use-sticky-arguments’ (see *note Popup Buffers and -Prefix Commands::). +but that obviously isn’t enough. The transient prefix command +‘magit-log’, on ‘l’, features several suffix commands, which show a +specific log in a separate log buffer. + + Like other transient prefix commands, ‘magit-log’ also features +several infix arguments that can be changed before invoking one of the +suffix commands. However, in the case of the log transient, these +arguments may be taken from those currently in use in the current +repository’s log buffer, depending on the value of +‘magit-prefix-use-buffer-arguments’ (see *note Transient Arguments and +Buffer Variables::). For information about the various arguments, see *note (gitman)git-log::. @@ -2826,13 +2961,14 @@ Prefix Commands::). ‘--author-date-order’, ‘--date-order’, or ‘--topo-order’ before being passed to ‘git log’. - The log popup also features several reflog commands. See *note + The log transient also features several reflog commands. See *note Reflog::. -‘l’ (‘magit-log-popup’) +‘l’ (‘magit-log’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘l l’ (‘magit-log-current’) @@ -2883,15 +3019,16 @@ File: magit.info, Node: Refreshing Logs, Next: Log Buffer, Up: Logging 5.3.1 Refreshing Logs --------------------- -The prefix command ‘magit-log-refresh-popup’, on ‘L’, can be used to +The transient prefix command ‘magit-log-refresh’, on ‘L’, can be used to change the log arguments used in the current buffer, without changing which log is shown. This works in dedicated log buffers, but also in the status buffer. -‘L’ (‘magit-log-refresh-popup’) +‘L’ (‘magit-log-refresh’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘L g’ (‘magit-log-refresh’) @@ -2923,11 +3060,13 @@ File: magit.info, Node: Log Buffer, Next: Log Margin, Prev: Refreshing Logs, 5.3.2 Log Buffer ---------------- -‘L’ (‘magit-log-refresh-popup’) +‘L’ (‘magit-log-refresh’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. See *note - Refreshing Logs::. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + See *note Refreshing Logs::. ‘q’ (‘magit-log-bury-buffer’) @@ -3015,7 +3154,7 @@ visible. For example: feature origin/feature [blue-] [green-------] - Also note that while the popup features the ‘--show-signature’ + Also note that while the transient features the ‘--show-signature’ argument, that won’t actually be used when enabled, because Magit defaults to use just one line per commit. Instead the commit colorized to indicate the validity of the signed commit object, using the faces @@ -3070,14 +3209,14 @@ used in the default of all other options. But setting it to ‘t’, i.e. re-enforcing the default for that option, does not carry to other options. -‘L’ (‘magit-margin-popup’) +‘L’ (‘magit-margin-settings’) - This prefix command features the following commands for changing - the appearance of the margin. + This transient prefix command binds the following suffix commands, + each of which changes the appearance of the margin in some way. - In some buffers that support the margin, "L" is bound to -‘magit-log-refresh-popup’, but that popup features the same commands, -and then some other unrelated commands. + In some buffers that support the margin, ‘L’ is instead bound to +‘magit-log-refresh’, but that transient features the same commands, and +then some other unrelated commands. ‘L L’ (‘magit-toggle-margin’) @@ -3155,8 +3294,8 @@ File: magit.info, Node: Reflog, Next: Cherries, Prev: Select from Log, Up: L Also see *note (gitman)git-reflog::. - These reflog commands are available from the log popup. See *note -Logging::. + These reflog commands are available from the log transient. See +*note Logging::. ‘l r’ (‘magit-reflog-current’) @@ -3251,23 +3390,25 @@ File: magit.info, Node: Diffing, Next: Ediffing, Prev: Logging, Up: Inspecti =========== The status buffer contains diffs for the staged and unstaged commits, -but that obviously isn’t enough. The prefix command ‘magit-diff-popup’, -on ‘d’, features several suffix commands, which show a specific diff in -a separate diff buffer. - - Like other popups, the diff popup also features several arguments -that can be changed before invoking one of the suffix commands. -However, in the case of the diff popup, these arguments may be taken -from those currently in use in the current repository’s log buffer, -depending on the value of ‘magit-use-sticky-arguments’ (see *note Popup -Buffers and Prefix Commands::). +but that obviously isn’t enough. The transient prefix command +‘magit-diff’, on ‘d’, features several suffix commands, which show a +specific diff in a separate diff buffer. + + Like other transient prefix commands, ‘magit-diff’ also features +several infix arguments that can be changed before invoking one of the +suffix commands. However, in the case of the diff transient, these +arguments may be taken from those currently in use in the current +repository’s diff buffer, depending on the value of +‘magit-prefix-use-buffer-arguments’ (see *note Transient Arguments and +Buffer Variables::). Also see *note (gitman)git-diff::. -‘d’ (‘magit-diff-popup’) +‘d’ (‘magit-diff’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘d d’ (‘magit-diff-dwim’) @@ -3308,7 +3449,7 @@ Buffers and Prefix Commands::). Show changes between any two files on disk. All of the above suffix commands update the repository’s diff buffer. -The diff popup also features two commands which show differences in +The diff transient also features two commands which show differences in another buffer: ‘d c’ (‘magit-show-commit’) @@ -3327,25 +3468,26 @@ Buffers Visiting Files::. * Menu: * Refreshing Diffs:: -* Diff Buffer:: +* Commands Available in Diffs:: * Diff Options:: * Revision Buffer::  -File: magit.info, Node: Refreshing Diffs, Next: Diff Buffer, Up: Diffing +File: magit.info, Node: Refreshing Diffs, Next: Commands Available in Diffs, Up: Diffing 5.4.1 Refreshing Diffs ---------------------- -The prefix command ‘magit-diff-refresh-popup’, on ‘D’, can be used to -change the diff arguments used in the current buffer, without changing -which diff is shown. This works in dedicated diff buffers, but also in -the status buffer. +The transient prefix command ‘magit-diff-refresh’, on ‘D’, can be used +to change the diff arguments used in the current buffer, without +changing which diff is shown. This works in dedicated diff buffers, but +also in the status buffer. -‘D’ (‘magit-diff-refresh-popup’) +‘D’ (‘magit-diff-refresh’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘D g’ (‘magit-diff-refresh’) @@ -3391,8 +3533,8 @@ the status buffer. useful when you display a revision from a log buffer that is restricted to a file or files. - In addition to the above popup, which allows changing any of the -supported arguments, there also exist some commands which change a + In addition to the above transient, which allows changing any of the +supported arguments, there also exist some commands that change only a particular argument. ‘-’ (‘magit-diff-less-context’) @@ -3409,7 +3551,7 @@ particular argument. height. The following commands quickly change what diff is being displayed -without having to using one of the diff popups. +without having to using one of the diff transient. ‘C-c C-d’ (‘magit-diff-while-committing’) @@ -3430,95 +3572,41 @@ without having to using one of the diff popups. This command moves forward in current buffer’s history.  -File: magit.info, Node: Diff Buffer, Next: Diff Options, Prev: Refreshing Diffs, Up: Diffing - -5.4.2 Diff Buffer ------------------ - -These commands are available in diff buffers. - -‘RET’ (‘magit-diff-visit-file’) - - From a diff, visit the corresponding file at the appropriate - position. - - If the diff shows changes in the worktree, the index, or ‘HEAD’, - then visit the actual file. Otherwise, when the diff is about an - older commit or a range, then visit the appropriate blob. - - If point is on a removed line, then visit the blob for the first - parent of the commit which removed that line, i.e. the last commit - where that line still existed. Otherwise visit the blob for the - commit whose changes are being shown. - - Interactively, when the file or blob to be displayed is already - being displayed in another window of the same frame, then just - select that window and adjust point. Otherwise, or with a prefix - argument, display the buffer in another window. The meaning of the - prefix argument can be inverted or further modified using the - option ‘magit-display-file-buffer-function’. +File: magit.info, Node: Commands Available in Diffs, Next: Diff Options, Prev: Refreshing Diffs, Up: Diffing - Non-interactively the optional OTHER-WINDOW argument is taken - literally. DISPLAY-FN can be used to specify the display function - explicitly, in which case OTHER-WINDOW is ignored. - - The optional FORCE-WORKTREE means to force visiting the worktree - version of the file. To do this interactively use the command - ‘magit-diff-visit-file-worktree’ instead. - - -- User Option: magit-diff-visit-previous-blob - - This option controls whether ‘magit-diff-visit-file’ may visit the - previous blob. When this is ‘t’ and point is on a removed line in - a diff for a committed change, then ‘magit-diff-visit-file’ visits - the blob from the last revision which still had that line. - - Currently this is only supported for committed changes, for staged - and unstaged changes ‘magit-diff-visit-file’ always visits the file - in the working tree. - -‘C-’ (‘magit-diff-visit-file-worktree’) - - From a diff, visit the corresponding file at the appropriate - position. - - When the file is already being displayed in another window of the - same frame, then just select that window and adjust point. With a - prefix argument also display in another window. - - The actual file in the worktree is visited. The positions in the - hunk headers get less useful the "older" the changes are, and as a - result, jumping to the appropriate position gets less reliable. +5.4.2 Commands Available in Diffs +--------------------------------- - Also see ‘magit-diff-visit-file’, which visits the respective blob, - unless the diff shows changes in the worktree, the index, or - ‘HEAD’. +Some commands are only available if point is inside a diff. - -- Command: magit-diff-visit-file-other-window - - From a diff, visit the corresponding file at the appropriate - position in another window. + ‘magit-diff-visit-file’ and related commands visit the appropriate +version of the file that the diff at point is about. Likewise +‘magit-diff-visit-worktree-file’ and related commands visit the worktree +version of the file that the diff at point is about. See *note Visiting +Files and Blobs from a Diff:: for more information and the key bindings. ‘C-c C-t’ (‘magit-diff-trace-definition’) - From a diff, show log for the definition at point. + This command shows a log for the definition at point. -- User Option: magit-log-trace-definition-function - The function used by ‘magit-log-trace-definition’ to determine the - function at point. For major-modes that have special needs, you - could set that using the mode’s hook. + The function specfied by this option is used by + ‘magit-log-trace-definition’ to determine the function at point. + For major-modes that have special needs, you could set the local + value using the mode’s hook. ‘C-c C-e’ (‘magit-diff-edit-hunk-commit’) - From a hunk, edit the respective commit and visit the file. + From a hunk, this command edits the respective commit and visits + the file. - First visit the file being modified by the hunk at the correct + First it visits the file being modified by the hunk at the correct location using ‘magit-diff-visit-file’. This actually visits a blob. When point is on a diff header, not within an individual hunk, then this visits the blob the first hunk is about. - Then invoke ‘magit-edit-line-commit’, which uses an interactive + Then it invokes ‘magit-edit-line-commit’, which uses an interactive rebase to make the commit editable, or if that is not possible because the commit is not reachable from ‘HEAD’ by checking out that commit directly. This also causes the actual worktree file to @@ -3530,20 +3618,25 @@ These commands are available in diff buffers. ‘j’ (‘magit-jump-to-diffstat-or-diff’) - Jump to the diffstat or diff. When point is on a file inside the - diffstat section, then jump to the respective diff section. - Otherwise, jump to the diffstat section or a child thereof. + This command jumps to the diffstat or diff. When point is on a + file inside the diffstat section, then jump to the respective diff + section. Otherwise, jump to the diffstat section or a child + thereof. + + The next two commands are not specific to Magit-Diff mdoe (or and +Magit buffer for that matter), but it might be worth pointing out that +they are available here too. ‘SPC’ (‘scroll-up’) - Scroll text upward. + This command scrolls text upward. ‘DEL’ (‘scroll-down’) - Scroll text downward. + This command scrolls text downward.  -File: magit.info, Node: Diff Options, Next: Revision Buffer, Prev: Diff Buffer, Up: Diffing +File: magit.info, Node: Diff Options, Next: Revision Buffer, Prev: Commands Available in Diffs, Up: Diffing 5.4.3 Diff Options ------------------ @@ -3732,15 +3825,26 @@ File: magit.info, Node: Revision Buffer, Prev: Diff Options, Up: Diffing restricted to a subset of the changed files. If the revision buffer is displayed from a log buffer, the revision buffer will share the same file restriction as that log buffer (also see the command -‘magit-diff-toggle-file-filter’). Note, however, that the log’s file -restriction will be ignored when ‘magit-log-arguments’ includes -‘--follow’. In this case, the ‘-u’ argument of the log popup can be -used to show the file-restricted diffs inline. +‘magit-diff-toggle-file-filter’). + + -- User Option: magit-revision-filter-files-on-follow + + Whether showing a commit from a log buffer honors the log’s file + filter when the log arguments include ‘--follow’. + + When this option is nil, displaying a commit from a log ignores the + log’s file filter if the log arguments include ‘--follow’. Doing + so avoids showing an empty diff in revision buffers for commits + before a rename event. In such cases, the ‘--patch’ argument of + the log transient can be used to show the file-restricted diffs + inline. + + Set this option to non-nil to keep the log’s file restriction even + if ‘--follow’ is present in the log arguments. If the revision buffer is not displayed from a log buffer, the file -restriction is determined by the file restriction in the repository’s -diff buffer, if it exists, and the value of the option -‘magit-use-sticky-arguments’. +restriction is determined as usual (see *note Transient Arguments and +Buffer Variables::).  File: magit.info, Node: Ediffing, Next: References Buffer, Prev: Diffing, Up: Inspecting @@ -3763,10 +3867,10 @@ information on how to use Ediff itself, see *note (ediff)Top::. be used explicitly. If it cannot read the user’s mind at all, then it asks the user for a command to run. -‘E’ (‘magit-ediff-popup’) +‘E’ (‘magit-ediff’) - This prefix command shows the following suffix commands in a popup - buffer. + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. ‘E r’ (‘magit-ediff-compare’) @@ -3846,28 +3950,36 @@ File: magit.info, Node: References Buffer, Next: Bisecting, Prev: Ediffing, 5.6 References Buffer ===================== -‘y’ (‘magit-show-refs-popup’) +‘y’ (‘magit-show-refs’) + + This command lists branches and tags in a dedicated buffer. + + However if this command is invoked again from this buffer or if it + is invoked with a prefix argument, then it acts as a transient + prefix command, which binds the following suffix commands and some + infix arguments. - List and compare references in a dedicated buffer. By default all - refs are compared with ‘HEAD’, but with a prefix argument this - command instead acts as a prefix command and shows the following - suffix commands along with the appropriate infix arguments in a - popup buffer. + All of the following suffix commands list exactly the same branches +and tags. The only difference the optional feature that can be enabled +by changing the value of ‘magit-refs-show-commit-count’ (see below). +These commands specify a different branch or commit against which all +the other references are compared. ‘y y’ (‘magit-show-refs-head’) - List and compare references in a dedicated buffer. Refs are - compared with ‘HEAD’. + This command lists branches and tags in a dedicated buffer. Each + reference is being compared with ‘HEAD’. ‘y c’ (‘magit-show-refs-current’) - List and compare references in a dedicated buffer. Refs are - compared with the current branch or ‘HEAD’ if it is detached. + This command lists branches and tags in a dedicated buffer. Each + reference is being compared with the current branch or ‘HEAD’ if it + is detached. -‘y o’ (‘magit-show-refs’) +‘y o’ (‘magit-show-refs-other’) - List and compare references in a dedicated buffer. Refs are - compared with a branch read from the user. + This command lists branches and tags in a dedicated buffer. Each + reference is being compared with a branch read from the user. -- User Option: magit-refs-show-commit-count @@ -4115,20 +4227,20 @@ status buffer. Insert sections showing all tags.  -File: magit.info, Node: Bisecting, Next: Visiting Blobs, Prev: References Buffer, Up: Inspecting +File: magit.info, Node: Bisecting, Next: Visiting Files and Blobs, Prev: References Buffer, Up: Inspecting 5.7 Bisecting ============= Also see *note (gitman)git-bisect::. -‘B’ (‘magit-bisect-popup’) +‘B’ (‘magit-bisect’) - This prefix command shows the following suffix commands in a popup - buffer. + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. - When bisecting is not in progress, then the popup buffer features the -following commands. + When bisecting is not in progress, then the transient features the +following suffix commands. ‘B B’ (‘magit-bisect-start’) @@ -4142,8 +4254,8 @@ following commands. Bisect automatically by running commands after each step. - When bisecting is in progress, then the popup buffer features these -commands instead. + When bisecting in progress, then the transient instead features the +following suffix commands. ‘B b’ (‘magit-bisect-bad’) @@ -4175,43 +4287,164 @@ bisect session. commits that still have to be bisected.  -File: magit.info, Node: Visiting Blobs, Next: Blaming, Prev: Bisecting, Up: Inspecting +File: magit.info, Node: Visiting Files and Blobs, Next: Blaming, Prev: Bisecting, Up: Inspecting + +5.8 Visiting Files and Blobs +============================ -5.8 Visiting Blobs -================== +Magit provides several commands that visit a file or blob (the version +of a file that is stored in a certain commit). Actually it provides +several *groups* of such commands and the several *variants* within each +group. + +* Menu: + +* General-Purpose Visit Commands:: +* Visiting Files and Blobs from a Diff:: + + +File: magit.info, Node: General-Purpose Visit Commands, Next: Visiting Files and Blobs from a Diff, Up: Visiting Files and Blobs -‘M-x magit-find-file’ (‘magit-find-file’) +5.8.1 General-Purpose Visit Commands +------------------------------------ - View FILE from REV. Switch to a buffer visiting blob REV:FILE, - creating one if none already exists. +These commands can be used anywhere to open any blob. Currently no keys +are bound to these commands by default, but that is likely to change. -‘M-x magit-find-file-other-window’ (‘magit-find-file-other-window’) + -- Command: magit-find-file - View FILE from REV, in another window. Like ‘magit-find-file’, but - create a new window or reuse an existing one. + This command reads a filename and revision from the user and visits + the respective blob in a buffer. The buffer is displayed in the + selected window. + + -- Command: magit-find-file-other-window + + This command reads a filename and revision from the user and visits + the respective blob in a buffer. The buffer is displayed in + another window. + + -- Command: magit-find-file-other-frame + + This command reads a filename and revision from the user and visits + the respective blob in a buffer. The buffer is displayed in + another frame.  -File: magit.info, Node: Blaming, Prev: Visiting Blobs, Up: Inspecting +File: magit.info, Node: Visiting Files and Blobs from a Diff, Prev: General-Purpose Visit Commands, Up: Visiting Files and Blobs + +5.8.2 Visiting Files and Blobs from a Diff +------------------------------------------ + +These commands can only be used when point is inside a diff. + +‘RET’ (‘magit-diff-visit-file’) + + This command visits the appropriate version of the file that the + diff at point is about. + + This commands visits the worktree version of the appropriate file. + The location of point inside the diff determines which file is + being visited. The visited version depends on what changes the + diff is about. + + • If the diff shows uncommitted changes (i.e. staged or + unstaged changes), then visit the file in the working tree + (i.e. the same "real" file that ‘find-file’ would visit. In + all other cases visit a "blob" (i.e. the version of a file as + stored in some commit). + + • If point is on a removed line, then visit the blob for the + first parent of the commit that removed that line, i.e. the + last commit where that line still exists. + + • If point is on an added or context line, then visit the blob + that adds that line, or if the diff shows from more than a + single commit, then visit the blob from the last of these + commits. + + In the file-visiting buffer this command goes to the line that + corresponds to the line that point is on in the diff. + + The buffer is displayed in the selected window. With a prefix + argument the buffer is displayed in another window instead. + + -- User Option: magit-diff-visit-previous-blob + + This option controls whether ‘magit-diff-visit-file’ may visit the + previous blob. When this is ‘t’ (the default) and point is on a + removed line in a diff for a committed change, then + ‘magit-diff-visit-file’ visits the blob from the last revision + which still had that line. + + Currently this is only supported for committed changes, for staged + and unstaged changes ‘magit-diff-visit-file’ always visits the file + in the working tree. + +‘C-’ (‘magit-diff-visit-file-worktree’) + + This command visits the worktree version of the appropriate file. + The location of point inside the diff determines which file is + being visited. Unlike ‘magit-diff-visit-file’ it always visits the + "real" file in the working tree, i.e the "current version" of the + file. + + In the file-visiting buffer this command goes to the line that + corresponds to the line that point is on in the diff. Lines that + were added or removed in the working tree, the index and other + commits in between are automatically accounted for. + + The buffer is displayed in the selected window. With a prefix + argument the buffer is displayed in another window instead. + + Variants of the above two commands exist that instead visit the file +in another window or in another frame. If you prefer such behavior, +then you may want to change the above key bindings, but note that the +above commands also use another window when invoked with a prefix +argument. + + -- Command: magit-diff-visit-file-other-window + -- Command: magit-diff-visit-file-other-frame + -- Command: magit-diff-visit-worktree-file-other-window + -- Command: magit-diff-visit-worktree-file-other-frame + + +File: magit.info, Node: Blaming, Prev: Visiting Files and Blobs, Up: Inspecting 5.9 Blaming =========== Also see *note (gitman)git-blame::. - To start blaming you can use ‘M-x’ in a file-visiting buffer to -invoke one of the following commands. You can also invoke these -commands using the blame popup, which is available on ‘b’ in -file-visiting buffers that already contain blame information and, also -on ‘b’, in all blob-visiting buffers. You can also enter the blame -popup from the file popup, which is available on ‘C-c M-g’, provided -‘magit-file-mode’ is enabled, see *note Minor Mode for Buffers Visiting -Files::. + To start blaming invoke the ‘magit-file-dispatch’ transient prefix +command by pressing ‘C-c M-g’. (This is only the default binding and +the recommended binding is ‘C-c g’. Also neither binding may be +available if you disabled ‘global-magit-file-mode’. Also see *note +Minor Mode for Buffers Visiting Files::.) + + The blaming suffix commands can be invoked from the dispatch +transient. However if you want to set an infix argument, then you have +to enter the blaming sub-transient first. + + The key bindings shown below assume that you enter the dispatch +transient using the default binding. + +‘C-c M-g B’ (‘magit-blame’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. - -- Command: magit-blame-addition + Note that not all of the following suffixes are available at all +times. For example if ‘magit-blame-mode’ is not enabled, then the +command whose purpose is to turn off that mode would not be of any use +and therefore isn’t available. + +‘C-c M-g b’ (‘magit-blame-addition’) +‘C-c M-g B b’ (‘magit-blame-addition’) This command augments each line or chunk of lines in the current - file- or blob-visiting buffer with information about what commits - last touched these lines. + file-visiting or blob-visiting buffer with information about what + commits last touched these lines. If the buffer visits a revision of that file, then history up to that revision is considered. Otherwise, the file’s full history is @@ -4222,13 +4455,8 @@ Files::. ‘magit-find-file’), where REVISION is a parent of the revision that added the current line or chunk of lines. - -- Command: magit-blame-echo - - This command is like ‘magit-blame-addition’ except that it doesn’t - turn on ‘read-only-mode’ and that it initially uses the - visualization style specified by option ‘magit-blame-echo-style’. - - -- Command: magit-blame-removal +‘C-c M-g r’ (‘magit-blame-removal’) +‘C-c M-g B r’ (‘magit-blame-removal’) This command augments each line or chunk of lines in the current blob-visiting buffer with information about the revision that @@ -4236,14 +4464,22 @@ Files::. Like ‘magit-blame-addition’, this command can be used recursively. - -- Command: magit-blame-reverse +‘C-c M-g f’ (‘magit-blame-reverse’) +‘C-c M-g B f’ (‘magit-blame-reverse’) This command augments each line or chunk of lines in the current - file- or blob-visiting buffer with information about the last - revision in which a line still existed. + file-visiting or blob-visiting buffer with information about the + last revision in which a line still existed. Like ‘magit-blame-addition’, this command can be used recursively. +‘C-c M-g e’ (‘magit-blame-echo’) +‘C-c M-g B e’ (‘magit-blame-echo’) + + This command is like ‘magit-blame-addition’ except that it doesn’t + turn on ‘read-only-mode’ and that it initially uses the + visualization style specified by option ‘magit-blame-echo-style’. + The following key bindings are available when Magit-Blame mode is enabled and Read-Only mode is not enabled. These commands are also available in other buffers; here only the behavior is described that is @@ -4273,13 +4509,12 @@ relevant in file-visiting buffers that are being blamed. information about that commit, then the buffer is scrolled down instead. - The following key bindings are available when Magit-Blame mode is -enabled and Read-Only mode is not enabled. + The following key bindings are available when both Magit-Blame mode +and Read-Only mode are enabled. -‘b’ (‘magit-blame-popup’) +‘b’ (‘magit-blame’) - This prefix command shows the above suffix command along with the - appropriate infix arguments in a popup buffer. + See above. ‘n’ (‘magit-blame-next-chunk’) @@ -4358,7 +4593,8 @@ File: magit.info, Node: Manipulating, Next: Transferring, Prev: Inspecting, * Menu: -* Repository Setup:: +* Creating Repository:: +* Cloning Repository:: * Staging and Unstaging:: * Applying:: * Committing:: @@ -4371,10 +4607,10 @@ File: magit.info, Node: Manipulating, Next: Transferring, Prev: Inspecting, * Stashing::  -File: magit.info, Node: Repository Setup, Next: Staging and Unstaging, Up: Manipulating +File: magit.info, Node: Creating Repository, Next: Cloning Repository, Up: Manipulating -6.1 Repository Setup -==================== +6.1 Creating Repository +======================= ‘M-x magit-init’ (‘magit-init’) @@ -4386,24 +4622,140 @@ File: magit.info, Node: Repository Setup, Next: Staging and Unstaging, Up: Ma directory is the root of the existing repository, then the user has to confirm that it should be reinitialized. -‘M-x magit-clone’ (‘magit-clone’) + +File: magit.info, Node: Cloning Repository, Next: Staging and Unstaging, Prev: Creating Repository, Up: Manipulating + +6.2 Cloning Repository +====================== + +To clone a remote or local repository use ‘C’, which is bound to the +command ‘magit-clone’. This command either act as a transient prefix +command, which binds several infix arguments and suffix commands, or it +can invoke ‘git clone’ directly, depending on whether a prefix argument +is used and on the value of ‘magit-clone-always-transient’. + + -- User Option: magit-clone-always-transient + + This option controls whether the command ‘magit-clone’ always acts + as a transient prefix command, regardless of whether a prefix + argument is used or not. If ‘t’, then that command always acts as + a transient prefix. If ‘nil’, then a prefix argument has to be + used for it to act as a transient. + +‘C’ (‘magit-clone’) + + This command either acts as a transient prefix command as described + above or does the same thing as ‘transient-clone-regular’ as + described below. + + If it acts as a transient prefix, then it binds the following + suffix commands and several infix arguments. + +‘C C’ (‘magit-clone-regular’) + + This command creates a regular clone of an existing repository. + The repository and the target directory are read from the user. + +‘C s’ (‘magit-clone-shallow’) + + This command creates a shallow clone of an existing repository. + The repository and the target directory are read from the user. By + default the depth of the cloned history is a single commit, but + with a prefix argument the depth is read from the user. + +‘C b’ (‘magit-clone-bare’) + + This command creates a bare clone of an existing repository. The + repository and the target directory are read from the user. + +‘C m’ (‘magit-clone-mirror’) - This command clones a repository and then shows the status buffer - for the new repository. + This command creates a mirror of an existing repository. The + repository and the target directory are read from the user. - The user is queried for a remote url and a local directory. + The following suffixes are disabled by default. See *note +(transient)Enabling and Disabling Suffixes:: for how to enable them. + +‘C d’ (‘magit-clone-shallow-since’) + + This command creates a shallow clone of an existing repository. + Only commits that were committed after a date are cloned, which is + read from the user. The repository and the target directory are + also read from the user. + +‘C e’ (‘magit-clone-shallow-exclude’) + + This command creates a shallow clone of an existing repository. + This reads a branch or tag from the user. Commits that are + reachable from that are not cloned. The repository and the target + directory are also read from the user. + + -- User Option: magit-clone-set-remote-head + + This option controls whether cloning causes the reference + ‘refs/remotes//HEAD’ to be created in the clone. The + default is to do so. + + Actually ‘git clone’ itself does that and cannot be told to not do + it. Therefore setting this to ‘nil’ causes Magit to remove that + reference after cloning. -- User Option: magit-clone-set-remote.pushDefault - Whether to set the value of ‘remote.pushDefault’ after cloning. + This option controls whether the value of the Git variable + ‘remote.pushDefault’ is set after cloning. + + • If ‘t’, then it is always set without asking. + + • If ‘ask’, then the users are asked every time they clone a + repository. + + • If ‘nil’, then it is never set. + + -- User Option: magit-clone-default-directory + + This option control the default directory name used when reading + the destination for a cloning operation. + + • If ‘nil’ (the default), then the value of ‘default-directory’ + is used. - If ‘t’, then set without asking. If ‘nil’, then don’t set. If - ‘ask’, then ask the user every time she clones a repository. + • If a directory, then that is used. + + • If a function, then that is called with the remote url as the + only argument and the returned value is used. + + -- User Option: magit-clone-name-alist + + This option maps regular expressions, which match repository names, + to repository urls, making it possible for users to enter short + names instead of urls when cloning repositories. + + Each element has the form ‘(REGEXP HOSTNAME USER)’. When the user + enters a name when a cloning command asks for a name or url, then + that is looked up in this list. The first element whose REGEXP + matches is used. + + The format specified by option ‘magit-clone-url-format’ is used to + turn the name into an url, using HOSTNAME and the repository name. + If the provided name contains a slash, then that is used. + Otherwise if the name omits the owner of the repository, then the + default user specified in the matched entry is used. + + If USER contains a dot, then it is treated as a Git variable and + the value of that is used as the username. Otherwise it is used as + the username itself. + + -- User Option: magit-clone-url-format + + The format specified by this option is used when turning repository + names into urls. ‘%h’ is the hostname and ‘%n’ is the repository + name, including the name of the owner.  -File: magit.info, Node: Staging and Unstaging, Next: Applying, Prev: Repository Setup, Up: Manipulating +File: magit.info, Node: Staging and Unstaging, Next: Applying, Prev: Cloning Repository, Up: Manipulating -6.2 Staging and Unstaging +6.3 Staging and Unstaging ========================= Like Git, Magit can of course stage and unstage complete files. Unlike @@ -4500,7 +4852,7 @@ apply variants are described in the next section.  File: magit.info, Node: Staging from File-Visiting Buffers, Up: Staging and Unstaging -6.2.1 Staging from File-Visiting Buffers +6.3.1 Staging from File-Visiting Buffers ---------------------------------------- Fine-grained un-/staging has to be done from the status or a diff @@ -4526,7 +4878,7 @@ visited in the current buffer right from inside that buffer.  File: magit.info, Node: Applying, Next: Committing, Prev: Staging and Unstaging, Up: Manipulating -6.3 Applying +6.4 Applying ============ Magit provides several "apply variants": stage, unstage, discard, @@ -4580,7 +4932,7 @@ appropriate (i.e. when ‘git apply’ is used internally).  File: magit.info, Node: Committing, Next: Branching, Prev: Applying, Up: Manipulating -6.4 Committing +6.5 Committing ============== When the user initiates a commit, Magit calls ‘git commit’ without any @@ -4598,15 +4950,16 @@ using the file’s content as message.  File: magit.info, Node: Initiating a Commit, Next: Editing Commit Messages, Up: Committing -6.4.1 Initiating a Commit +6.5.1 Initiating a Commit ------------------------- Also see *note (gitman)git-commit::. -‘c’ (‘magit-commit-popup’) +‘c’ (‘magit-commit’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘c c’ (‘magit-commit-create’) @@ -4694,7 +5047,7 @@ Also see *note (gitman)git-commit::.  File: magit.info, Node: Editing Commit Messages, Prev: Initiating a Commit, Up: Committing -6.4.2 Editing Commit Messages +6.5.2 Editing Commit Messages ----------------------------- After initiating a commit as described in the previous section, two new @@ -4901,10 +5254,10 @@ suitable for that hook. Propertize the diff shown inside the commit message buffer. Git inserts such diffs into the commit message template when the - ‘--verbose’ argument is used. Magit’s commit popup by default does - not offer that argument because the diff that is shown in a - separate buffer is more useful. But some users disagree, which is - why this function exists. + ‘--verbose’ argument is used. ‘magit-commit’ by default does not + offer that argument because the diff that is shown in a separate + buffer is more useful. But some users disagree, which is why this + function exists. -- Function: with-editor-usage-message @@ -4951,20 +5304,20 @@ when certain rules are violated.  File: magit.info, Node: Branching, Next: Merging, Prev: Committing, Up: Manipulating -6.5 Branching +6.6 Branching ============= * Menu: * The Two Remotes:: -* The Branch Popup:: -* The Branch Config Popup:: +* Branch Commands:: +* Branch Git Variables:: * Auxiliary Branch Commands::  -File: magit.info, Node: The Two Remotes, Next: The Branch Popup, Up: Branching +File: magit.info, Node: The Two Remotes, Next: Branch Commands, Up: Branching -6.5.1 The Two Remotes +6.6.1 The Two Remotes --------------------- The upstream branch of some local branch is the branch into which the @@ -4995,56 +5348,70 @@ variables ‘branch..pushRemote’ and ‘remote.pushDefault’. So we no longer have to choose which of the two remotes should be used as "the remote". - Each of the fetching, pulling, and pushing popups features three -commands that act on the current branch and some other branch. Of -these, ‘p’ is bound to a command which acts on the push-remote, ‘u’ is -bound to a command which acts on the upstream, and ‘e’ is bound to a -command which acts on any other branch. The status buffer shows -unpushed and unpulled commits for both the push-remote and the upstream. + Each of the fetching, pulling, and pushing transient commands +features three suffix commands that act on the current branch and some +other branch. Of these, ‘p’ is bound to a command which acts on the +push-remote, ‘u’ is bound to a command which acts on the upstream, and +‘e’ is bound to a command which acts on any other branch. The status +buffer shows unpushed and unpulled commits for both the push-remote and +the upstream. It’s fairly simple to configure these two remotes. The values of all the variables that are related to fetching, pulling, and pushing (as well as some other branch-related variables) can be inspected and -changed using the popup ‘magit-branch-config-popup’, which is a -sub-popup of many popups that deal with branches. It is also possible -to set the push-remote or upstream while pushing (see *note Pushing::). +changed using the command ‘magit-branch-configure’, which is available +from many transient prefix commands that deal with branches. It is also +possible to set the push-remote or upstream while pushing (see *note +Pushing::).  -File: magit.info, Node: The Branch Popup, Next: The Branch Config Popup, Prev: The Two Remotes, Up: Branching +File: magit.info, Node: Branch Commands, Next: Branch Git Variables, Prev: The Two Remotes, Up: Branching -6.5.2 The Branch Popup ----------------------- +6.6.2 Branch Commands +--------------------- -The popup ‘magit-branch-popup’ is used to create and checkout branches, -and to make changes to existing branches. It is not used to fetch, -pull, merge, rebase, or push branches, i.e. this popup deals with -branches themselves, not with the commits reachable from them. Those -features are available from separate popups. +The transient prefix command ‘magit-branch’ is used to create and +checkout branches, and to make changes to existing branches. It is not +used to fetch, pull, merge, rebase, or push branches, i.e. this command +deals with branches themselves, not with the commits reachable from +them. Those features are available from separate transient command. -‘b’ (‘magit-branch-popup’) +‘b’ (‘magit-branch’) - This prefix command shows the following suffix commands in a popup - buffer. + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + + By default it also binds and displays the values of some + branch-related Git variables and allows changing their values. + + -- User Option: magit-branch-direct-configure - By default it also displays the values of some branch-related Git - variables and allows changing their values, just like the - specialized ‘magit-branch-config-popup’ does. + This option controls whether the transient command ‘magit-branch’ + can be used directly change the values Git variables. This + defaults to ‘t’ (to avoid changing key bindings). When set to + ‘nil’, then no variables are displayed by that transient command, + and its suffix command ‘magit-branch-configure’ has to be used + instead to view and change branch related variables. - -- User Option: magit-branch-popup-show-variables +‘b C’ (‘magit-branch-configure’) +‘f C’ (‘magit-branch-configure’) +‘F C’ (‘magit-branch-configure’) +‘P C’ (‘magit-branch-configure’) - Whether the ‘magit-branch-popup’ shows Git variables. This - defaults to t to avoid changing key bindings. When set to nil, no - variables are displayed directly in this popup, and the sub-popup - ‘magit-branch-config-popup’ has to be used instead to view and - change branch related variables. + This transient prefix command binds commands that set the value of + branch-related variables and displays them in a temporary buffer + until the transient is exited. -‘b C’ (‘magit-branch-config-popup’) + With a prefix argument, this command always prompts for a branch. - This command shows branch related variables in a separate popup. - By default this asks the user for which branch the variables should - be shown. When ‘magit-branch-popup-show-variables’ is ‘nil’, then - it shows the variables for the current branch, unless a prefix - argument is used. + Without a prefix argument this depends on whether it was invoked as + a suffix of ‘magit-branch’ and on the + ‘magit-branch-direct-configure’ option. If ‘magit-branch’ already + displays the variables for the current branch, then it isn’t useful + to invoke another transient that displays them for the same branch. + In that case this command prompts for a branch. + + The variables are described in *note Branch Git Variables::. ‘b b’ (‘magit-checkout’) @@ -5122,6 +5489,12 @@ features are available from separate popups. branch. If FROM is not reachable from ‘HEAD’ or is reachable from the source branch’s upstream, then an error is raised. +‘b S’ (‘magit-branch-spinout’) + + This command behaves like ‘magit-branch-spinoff’, except that it + does not change the current branch. If there are any uncommitted + changes, then it behaves exactly like ‘magit-branch-spinoff’. + ‘b x’ (‘magit-branch-reset’) This command resets a branch, defaulting to the branch at point, to @@ -5252,7 +5625,7 @@ features are available from separate popups. This command is a hybrid between ‘magit-checkout’ and ‘magit-branch-and-checkout’ and is intended as a replacement for - the former in ‘magit-branch-popup’. + the former in ‘magit-branch’. It first asks the user for an existing branch or revision. If the user input actually can be resolved as a branch or revision, then @@ -5265,33 +5638,18 @@ features are available from separate popups. To use this command instead of ‘magit-checkout’ add this to your init file: - (magit-remove-popup-key 'magit-branch-popup :action ?b) - (magit-define-popup-action 'magit-branch-popup - ?b "Checkout" 'magit-branch-or-checkout - 'magit-branch t) + (transient-replace-suffix 'magit-branch 'magit-checkout + '("b" "dwim" magit-branch-or-checkout))  -File: magit.info, Node: The Branch Config Popup, Next: Auxiliary Branch Commands, Prev: The Branch Popup, Up: Branching +File: magit.info, Node: Branch Git Variables, Next: Auxiliary Branch Commands, Prev: Branch Commands, Up: Branching -6.5.3 The Branch Config Popup ------------------------------ - - -- Command: magit-branch-config-popup - - This prefix command shows the following branch-related Git - variables in a popup buffer. The values can be changed from that - buffer. - - This popup is a sub-popup of several popups that deal with - branches, including ‘magit-branch-popup’, ‘magit-pull-popup’, - ‘magit-fetch-popup’, ‘magit-pull-and-fetch-popup’, and - ‘magit-push-popup’. In all of these popups "C" is bound to this - popup. +6.6.3 Branch Git Variables +-------------------------- - The following variables are used to configure a specific branch. The -values are being displayed for the current branch (if any). To change -the value for another branch invoke ‘magit-branch-config-popup’ with a -prefix argument. +These variables can be set from the transient prefix command +‘magit-branch-configure’. By default they can also be set from +‘magit-branch’. See *note Branch Commands::. -- Variable: branch.NAME.merge @@ -5421,12 +5779,13 @@ e.g.: change the upstream and many which create new branches.  -File: magit.info, Node: Auxiliary Branch Commands, Prev: The Branch Config Popup, Up: Branching +File: magit.info, Node: Auxiliary Branch Commands, Prev: Branch Git Variables, Up: Branching -6.5.4 Auxiliary Branch Commands +6.6.4 Auxiliary Branch Commands ------------------------------- -These commands are not available from the branch popup by default. +These commands are not available from the transient ‘magit-branch’ by +default. -- Command: magit-branch-shelve @@ -5451,19 +5810,20 @@ These commands are not available from the branch popup by default.  File: magit.info, Node: Merging, Next: Resolving Conflicts, Prev: Branching, Up: Manipulating -6.6 Merging +6.7 Merging =========== Also see *note (gitman)git-merge::. For information on how to resolve merge conflicts see the next section. -‘m’ (‘magit-merge-popup’) +‘m’ (‘magit-merge’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. - When no merge is in progress, then the popup buffer features the -following commands. + When no merge is in progress, then the transient features the +following suffix commands. ‘m m’ (‘magit-merge-plain’) @@ -5526,15 +5886,15 @@ following commands. the changes made by the squashed commits. No information is preserved that would allow creating an actual merge commit. Instead of this command you should probably use a command from the - apply popup. + apply transient. ‘m p’ (‘magit-merge-preview’) This command shows a preview of merging another branch or an arbitrary revision into the current branch. - When a merge is in progress, then the popup buffer features these -commands instead. + When a merge is in progress, then the transient instead features the +following suffix commands. ‘m m’ (‘magit-merge’) @@ -5549,7 +5909,7 @@ commands instead.  File: magit.info, Node: Resolving Conflicts, Next: Rebasing, Prev: Merging, Up: Manipulating -6.7 Resolving Conflicts +6.8 Resolving Conflicts ======================= When merging branches (or otherwise combining or changing history) @@ -5658,19 +6018,20 @@ complex conflicts, the latter is usually overkill.  File: magit.info, Node: Rebasing, Next: Cherry Picking, Prev: Resolving Conflicts, Up: Manipulating -6.8 Rebasing +6.9 Rebasing ============ Also see *note (gitman)git-rebase::. For information on how to resolve conflicts that occur during rebases see the preceding section. -‘r’ (‘magit-rebase-popup’) +‘r’ (‘magit-rebase’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. - When no rebase is in progress, then the popup buffer features the -following commands. + When no rebase is in progress, then the transient features the +following suffix commands. Using one of these commands _starts_ a rebase sequence. Git might then stop somewhere along the way, either because you told it to do so, @@ -5679,26 +6040,37 @@ happens, then the status buffer shows information about the rebase sequence which is in progress in a section similar to a log section. See *note Information About In-Progress Rebase::. + For information about the upstream and the push-remote, see *note The +Two Remotes::. + ‘r p’ (‘magit-rebase-onto-pushremote’) - Rebase the current branch onto ‘branch..pushRemote’. If that - variable is unset, then rebase onto ‘remote.pushDefault’. + This command rebases the current branch onto its push-remote. + + When ‘magit-remote-set-if-missing’ is non-nil and the push-remote + is not configured, then configure it before rebasing. With a + prefix argument let the user change the push-remote before rebasing + onto it. ‘r u’ (‘magit-rebase-onto-upstream’) - Rebase the current branch onto its upstream branch. + This command rebases the current branch onto its upstream branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the upstream is + not configured, then configure it before rebasing. With a prefix + argument let the user change the upstream before rebasing onto it. ‘r e’ (‘magit-rebase-branch’) - Rebase the current branch onto a branch read in the minibuffer. - All commits that are reachable from head but not from the selected - branch TARGET are being rebased." + This command rebases the current branch onto a branch read in the + minibuffer. All commits that are reachable from head but not from + the selected branch TARGET are being rebased. ‘r s’ (‘magit-rebase-subset’) - Start a non-interactive rebase sequence with commits from START to - ‘HEAD’ onto NEWBASE. START has to be selected from a list of - recent commits. + This command starts a non-interactive rebase sequence to transfer + commits from START to ‘HEAD’ onto NEWBASE. START has to be + selected from a list of recent commits. By default Magit uses the ‘--autostash’ argument, which causes uncommitted changes to be stored in a stash before the rebase begins. @@ -5708,9 +6080,9 @@ stash is not removed. In case something goes wrong when resolving the conflicts, this allows you to start over. Even though one of the actions is dedicated to interactive rebases, -the popup also features the infix argument ‘--interactive’. This can be -used to turn one of the other, non-interactive rebase variants into an -interactive rebase. +the transient also features the infix argument ‘--interactive’. This +can be used to turn one of the other, non-interactive rebase variants +into an interactive rebase. For example if you want to clean up a feature branch and at the same time rebase it onto ‘master’, then you could use ‘r-iu’. But we @@ -5722,49 +6094,55 @@ only have to redo half the work. Explicitly enabling ‘--interactive’ won’t have an effect on the following commands as they always use that argument anyway, even if it -is not enabled in the popup. +is not enabled in the transient. ‘r i’ (‘magit-rebase-interactive’) - Start an interactive rebase sequence. + This command starts an interactive rebase sequence. ‘r f’ (‘magit-rebase-autosquash’) - Combine squash and fixup commits with their intended targets. + This command combines squash and fixup commits with their intended + targets. ‘r m’ (‘magit-rebase-edit-commit’) - Edit a single older commit using rebase. + This command starts an interactive rebase sequence that lets the + user edit a single older commit. ‘r w’ (‘magit-rebase-reword-commit’) - Reword a single older commit using rebase. + This command starts an interactive rebase sequence that lets the + user reword a single older commit. ‘r k’ (‘magit-rebase-remove-commit’) - Remove a single older commit using rebase. + This command removes a single older commit using rebase. - When a rebase is in progress, then the popup buffer features these -commands instead. + When a rebase is in progress, then the transient instead features the +following suffix commands. ‘r r’ (‘magit-rebase-continue’) - Restart the current rebasing operation. + This command restart the current rebasing operation. In some cases this pops up a commit message buffer for you do edit. With a prefix argument the old message is reused as-is. ‘r s’ (‘magit-rebase-skip’) - Skip the current commit and restart the current rebase operation. + This command skips the current commit and restarts the current + rebase operation. ‘r e’ (‘magit-rebase-edit’) - Edit the todo list of the current rebase operation. + This command lets the user edit the todo list of the current rebase + operation. ‘r a’ (‘magit-rebase-abort’) - Abort the current rebase operation, restoring the original branch. + This command aborts the current rebase operation, restoring the + original branch. * Menu: @@ -5774,7 +6152,7 @@ commands instead.  File: magit.info, Node: Editing Rebase Sequences, Next: Information About In-Progress Rebase, Up: Rebasing -6.8.1 Editing Rebase Sequences +6.9.1 Editing Rebase Sequences ------------------------------ ‘C-c C-c’ (‘with-editor-finish’) @@ -5856,6 +6234,11 @@ File: magit.info, Node: Editing Rebase Sequences, Next: Information About In-P when there already is one on the current line. With empty input remove the command on the current line, if any. +‘b’ (‘git-rebase-break’) + + Insert a break action before the current line, instructing Git to + return control to the user. + ‘y’ (‘git-rebase-insert’) Read an arbitrary commit and insert it below current line. @@ -5877,10 +6260,39 @@ File: magit.info, Node: Editing Rebase Sequences, Next: Information About In-P Whether confirmation is required to cancel. + When a rebase is performed with the ‘--rebase-merges’ option, the +sequence will include a few other types of actions and the following +commands become relevant. + +‘l’ (‘git-rebase-label’) + + This commands inserts a label action or edits the one at point. + +‘t’ (‘git-rebase-reset’) + + This command inserts a reset action or edits the one at point. The + prompt will offer the labels that are currently present in the + buffer. + +‘MM’ (‘git-rebase-merge’) + + The command inserts a merge action or edits the one at point. The + prompt will offer the labels that are currently present in the + buffer. Specifying a message to reuse via ‘-c’ or ‘-C’ is not + supported; an editor will always be invoked for the merge. + +‘Mt’ (‘git-rebase-merge-toggle-editmsg’) + + This command toggles between the ‘-C’ and ‘-c’ options of the merge + action at point. These options both specify a commit whose message + should be reused. The lower-case variant instructs Git to invoke + the editor when creating the merge, allowing the user to edit the + message. +  File: magit.info, Node: Information About In-Progress Rebase, Prev: Editing Rebase Sequences, Up: Rebasing -6.8.2 Information About In-Progress Rebase +6.9.2 Information About In-Progress Rebase ------------------------------------------ While a rebase sequence is in progress, the status buffer features a @@ -5924,7 +6336,9 @@ shown in different colors to indicate the status of the commits. • Commits prefixed with ‘pick’, ‘reword’, ‘edit’, ‘squash’, and ‘fixup’ have not been applied yet. These words have the same meaning here as they do in the buffer used to edit the rebase - sequence. See *note Editing Rebase Sequences::. + sequence. See *note Editing Rebase Sequences::. When the + ‘--rebase-merges’ option was specified, ‘reset’, ‘label’, and + ‘merge’ lines may also be present. • Commits prefixed with ‘done’ and ‘onto’ have already been applied. It is possible for such a commit to be the ‘HEAD’, in which case it @@ -6059,18 +6473,19 @@ commits make the same change?".  File: magit.info, Node: Cherry Picking, Next: Resetting, Prev: Rebasing, Up: Manipulating -6.9 Cherry Picking -================== +6.10 Cherry Picking +=================== Also see *note (gitman)git-cherry-pick::. -‘A’ (‘magit-cherry-pick-popup’) +‘A’ (‘magit-cherry-pick’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. - When no cherry-pick or revert is in progress, then the popup buffer -features the following commands. + When no cherry-pick or revert is in progress, then the transient +features the following suffix commands. ‘A A’ (‘magit-cherry-copy’) @@ -6087,7 +6502,7 @@ features the following commands. prompted for a commit or range, defaulting to the commit at point. This command also has a top-level binding, which can be invoked - without using the popup by typing ‘a’ at the top-level. + without using the transient by typing ‘a’ at the top-level. The following commands not only apply some commits to some branch, but also remove them from some other branch. The removal is performed @@ -6142,8 +6557,8 @@ you would have to if these commands didn’t exist at all. command stops and you have to resolve the conflicts and then finish the process manually. - When a cherry-pick or revert is in progress, then the popup buffer -features these commands instead. + When a cherry-pick or revert is in progress, then the transient +instead features the following suffix commands. ‘A A’ (‘magit-sequence-continue’) @@ -6165,16 +6580,17 @@ features these commands instead.  File: magit.info, Node: Reverting, Up: Cherry Picking -6.9.1 Reverting ---------------- +6.10.1 Reverting +---------------- -‘V’ (‘magit-revert-popup’) +‘V’ (‘magit-revert’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. - When no cherry-pick or revert is in progress, then the popup buffer -features the following commands. + When no cherry-pick or revert is in progress, then the transient +features the following suffix commands. ‘V V’ (‘magit-revert-and-commit’) @@ -6189,8 +6605,8 @@ features the following commands. region selects multiple commits, then revert all of them, without prompting. - When a cherry-pick or revert is in progress, then the popup buffer -features these commands instead. + When a cherry-pick or revert is in progress, then the transient +instead features the following suffix commands. ‘V A’ (‘magit-sequence-continue’) @@ -6208,7 +6624,7 @@ features these commands instead.  File: magit.info, Node: Resetting, Next: Stashing, Prev: Cherry Picking, Up: Manipulating -6.10 Resetting +6.11 Resetting ============== Also see *note (gitman)git-reset::. @@ -6257,20 +6673,21 @@ Also see *note (gitman)git-reset::.  File: magit.info, Node: Stashing, Prev: Resetting, Up: Manipulating -6.11 Stashing +6.12 Stashing ============= Also see *note (gitman)git-stash::. -‘z’ (‘magit-stash-popup’) +‘z’ (‘magit-stash’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘z z’ (‘magit-stash-both’) Create a stash of the index and working tree. Untracked files are - included according to popup arguments. One prefix argument is + included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’. @@ -6282,21 +6699,21 @@ Also see *note (gitman)git-stash::. ‘z w’ (‘magit-stash-worktree’) Create a stash of unstaged changes in the working tree. Untracked - files are included according to popup arguments. One prefix + files are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’. ‘z x’ (‘magit-stash-keep-index’) Create a stash of the index and working tree, keeping index intact. - Untracked files are included according to popup arguments. One + Untracked files are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’. ‘z Z’ (‘magit-snapshot-both’) Create a snapshot of the index and working tree. Untracked files - are included according to popup arguments. One prefix argument is + are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’. @@ -6308,7 +6725,7 @@ Also see *note (gitman)git-stash::. ‘z W’ (‘magit-snapshot-worktree’) Create a snapshot of unstaged changes in the working tree. - Untracked files are included according to popup arguments. One + Untracked files are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’-. @@ -6395,8 +6812,8 @@ File: magit.info, Node: Transferring, Next: Miscellaneous, Prev: Manipulating * Fetching:: * Pulling:: * Pushing:: -* Creating and Sending Patches:: -* Applying Patches:: +* Plain Patches:: +* Maildir Patches::  File: magit.info, Node: Remotes, Next: Fetching, Up: Transferring @@ -6406,43 +6823,58 @@ File: magit.info, Node: Remotes, Next: Fetching, Up: Transferring * Menu: -* The Remote Popup:: -* The Remote Config Popup:: +* Remote Commands:: +* Remote Git Variables::  -File: magit.info, Node: The Remote Popup, Next: The Remote Config Popup, Up: Remotes +File: magit.info, Node: Remote Commands, Next: Remote Git Variables, Up: Remotes -7.1.1 The Remote Popup ----------------------- +7.1.1 Remote Commands +--------------------- -The popup ‘magit-remote-popup’ is used to add remotes and to make -changes to existing remotes. This popup only deals with remotes -themselves, not with branches or the transfer of commits. Those -features are available from separate popups. +The transient prefix command ‘magit-remote’ is used to add remotes and +to make changes to existing remotes. This command only deals with +remotes themselves, not with branches or the transfer of commits. Those +features are available from separate transient commands. Also see *note (gitman)git-remote::. -‘M’ (‘magit-remote-popup’) +‘M’ (‘magit-remote’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + + By default it also binds and displays the values of some + remote-related Git variables and allows changing their values. + + -- User Option: magit-remote-direct-configure + + This option controls whether remote-related Git variables are + accessible directly from the transient ‘magit-remote’. + + If ‘t’ (the default) and a local branch is checked out, then + ‘magit-remote’ features the variables for the upstream remote of + that branch, or if ‘HEAD’ is detached, for ‘origin’, provided that + exists. - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + If ‘nil’, then ‘magit-remote-configure’ has to be used to do so. - -- User Option: magit-remote-popup-show-variables +‘M C’ (‘magit-remote-configure’) - This option controls whether the ‘magit-remote-popup’ shows remote - related Git variables. When set to nil, no variables are displayed - directly in this popup, and the sub-popup - ‘magit-remote-config-popup’ has to be used instead to view and - change remote related variables. + This transient prefix command binds commands that set the value of + remote-related variables and displays them in a temporary buffer + until the transient is exited. -‘M C’ (‘magit-remote-config-popup’) + With a prefix argument, this command always prompts for a remote. - This command shows remote related variables in a separate popup. - By default this asks the user for which remote the variables should - be shown. When ‘magit-remote-popup-show-variables’ is ‘nil’, then - it shows the variables for the upstream of the current branch or - "origin" it that branch has no remote upstream. To select another - remote use a prefix argument. + Without a prefix argument this depends on whether it was invoked as + a suffix of ‘magit-remote’ and on the + ‘magit-remote-direct-configure’ option. If ‘magit-remote’ already + displays the variables for the upstream, then it does not make + sense to invoke another transient that displays them for the same + remote. In that case this command prompts for a remote. + + The variables are described in *note Remote Git Variables::. ‘M a’ (‘magit-remote-add’) @@ -6499,24 +6931,14 @@ features are available from separate popups. and the variable isn’t already set.  -File: magit.info, Node: The Remote Config Popup, Prev: The Remote Popup, Up: Remotes - -7.1.2 The Remote Config Popup ------------------------------ - - -- Command: magit-remote-config-popup - - This prefix command shows the following remote-related Git - variables in a popup buffer. The values can be changed from that - buffer. +File: magit.info, Node: Remote Git Variables, Prev: Remote Commands, Up: Remotes - This popup is a sub-popup of the ‘magit-remote-popup’ in which "C" - is bound to this popup. +7.1.2 Remote Git Variables +-------------------------- - The following variables are used to configure a specific remote. The -values are being displayed for the upstream remote of the current -branch. To change the value for another remote invoke -‘magit-remote-config-popup’ with a prefix argument. +These variables can be set from the transient prefix command +‘magit-remote-configure’. By default they can also be set from +‘magit-remote’. See *note Remote Commands::. -- Variable: remote.NAME.url @@ -6543,60 +6965,99 @@ branch. To change the value for another remote invoke This variable specifies what tags are fetched by default. If the value is ‘--no-tags’ then no tags are fetched. If the value is - ‘--tags’, then all tags are fetched. If this variable has not + ‘--tags’, then all tags are fetched. If this variable has no value, then only tags are fetched that are reachable from fetched branches. + -- User Option: magit-remote-set-if-missing + + This option controls whether missing remotes are configured before + fetching, pulling, pushing and rebasing. + + When ‘nil’, then commands such as ‘magit-pull-from-upstream’ and + ‘magit-rebase-onto-uptream’ are not available as suffix commands if + the push-remote or upstream is not configured. + + When ‘non-nil’, then these commands are always available in their + respective transient, but if the required configuration is missing, + then they do appear in a way that indicates that this is the case. + If the user invokes such a command, then it asks for the necessary + configuration, stores the configuration, and only then performs the + action. + + This option also affects whether the argument ‘--set-upstream’ is + available in ‘magit-push’. If the value is ‘non-nil’, then that + argument would be redundant. But note that changing the value of + this option does not take affect immediately, the argument will + only be added or removed after restarting Emacs. +  File: magit.info, Node: Fetching, Next: Pulling, Prev: Remotes, Up: Transferring 7.2 Fetching ============ -For information about the differences between the _upstream_ and the -_push-remote_, see *note Branching::. - - Also see *note (gitman)git-fetch::. +Also see *note (gitman)git-fetch::. For information about the upstream +and the push-remote, see *note The Two Remotes::. -‘f’ (‘magit-fetch-popup’) +‘f’ (‘magit-fetch’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘f p’ (‘magit-fetch-from-pushremote’) - Fetch from the push-remote of the current branch. + This command fetches from the push-remote of the current branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the push-remote + is not configured, then configure it before fetching. With a + prefix argument let the user change the push-remote before fetching + from it. ‘f u’ (‘magit-fetch-from-upstream’) - Fetch from the upstream of the current branch. + This command fetch from the upstream of the current branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the upstream is + not configured, then configure it before fetching. With a prefix + argument let the user change the upstream before fetching from it. ‘f e’ (‘magit-fetch-other’) - Fetch from another repository. + This command fetch from a repository read from the minibuffer. ‘f o’ (‘magit-fetch-branch’) - Fetch a branch from a remote, both of which are read from the - minibuffer. + This command fetches a branch from a remote, both of which are read + from the minibuffer. ‘f r’ (‘magit-fetch-refspec’) - Fetch from a remote using an explicit refspec, both of which are - read from the minibuffer. + This command fetches from a remote using an explicit refspec, both + of which are read from the minibuffer. ‘f a’ (‘magit-fetch-all’) - Fetch from all remotes. + This command fetches from all remotes. ‘f m’ (‘magit-submodule-fetch’) - Fetch all submodules. With a prefix argument fetch all remotes of - all submodules. + This command fetches all submodules. With a prefix argument it + fetches all remotes of all submodules. + + -- User Option: magit-pull-or-fetch + + By default fetch and pull commands are available from separate + transient prefix command. Setting this to ‘t’ adds some (but not + all) of the above suffix commands to the ‘magit-pull’ transient. + + If you do that, then you might also want to change the key binding + for these prefix commands, e.g.: - Instead of using one popup for fetching and another for pulling, you -could also use ‘magit-pull-and-fetch-popup’. See its doc-string for -more information. + (setq magit-pull-or-fetch t) + (define-key magit-mode-map "f" 'magit-pull) ; was magit-fetch + (define-key magit-mode-map "F" nil) ; was magit-pull  File: magit.info, Node: Pulling, Next: Pushing, Prev: Fetching, Up: Transferring @@ -6604,80 +7065,80 @@ File: magit.info, Node: Pulling, Next: Pushing, Prev: Fetching, Up: Transfer 7.3 Pulling =========== -For information about the differences between the _upstream_ and the -_push-remote_, see *note Branching::. +Also see *note (gitman)git-pull::. For information about the upstream +and the push-remote, see *note The Two Remotes::. - Also see *note (gitman)git-pull::. +‘F’ (‘magit-pull’) -‘F’ (‘magit-pull-popup’) - - This prefix command shows the following suffix commands in a popup - buffer. + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. ‘F p’ (‘magit-pull-from-pushremote’) - Pull from the push-remote of the current branch. + This command pulls from the push-remote of the current branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the push-remote + is not configured, then configure it before pulling. With a prefix + argument let the user change the push-remote before pulling from + it. ‘F u’ (‘magit-pull-from-upstream’) - Pull from the upstream of the current branch. + This command pulls from the upstream of the current branch. -‘F e’ (‘magit-pull-branch’) + When ‘magit-remote-set-if-missing’ is non-nil and the upstream is + not configured, then configure it before pulling. With a prefix + argument let the user change the upstream before pulling from it. - Pull from a branch read in the minibuffer. +‘F e’ (‘magit-pull-branch’) - Instead of using one popup for fetching and another for pulling, you -could also use ‘magit-pull-and-fetch-popup’. See its doc-string for -more information. + This command pulls from a branch read in the minibuffer.  -File: magit.info, Node: Pushing, Next: Creating and Sending Patches, Prev: Pulling, Up: Transferring +File: magit.info, Node: Pushing, Next: Plain Patches, Prev: Pulling, Up: Transferring 7.4 Pushing =========== -For information about the differences between the _upstream_ and the -_push-remote_, see *note Branching::. - - Also see *note (gitman)git-push::. +Also see *note (gitman)git-push::. For information about the upstream +and the push-remote, see *note The Two Remotes::. -‘P’ (‘magit-push-popup’) +‘P’ (‘magit-push’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘P p’ (‘magit-push-current-to-pushremote’) - Push the current branch to ‘branch..pushRemote’ or if that is - unset to ‘remote.pushDefault’. + This command pushes the current branch to its push-remote. - When ‘magit-push-current-set-remote-if-missing’ is non-nil and the - push-remote is not configured, then read the push-remote from the - user, set it, and then push to it. With a prefix argument the - push-remote can be changed before pushed to it. + When ‘magit-remote-set-if-missing’ is non-nil and the push-remote + is not configured, then configure it before pushing. With a prefix + argument let the user change the push-remote before pushing to it. ‘P u’ (‘magit-push-current-to-upstream’) - Push the current branch to its upstream branch. + This command pushes the current branch to its upstream branch. - When ‘magit-push-current-set-remote-if-missing’ is non-nil and the - push-remote is not configured, then read the upstream from the - user, set it, and then push to it. With a prefix argument the - push-remote can be changed before pushed to it. + When ‘magit-remote-set-if-missing’ is non-nil and the upstream is + not configured, then configure it before pushing. With a prefix + argument let the user change the upstream before pushing to it. ‘P e’ (‘magit-push-current’) - Push the current branch to a branch read in the minibuffer. + This command pushes the current branch to a branch read in the + minibuffer. ‘P o’ (‘magit-push-other’) - Push an arbitrary branch or commit somewhere. Both the source and - the target are read in the minibuffer. + This command pushes an arbitrary branch or commit somewhere. Both + the source and the target are read in the minibuffer. ‘P r’ (‘magit-push-refspecs’) - Push one or multiple refspecs to a remote, both of which are read - in the minibuffer. + This command pushes one or multiple refspecs to a remote, both of + which are read in the minibuffer. To use multiple refspecs, separate them with commas. Completion is only available for the part before the colon, or when no colon is @@ -6685,144 +7146,136 @@ _push-remote_, see *note Branching::. ‘P m’ (‘magit-push-matching’) - Push all matching branches to another repository. If multiple - remotes exit, then read one from the user. If just one exists, use - that without requiring confirmation. + This command pushes all matching branches to another repository. + + If only one remote exists, then push to that. Otherwise prompt for + a remote, offering the remote configured for the current branch as + default. ‘P t’ (‘magit-push-tags’) - Push all tags to another repository. If only one remote exists, - then push to that. Otherwise prompt for a remote, offering the - remote configured for the current branch as default. + This command pushes all tags to another repository. + + If only one remote exists, then push to that. Otherwise prompt for + a remote, offering the remote configured for the current branch as + default. ‘P T’ (‘magit-push-tag’) - Push a tag to another repository. + This command pushes a tag to another repository. Two more push commands exist, which by default are not available from -the push popup. See their doc-strings for instructions on how to add -them to the popup. +the push transient. See their doc-strings for instructions on how to +add them to the transient. -- Command: magit-push-implicitly args - Push somewhere without using an explicit refspec. + This command pushes somewhere without using an explicit refspec. - This command simply runs ‘git push -v [ARGS]’. ARGS are the - arguments specified in the popup buffer. No explicit refspec - arguments are used. Instead the behavior depends on at least these - Git variables: ‘push.default’, ‘remote.pushDefault’, - ‘branch..pushRemote’, ‘branch..remote’, - ‘branch..merge’, and ‘remote..push’. + This command simply runs ‘git push -v [ARGS]’. ARGS are the infix + arguments. No explicit refspec arguments are used. Instead the + behavior depends on at least these Git variables: ‘push.default’, + ‘remote.pushDefault’, ‘branch..pushRemote’, + ‘branch..remote’, ‘branch..merge’, and + ‘remote..push’. -- Command: magit-push-to-remote remote args - Push to the remote REMOTE without using an explicit refspec. The - remote is read in the minibuffer. + This command pushes to the remote REMOTE without using an explicit + refspec. The remote is read in the minibuffer. This command simply runs ‘git push -v [ARGS] REMOTE’. ARGS are the - arguments specified in the popup buffer. No refspec arguments are - used. Instead the behavior depends on at least these Git - variables: ‘push.default’, ‘remote.pushDefault’, - ‘branch..pushRemote’, ‘branch..remote’, - ‘branch..merge’, and ‘remote..push’. + infix arguments. No refspec arguments are used. Instead the + behavior depends on at least these Git variables: ‘push.default’, + ‘remote.pushDefault’, ‘branch..pushRemote’, + ‘branch..remote’, ‘branch..merge’, and + ‘remote..push’. - -- User Option: magit-push-current-set-remote-if-missing - - This option controls whether missing remotes are configured before - pushing. - - When ‘nil’, then the command ‘magit-push-current-to-pushremote’ and - ‘magit-push-current-to-upstream’ do not appear in the push popup if - the push-remote resp. upstream is not configured. If the user - invokes one of these commands anyway, then it raises an error. + +File: magit.info, Node: Plain Patches, Next: Maildir Patches, Prev: Pushing, Up: Transferring - When ‘non-nil’, then these commands always appear in the push - popup. But if the required configuration is missing, then they do - appear in a way that indicates that this is the case. If the user - invokes one of them, then it asks for the necessary configuration, - stores the configuration, and then uses it to push a first time. +7.5 Plain Patches +================= - This option also affects whether the argument ‘--set-upstream’ is - available in the popup. If the value is ‘non-nil’, then that - argument is redundant. But note that changing the value of this - option does not take affect immediately, the argument will only be - added or removed after restarting Emacs. +‘W’ (‘magit-patch’) - -File: magit.info, Node: Creating and Sending Patches, Next: Applying Patches, Prev: Pushing, Up: Transferring + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. -7.5 Creating and Sending Patches -================================ +‘W c’ (‘magit-patch-create’) -‘W’ (‘magit-patch-popup’) + This command creates patches for a set commits. If the region + marks several commits, then it creates patches for all of them. + Otherwise it functions as a transient prefix command, which + features several infix arguments and binds itself as a suffix + command. When this command is invoked as a suffix of itself, then + it creates a patch using the specified infix arguments. - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. +‘w a’ (‘magit-patch-apply’) -‘W p’ (‘magit-format-patch’) + This command applies a patch. This is a transient prefix command, + which features several infix arguments and binds itself as a suffix + command. When this command is invoked as a suffix of itself, then + it applies a patch using the specified infix arguments. - Create patches for a set commits. If the region marks commits, - then create patches for those. Otherwise prompt for a range or a - single commit, defaulting to the commit at point. +‘W s’ (‘magit-patch-save’) -‘W r’ (‘magit-request-pull’) + This command creates a patch from the current diff. - Request that upstream pulls from your public repository. + Inside ‘magit-diff-mode’ or ‘magit-revision-mode’ buffers, ‘C-x + C-w’ is also bound to this command. - It is also possible to save a plain patch file by using ‘C-x C-w’ -inside a ‘magit-diff-mode’ or ‘magit-revision-mode’ buffer. + FIXME It is also possible to save a plain patch file by using ‘C-x +C-w’ inside a ‘magit-diff-mode’ or ‘magit-revision-mode’ buffer.  -File: magit.info, Node: Applying Patches, Prev: Creating and Sending Patches, Up: Transferring +File: magit.info, Node: Maildir Patches, Prev: Plain Patches, Up: Transferring -7.6 Applying Patches -==================== +7.6 Maildir Patches +=================== Also see *note (gitman)git-am::. and *note (gitman)git-apply::. -‘w’ (‘magit-am-popup’) +‘w’ (‘magit-am’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘w w’ (‘magit-am-apply-patches’) - Apply one or more patches. If the region marks files, then apply - those patches. Otherwise read a file name in the minibuffer - defaulting to the file at point. + This command applies one or more patches. If the region marks + files, then those are applied as patches. Otherwise this command + reads a file-name in the minibuffer, defaulting to the file at + point. ‘w m’ (‘magit-am-apply-maildir’) - Apply the patches from a maildir. + This command applies patches from a maildir. + +‘w a’ (‘magit-patch-apply’) - When an "am" operation is in progress, then the popup buffer features -these commands instead. + This command applies a plain patch. For a longer description see + *note Plain Patches::. This command is only available from the + ‘magit-am’ transient for historic reasons. + + When an "am" operation is in progress, then the transient instead +features the following suffix commands. ‘w w’ (‘magit-am-continue’) - Resume the current patch applying sequence. + This command resumes the current patch applying sequence. ‘w s’ (‘magit-am-skip’) - Skip the stopped at patch during a patch applying sequence. + This command skips the stopped at patch during a patch applying + sequence. ‘w a’ (‘magit-am-abort’) - Abort the current patch applying sequence. This discards all - changes made since the sequence started. - - In addition to the commands listed at the top, the "am" popup also -has a binding for the related "patch" popup. - -‘w a’ (‘magit-patch-apply-popup’) - - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. - -‘w a a’ (‘magit-patch-apply’) - - This command applies a simple patch file, which may not contain any - Git metadata in addition to the actual diff. + This command aborts the current patch applying sequence. This + discards all changes made since the sequence started.  File: magit.info, Node: Miscellaneous, Next: Customizing, Prev: Transferring, Up: Top @@ -6850,10 +7303,11 @@ File: magit.info, Node: Tagging, Next: Notes, Up: Miscellaneous Also see *note (gitman)git-tag::. -‘t’ (‘magit-tag-popup’) +‘t’ (‘magit-tag’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘t t’ (‘magit-tag-create’) @@ -6878,8 +7332,8 @@ Also see *note (gitman)git-tag::. Then it calls "git tag –annotate –sign -m MSG TAG" to create the tag, regardless of whether these arguments are enabled in the - popup. Finally it shows the refs buffer to let the user quickly - review the result. + transient. Finally it shows the refs buffer to let the user + quickly review the result. ‘t k’ (‘magit-tag-delete’) @@ -6901,10 +7355,11 @@ File: magit.info, Node: Notes, Next: Submodules, Prev: Tagging, Up: Miscella Also see *note (gitman)git-notes::. -‘T’ (‘magit-notes-popup’) +‘T’ (‘magit-notes’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. ‘T T’ (‘magit-notes-edit’) @@ -6936,7 +7391,7 @@ in conflicts which have to resolved in the temporary worktree ref. The current notes ref is the value of Git variable ‘core.notesRef’ or "refs/notes/commits" if that is undefined. - When a notes merge is in progress then the popup features the + When a notes merge is in progress then the transient features the following suffix commands, instead of those listed above. ‘T c’ (‘magit-notes-merge-commit’) @@ -6975,10 +7430,10 @@ Also see *note (gitman)git-submodule::. * Menu: * Listing Submodules:: -* Submodule Popup:: +* Submodule Transient::  -File: magit.info, Node: Listing Submodules, Next: Submodule Popup, Up: Submodules +File: magit.info, Node: Listing Submodules, Next: Submodule Transient, Up: Submodules 8.3.1 Listing Submodules ------------------------ @@ -7024,15 +7479,16 @@ Sections::. not displayed in the super-repository’s status buffer.  -File: magit.info, Node: Submodule Popup, Prev: Listing Submodules, Up: Submodules +File: magit.info, Node: Submodule Transient, Prev: Listing Submodules, Up: Submodules -8.3.2 Submodule Popup ---------------------- +8.3.2 Submodule Transient +------------------------- -‘o’ (‘magit-submodule-popup’) +‘o’ (‘magit-submodule’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. Some of the below commands default to act on the modules that are selected using the region. For brevity their description talk about @@ -7097,42 +7553,60 @@ File: magit.info, Node: Subtree, Next: Worktree, Prev: Submodules, Up: Misce Also see *note (gitman)git-subtree::. -‘O’ (‘magit-tree-popup’) +‘O’ (‘magit-subtree’) + + This transient prefix command binds the two sub-transients; one for + importing a subtree and one for exporting a subtree. + +‘O i’ (‘magit-subtree-import’) - This prefix command shows the following suffix commands along with - the appropriate infix arguments in a popup buffer. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. - Most infix arguments only apply to some of the ‘git subtree’ -subcommands. When an argument that does not apply to the invoked -command is set, then it is silently ignored. + The suffixes of this command import subtrees. - When the ‘--prefix’ argument is set in the popup buffer, then that is -used. Otherwise the prefix is read in the minibuffer. + If the ‘--prefix’ argument is set, then the suffix commands use + that prefix without prompting the user. If it is unset, then they + read the prefix in the minibuffer. -‘O a’ (‘magit-subtree-add’) +‘O i a’ (‘magit-subtree-add’) - Add COMMIT from REPOSITORY as a new subtree at PREFIX. + This command adds COMMIT from REPOSITORY as a new subtree at + PREFIX. -‘O c’ (‘magit-subtree-add-commit’) +‘O i c’ (‘magit-subtree-add-commit’) - Add COMMIT as a new subtree at PREFIX. + This command add COMMIT as a new subtree at PREFIX. -‘O m’ (‘magit-subtree-merge’) +‘O i m’ (‘magit-subtree-merge’) - Merge COMMIT into the PREFIX subtree. + This command merges COMMIT into the PREFIX subtree. -‘O f’ (‘magit-subtree-pull’) +‘O i f’ (‘magit-subtree-pull’) - Pull COMMIT from REPOSITORY into the PREFIX subtree. + This command pulls COMMIT from REPOSITORY into the PREFIX subtree. -‘O p’ (‘magit-subtree-push’) +‘O e’ (‘magit-subtree-export’) - Extract the history of the subtree PREFIX and push it to REF on - REPOSITORY. + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. -‘O s’ (‘magit-subtree-split’) + The suffixes of this command export subtrees. - Extract the history of the subtree PREFIX. + If the ‘--prefix’ argument is set, then the suffix commands use + that prefix without prompting the user. If it is unset, then they + read the prefix in the minibuffer. + +‘O e p’ (‘magit-subtree-push’) + + This command extract the history of the subtree PREFIX and pushes + it to REF on REPOSITORY. + +‘O e s’ (‘magit-subtree-split’) + + This command extracts the history of the subtree PREFIX.  File: magit.info, Node: Worktree, Next: Common Commands, Prev: Subtree, Up: Miscellaneous @@ -7142,10 +7616,10 @@ File: magit.info, Node: Worktree, Next: Common Commands, Prev: Subtree, Up: Also see *note (gitman)git-worktree::. -‘%’ (‘magit-worktree-popup’) +‘%’ (‘magit-worktree’) - This prefix command shows the following suffix commands in a popup - buffer. + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. ‘% b’ (‘magit-worktree-checkout’) @@ -7327,603 +7801,3 @@ files are being committed. * Wip Graph:: * Legacy Wip Modes:: - -File: magit.info, Node: Wip Graph, Next: Legacy Wip Modes, Up: Wip Modes - -8.7.1 Wip Graph ---------------- - - -- User Option: magit-wip-merge-branch - - This option controls whether the current branch is merged into the - wip refs after a new commit was created on the branch. - - If non-nil and the current branch has new commits, then it is - merged into the wip ref before creating a new wip commit. This - makes it easier to inspect wip history and the wip commits are - never garbage collected. - - If nil and the current branch has new commits, then the wip ref is - reset to the tip of the branch before creating a new wip commit. - With this setting wip commits are eventually garbage collected. - - When ‘magit-wip-merge-branch’ is ‘t’, then the history looks like -this: - - *--*--*--*--*--* refs/wip/index/refs/heads/master - / / / - A-----B-----C refs/heads/master - - When ‘magit-wip-merge-branch’ is ‘nil’, then creating a commit on the -real branch and then making a change causes the wip refs to be recreated -to fork from the new commit. But the old commits on the wip refs are -not lost. They are still available from the reflog. To make it easier -to see when the fork point of a wip ref was changed, an additional -commit with the message "restart autosaving" is created on it (‘xxO’ -commits below are such boundary commits). - - Starting with - - BI0---BI1 refs/wip/index/refs/heads/master - / - A---B refs/heads/master - \ - BW0---BW1 refs/wip/wtree/refs/heads/master - - and committing the staged changes and editing and saving a file would -result in - - BI0---BI1 refs/wip/index/refs/heads/master - / - A---B---C refs/heads/master - \ \ - \ CW0---CW1 refs/wip/wtree/refs/heads/master - \ - BW0---BW1 refs/wip/wtree/refs/heads/master@{2} - - The fork-point of the index wip ref is not changed until some change -is being staged. Likewise just checking out a branch or creating a -commit does not change the fork-point of the working tree wip ref. The -fork-points are not adjusted until there actually is a change that -should be committed to the respective wip ref. - - -File: magit.info, Node: Legacy Wip Modes, Prev: Wip Graph, Up: Wip Modes - -8.7.2 Legacy Wip Modes ----------------------- - -It is recommended that you use the mode ‘magit-wip-mode’ (which see) and -ignore the existence of the following modes, which are preserved for -historic reasons. - - Setting the following variables directly does not take effect; either -use the Custom interface to do so or call the respective mode functions. - - -- User Option: magit-wip-after-save-mode - - When this mode is enabled, then saving a buffer that visits a file - tracked in a Git repository causes its current state to be - committed to the working tree wip ref for the current branch. - - -- User Option: magit-wip-after-apply-mode - - When this mode is enabled, then applying (i.e. staging, unstaging, - discarding, reversing, and regularly applying) a change to a file - tracked in a Git repository causes its current state to be - committed to the index and/or working tree wip refs for the current - branch. - - If you only ever edit files using Emacs and only ever interact with -Git using Magit, then the above two modes should be enough to protect -each and every change from accidental loss. In practice nobody does -that. Two additional modes exists that do commit to the wip refs before -making changes that could cause the loss of earlier changes. - - -- User Option: magit-wip-before-change-mode - - When this mode is enabled, then certain commands commit the - existing changes to the files they are about to make changes to. - - -- User Option: magit-wip-initial-backup-mode - - When this mode is enabled, then the current version of a file is - committed to the worktree wip ref before the buffer visiting that - file is saved for the first time since the buffer was created. - - This backs up the same version of the file that ‘backup-buffer’ - would save. While ‘backup-buffer’ uses a backup file, this mode - uses the same worktree wip ref as used by the other Magit Wip - modes. Like ‘backup-buffer’, it only does this once; unless you - kill the buffer and visit the file again only one backup will be - created per Emacs session. - - This mode ignores the variables that affect ‘backup-buffer’ and can - be used along-side that function, which is recommended because it - only backs up files that are tracked in a Git repository. - - -- User Option: magit-wip-after-save-local-mode-lighter - - Mode-line lighter for ‘magit-wip-after-save-local-mode’. - - -- User Option: magit-wip-after-apply-mode-lighter - - Mode-line lighter for ‘magit-wip-after-apply-mode’. - - -- User Option: magit-wip-before-change-mode-lighter - - Mode-line lighter for ‘magit-wip-before-change-mode’. - - -- User Option: magit-wip-initial-backup-mode-lighter - - Mode-line lighter for ‘magit-wip-initial-backup-mode’. - - -File: magit.info, Node: Minor Mode for Buffers Visiting Files, Next: Minor Mode for Buffers Visiting Blobs, Prev: Wip Modes, Up: Miscellaneous - -8.8 Minor Mode for Buffers Visiting Files -========================================= - -The ‘magit-file-mode’ enables certain Magit features in file-visiting -buffers belonging to a Git repository. It should be enabled globally -using ‘global-magit-file-mode’. Currently this mode only establishes a -few key bindings, but this might be extended in the future. - - -- User Option: magit-file-mode - - Whether to establish certain Magit key bindings in all - file-visiting buffers belonging to a Git repository. This - establishes the bindings suggested in *note Getting Started:: (but - only for file-visiting buffers), and additionally binds ‘C-c M-g’ - to ‘magit-file-popup’. - -‘C-c M-g’ (‘magit-file-popup’) - - This prefix command shows a popup buffer featuring suffix commands - that operate on the file being visited in the current buffer. - -‘C-c M-g s’ (‘magit-stage-file’) - - Stage all changes to the file being visited in the current buffer. - -‘C-c M-g u’ (‘magit-unstage-file’) - - Unstage all changes to the file being visited in the current - buffer. - -‘C-c M-g c’ (‘magit-commit-popup’) - - This prefix command shows suffix commands along with the - appropriate infix arguments in a popup buffer. See *note - Initiating a Commit::. - -‘C-c M-g D’ (‘magit-diff-buffer-file-popup’) - - This prefix command shows the same suffix commands and infix - arguments in a popup buffer as ‘magit-diff-popup’. But this - variant has to be called from a file-visiting buffer and the - visited file is automatically used in the popup to limit the diff - to that file. - -‘C-c M-g d’ (‘magit-diff-buffer-file’) - - This command shows the diff for the file of blob that the current - buffer visits. - - -- User Option: magit-diff-buffer-file-locked - - This option controls whether ‘magit-diff-buffer-file’ uses a - dedicated buffer. See *note Modes and Buffers::. - -‘C-c M-g L’ (‘magit-log-buffer-file-popup’) - - This prefix command shows the same suffix commands and infix - arguments in a popup buffer as ‘magit-log-popup’. But this variant - has to be called from a file-visiting buffer and the visited file - is automatically used in the popup to limit the log to that file. - -‘C-c M-g l’ (‘magit-log-buffer-file’) - - This command shows the log for the file of blob that the current - buffer visits. Renames are followed when a prefix argument is used - or when ‘--follow’ is part of ‘magit-log-arguments’. When the - region is active, the log is restricted to the selected line range. - -‘C-c M-g t’ (‘magit-log-trace-definition’) - - This command shows the log for the definition at point. - - -- User Option: magit-log-buffer-file-locked - - This option controls whether ‘magit-log-buffer-file’ uses a - dedicated buffer. See *note Modes and Buffers::. - -‘C-c M-g B’ (‘magit-blame-popup’) - - This prefix command shows all blaming suffix command along with the - appropriate infix arguments in a popup buffer. See *note - Blaming::. - -‘C-c M-g b’ (‘magit-blame-addition’) - - This command shows for each line the revision in which it was - added. - -‘C-c M-g r’ (‘magit-blame-removal’) - - This command shows for each line the revision in which it was - removed. This command is only available in blob-visiting buffers. - -‘C-c M-g f’ (‘magit-blame-reverse’) - - This command shows for each line the last revision in which it - still exists. This command is only available in blob-visiting - buffers. - -‘C-c M-g e’ (‘magit-edit-line-commit’) - - This command makes the commit editable that added the current line. - - With a prefix argument it makes the commit editable that removes - the line, if any. The commit is determined using ‘git blame’ and - made editable using ‘git rebase --interactive’ if it is reachable - from ‘HEAD’, or by checking out the commit (or a branch that points - at it) otherwise. - -‘C-c M-g p’ (‘magit-blob-previous’) - - Visit the previous blob which modified the current file. - - There are a few additional commands that operate on a single file but -are not available from the file popup by default: - - -- Command: magit-file-rename - - This command renames a file read from the user. - - -- Command: magit-file-delete - - This command deletes a file read from the user. - - -- Command: magit-file-untrack - - This command untracks a file read from the user. - - -- Command: magit-file-checkout - - This command updates a file in the working tree and index to the - contents from a revision. Both the revision and file are read from - the user. - - You could add them to the popup like so: - - (magit-define-popup-action 'magit-file-popup - ?R "Rename file" 'magit-file-rename) - (magit-define-popup-action 'magit-file-popup - ?K "Delete file" 'magit-file-delete) - (magit-define-popup-action 'magit-file-popup - ?U "Untrack file" 'magit-file-untrack) - (magit-define-popup-action 'magit-file-popup - ?C "Checkout file" 'magit-file-checkout) - - -File: magit.info, Node: Minor Mode for Buffers Visiting Blobs, Prev: Minor Mode for Buffers Visiting Files, Up: Miscellaneous - -8.9 Minor Mode for Buffers Visiting Blobs -========================================= - -The ‘magit-blob-mode’ enables certain Magit features in blob-visiting -buffers. Such buffers can be created using ‘magit-find-file’ and some -of the commands mentioned below, which also take care of turning on this -minor mode. Currently this mode only establishes a few key bindings, -but this might be extended. - -‘p’ (‘magit-blob-previous’) - - Visit the previous blob which modified the current file. - -‘n’ (‘magit-blob-next’) - - Visit the next blob which modified the current file. - -‘q’ (‘magit-kill-this-buffer’) - - Kill the current buffer. - - -File: magit.info, Node: Customizing, Next: Plumbing, Prev: Miscellaneous, Up: Top - -9 Customizing -************* - -Both Git and Emacs are highly customizable. Magit is both a Git -porcelain as well as an Emacs package, so it makes sense to customize it -using both Git variables as well as Emacs options. However this -flexibility doesn’t come without problems, including but not limited to -the following. - - • Some Git variables automatically have an effect in Magit without - requiring any explicit support. Sometimes that is desirable - in - other cases, it breaks Magit. - - When a certain Git setting breaks Magit but you want to keep using - that setting on the command line, then that can be accomplished by - overriding the value for Magit only by appending something like - ‘("-c" "some.variable=compatible-value")’ to - ‘magit-git-global-arguments’. - - • Certain settings like ‘fetch.prune=true’ are respected by Magit - commands (because they simply call the respective Git command) but - their value is not reflected in the respective popup buffers. In - this case the ‘--prune’ argument in ‘magit-fetch-popup’ might be - active or inactive depending on the value of - ‘magit-fetch-arguments’ only, but that doesn’t keep the Git - variable from being honored by the suffix commands anyway. So - pruning might happen despite the ‘--prune’ arguments being - displayed in a way that seems to indicate that no pruning will - happen. - - I intend to address these and similar issues in a future release. - -* Menu: - -* Per-Repository Configuration:: -* Essential Settings:: - - -File: magit.info, Node: Per-Repository Configuration, Next: Essential Settings, Up: Customizing - -9.1 Per-Repository Configuration -================================ - -Magit can be configured on a per-repository level using both Git -variables as well as Emacs options. - - To set a Git variable for one repository only, simply set it in -‘/path/to/repo/.git/config’ instead of ‘$HOME/.gitconfig’ or -‘/etc/gitconfig’. See *note (gitman)git-config::. - - Similarly, Emacs options can be set for one repository only by -editing ‘/path/to/repo/.dir-locals.el’. See *note (emacs)Directory -Variables::. For example to disable automatic refreshes of -file-visiting buffers in just one huge repository use this: - - • ‘/path/to/huge/repo/.dir-locals.el’ - - ((nil . ((magit-refresh-buffers . nil)))) - - If you want to apply the same settings to several, but not all, -repositories then keeping the repository-local config files in sync -would quickly become annoying. To avoid that you can create config -files for certain classes of repositories (e.g. "huge repositories") -and then include those files in the per-repository config files. For -example: - - • ‘/path/to/huge/repo/.git/config’ - - [include] - path = /path/to/huge-gitconfig - - • ‘/path/to/huge-gitconfig’ - - [status] - showUntrackedFiles = no - - • ‘$HOME/.emacs.d/init.el’ - - (dir-locals-set-class-variables 'huge-git-repository - '((nil . ((magit-refresh-buffers . nil))))) - - (dir-locals-set-directory-class - "/path/to/huge/repo/" 'huge-git-repository) - - -File: magit.info, Node: Essential Settings, Prev: Per-Repository Configuration, Up: Customizing - -9.2 Essential Settings -====================== - -The next two sections list and discuss several variables that many users -might want to customize, for safety and/or performance reasons. - -* Menu: - -* Safety:: -* Performance:: - - -File: magit.info, Node: Safety, Next: Performance, Up: Essential Settings - -9.2.1 Safety ------------- - -This section discusses various variables that you might want to change -(or *not* change) for safety reasons. - - Git keeps *committed* changes around long enough for users to recover -changes they have accidentally been deleted. It does not do the same -for *uncommitted* changes in the working tree and not even the index -(the staging area). Because Magit makes it so easy to modify -uncommitted changes, it also makes it easy to shoot yourself in the foot -in the process. For that reason Magit provides three global modes that -save *tracked* files to work-in-progress references after or before -certain actions. See *note Wip Modes::. - - These modes are not enabled by default because of performance -concerns. Instead a lot of potentially destructive commands require -confirmation every time they are used. In many cases this can be -disabled by adding a symbol to ‘magit-no-confirm’ (see *note Completion -and Confirmation::). If you enable the various wip modes then you -should add ‘safe-with-wip’ to this list. - - Similarly it isn’t necessary to require confirmation before moving a -file to the system trash - if you trashed a file by mistake then you can -recover it from the there. Option ‘magit-delete-by-moving-to-trash’ -controls whether the system trash is used, which is the case by default. -Nevertheless, ‘trash’ isn’t a member of ‘magit-no-confirm’ - you might -want to change that. - - By default buffers visiting files are automatically reverted when the -visited file changes on disk. This isn’t as risky as it might seem, but -to make an informed decision you should see *note Risk of Reverting -Automatically::. - - -File: magit.info, Node: Performance, Prev: Safety, Up: Essential Settings - -9.2.2 Performance ------------------ - -After Magit has run ‘git’ for side-effects, it also refreshes the -current Magit buffer and the respective status buffer. This is -necessary because otherwise outdated information might be displayed -without the user noticing. Magit buffers are updated by recreating -their content from scratch, which makes updating simpler and less -error-prone, but also more costly. Keeping it simple and just -re-creating everything from scratch is an old design decision and -departing from that will require major refactoring. - - I plan to do that in time for the next major release. I also intend -to create logs and diffs asynchronously, which should also help a lot -but also requires major refactoring. - - Meanwhile you can tell Magit to only automatically refresh the -current Magit buffer, but not the status buffer. If you do that, then -the status buffer is only refreshed automatically if it is the current -buffer. - - (setq magit-refresh-status-buffer nil) - - You should also check whether any third-party packages have added -anything to ‘magit-refresh-buffer-hook’, ‘magit-status-refresh-hook’, -‘magit-pre-refresh-hook’, and ‘magit-post-refresh-hook’. If so, then -check whether those additions impact performance significantly. Setting -‘magit-refresh-verbose’ and then inspecting the output in the -‘*Messages*’ buffer, should help doing so. - - Magit also reverts buffers for visited files located inside the -current repository when the visited file changes on disk. That is -implemented on top of ‘auto-revert-mode’ from the built-in library -‘autorevert’. To figure out whether that impacts performance, check -whether performance is significantly worse, when many buffers exist -and/or when some buffers visit files using TRAMP. If so, then this -should help. - - (setq auto-revert-buffer-list-filter - 'magit-auto-revert-repository-buffers-p) - - For alternative approaches see *note Automatic Reverting of -File-Visiting Buffers::. - - If you have enabled any features that are disabled by default, then -you should check whether they impact performance significantly. It’s -likely that they were not enabled by default because it is known that -they reduce performance at least in large repositories. - - If performance is only slow inside certain unusually large -repositories, then you might want to disable certain features on a -per-repository or per-repository-class basis only. See *note -Per-Repository Configuration::. - -* Menu: - -* Microsoft Windows Performance:: -* MacOS Performance:: - -Log Performance -............... - -When showing logs, Magit limits the number of commits initially shown in -the hope that this avoids unnecessary work. When using ‘--graph’ is -used, then this unfortunately does not have the desired effect for large -histories. Junio, Git’s maintainer, said on the git mailing list -(): "‘--graph’ wants to -compute the whole history and the max-count only affects the output -phase after ‘--graph’ does its computation". - - In other words, it’s not that Git is slow at outputting the -differences, or that Magit is slow at parsing the output - the problem -is that Git first goes outside and has a smoke. - - We actually work around this issue by limiting the number of commits -not only by using ‘-’ but by also using a range. But unfortunately -that’s not always possible. - - In repositories with more than a few thousand commits ‘--graph’ -should never be a member of ‘magit-log-section-arguments’. That -variable is used in the status buffer which is refreshed every time you -run any Magit command. - - Using ‘--color --graph’ is even slower. Magit uses code that is part -of Emacs to turn control characters into faces. That code is pretty -slow and this is quite noticeable when showing a log with many branches -and merges. For that reason ‘--color’ is not enabled by default -anymore. Consider leaving it at that. - -Diff Performance -................ - -If diffs are slow, then consider turning off some optional diff features -by setting all or some of the following variables to ‘nil’: -‘magit-diff-highlight-indentation’, ‘magit-diff-highlight-trailing’, -‘magit-diff-paint-whitespace’, ‘magit-diff-highlight-hunk-body’, and -‘magit-diff-refine-hunk’. - - When showing a commit instead of some arbitrary diff, then some -additional information is displayed. Calculating this information can -be quite expensive given certain circumstances. If looking at a commit -using ‘magit-revision-mode’ takes considerably more time than looking at -the same commit in ‘magit-diff-mode’, then consider setting -‘magit-revision-insert-related-refs’ to ‘nil’. - -Refs Buffer Performance -....................... - -When refreshing the "references buffer" is slow, then that’s usually -because several hundred refs are being displayed. The best way to -address that is to display fewer refs, obviously. - - If you are not, or only mildly, interested in seeing the list of -tags, then start by not displaying them: - - (remove-hook 'magit-refs-sections-hook 'magit-insert-tags) - - Then you should also make sure that the listed remote branches -actually all exist. You can do so by pruning branches which no longer -exist using ‘f-pa’. - -Committing Performance -...................... - -When you initiate a commit, then Magit by default automatically shows a -diff of the changes you are about to commit. For large commits this can -take a long time, which is especially distracting when you are -committing large amounts of generated data which you don’t actually -intend to inspect before committing. This behavior can be turned off -using: - - (remove-hook 'server-switch-hook 'magit-commit-diff) - - Then you can type ‘C-c C-d’ to show the diff when you actually want -to see it, but only then. Alternatively you can leave the hook alone -and just type ‘C-g’ in those cases when it takes too long to generate -the diff. If you do that, then you will end up with a broken diff -buffer, but doing it this way has the advantage that you usually get to -see the diff, which is useful because it increases the odds that you -spot potential issues. - -The Built-In VC Package -....................... - -Emacs comes with a version control interface called "VC", see *note -(emacs)Version Control::. It is enabled be default, and if you don’t -use it in addition to Magit, then you should disable it to keep it from -performing unnecessary work: - - (setq vc-handled-backends nil) - - You can also disable its use for Git but keep using it when using -another version control system: - - (setq vc-handled-backends (delq 'Git vc-handled-backends)) - diff --git a/elpa/magit-20190122.503/magit.info-2 b/elpa/magit-20190514.1814/magit.info-2 similarity index 75% rename from elpa/magit-20190122.503/magit.info-2 rename to elpa/magit-20190514.1814/magit.info-2 index 30df6f52..ecffe62b 100644 --- a/elpa/magit-20190122.503/magit.info-2 +++ b/elpa/magit-20190514.1814/magit.info-2 @@ -17,6 +17,632 @@ START-INFO-DIR-ENTRY * Magit: (magit). Using Git from Emacs with Magit. END-INFO-DIR-ENTRY + +File: magit.info, Node: Wip Graph, Next: Legacy Wip Modes, Up: Wip Modes + +8.7.1 Wip Graph +--------------- + + -- User Option: magit-wip-merge-branch + + This option controls whether the current branch is merged into the + wip refs after a new commit was created on the branch. + + If non-nil and the current branch has new commits, then it is + merged into the wip ref before creating a new wip commit. This + makes it easier to inspect wip history and the wip commits are + never garbage collected. + + If nil and the current branch has new commits, then the wip ref is + reset to the tip of the branch before creating a new wip commit. + With this setting wip commits are eventually garbage collected. + + When ‘magit-wip-merge-branch’ is ‘t’, then the history looks like +this: + + *--*--*--*--*--* refs/wip/index/refs/heads/master + / / / + A-----B-----C refs/heads/master + + When ‘magit-wip-merge-branch’ is ‘nil’, then creating a commit on the +real branch and then making a change causes the wip refs to be recreated +to fork from the new commit. But the old commits on the wip refs are +not lost. They are still available from the reflog. To make it easier +to see when the fork point of a wip ref was changed, an additional +commit with the message "restart autosaving" is created on it (‘xxO’ +commits below are such boundary commits). + + Starting with + + BI0---BI1 refs/wip/index/refs/heads/master + / + A---B refs/heads/master + \ + BW0---BW1 refs/wip/wtree/refs/heads/master + + and committing the staged changes and editing and saving a file would +result in + + BI0---BI1 refs/wip/index/refs/heads/master + / + A---B---C refs/heads/master + \ \ + \ CW0---CW1 refs/wip/wtree/refs/heads/master + \ + BW0---BW1 refs/wip/wtree/refs/heads/master@{2} + + The fork-point of the index wip ref is not changed until some change +is being staged. Likewise just checking out a branch or creating a +commit does not change the fork-point of the working tree wip ref. The +fork-points are not adjusted until there actually is a change that +should be committed to the respective wip ref. + + +File: magit.info, Node: Legacy Wip Modes, Prev: Wip Graph, Up: Wip Modes + +8.7.2 Legacy Wip Modes +---------------------- + +It is recommended that you use the mode ‘magit-wip-mode’ (which see) and +ignore the existence of the following modes, which are preserved for +historic reasons. + + Setting the following variables directly does not take effect; either +use the Custom interface to do so or call the respective mode functions. + + -- User Option: magit-wip-after-save-mode + + When this mode is enabled, then saving a buffer that visits a file + tracked in a Git repository causes its current state to be + committed to the working tree wip ref for the current branch. + + -- User Option: magit-wip-after-apply-mode + + When this mode is enabled, then applying (i.e. staging, unstaging, + discarding, reversing, and regularly applying) a change to a file + tracked in a Git repository causes its current state to be + committed to the index and/or working tree wip refs for the current + branch. + + If you only ever edit files using Emacs and only ever interact with +Git using Magit, then the above two modes should be enough to protect +each and every change from accidental loss. In practice nobody does +that. Two additional modes exists that do commit to the wip refs before +making changes that could cause the loss of earlier changes. + + -- User Option: magit-wip-before-change-mode + + When this mode is enabled, then certain commands commit the + existing changes to the files they are about to make changes to. + + -- User Option: magit-wip-initial-backup-mode + + When this mode is enabled, then the current version of a file is + committed to the worktree wip ref before the buffer visiting that + file is saved for the first time since the buffer was created. + + This backs up the same version of the file that ‘backup-buffer’ + would save. While ‘backup-buffer’ uses a backup file, this mode + uses the same worktree wip ref as used by the other Magit Wip + modes. Like ‘backup-buffer’, it only does this once; unless you + kill the buffer and visit the file again only one backup will be + created per Emacs session. + + This mode ignores the variables that affect ‘backup-buffer’ and can + be used along-side that function, which is recommended because it + only backs up files that are tracked in a Git repository. + + -- User Option: magit-wip-after-save-local-mode-lighter + + Mode-line lighter for ‘magit-wip-after-save-local-mode’. + + -- User Option: magit-wip-after-apply-mode-lighter + + Mode-line lighter for ‘magit-wip-after-apply-mode’. + + -- User Option: magit-wip-before-change-mode-lighter + + Mode-line lighter for ‘magit-wip-before-change-mode’. + + -- User Option: magit-wip-initial-backup-mode-lighter + + Mode-line lighter for ‘magit-wip-initial-backup-mode’. + + +File: magit.info, Node: Minor Mode for Buffers Visiting Files, Next: Minor Mode for Buffers Visiting Blobs, Prev: Wip Modes, Up: Miscellaneous + +8.8 Minor Mode for Buffers Visiting Files +========================================= + +The minor-mode ‘magit-file-mode’ enables certain Magit features in +file-visiting buffers belonging to a Git repository. The globalized +variant ‘global-magit-file-mode’ enables the local mode in all such +buffers. It is enabled by default. Currently the local mode only +establishes a few key bindings, but this might be extended in the +future. + + -- User Option: global-magit-file-mode + + Whether to establish certain Magit key bindings in all + file-visiting buffers belonging to any Git repository. This is + enabled by default. This globalized mode turns on the local + minor-mode ‘magit-file-mode’ in all suitable buffers. + + -- Variable: magit-file-mode-map + + This keymap is used by the local minor-mode ‘magit-file-mode’ and + establishes the key bindings described below. + + Note that the default binding for ‘magit-file-dispatch’ is very + cumbersome to use and that we recommend that you add a better + binding. + + Instead of ‘C-c M-g’ I would have preferred to use ‘C-c g’ because + (1) it is similar to ‘C-x g’ (the recommended global binding for + ‘~magit-status’), (2) we cannot use ‘C-c C-g’ because we have been + recommending that that be bound to ‘magit-dispatch’ for a long + time, (3) we cannot use ‘C-x C-g’ because that is a convenient way + of aborting the incomplete key sequence ‘C-x’, and most importantly + (4) it would make it much easier to type the next key (a suffix + binding) because most of those are letters. + + For example ‘C-c g b’ is much easier to type than ‘C-c M-g b’. For + suffix bindings that use uppercase letters, the default is just + horrible—having to use e.g. ‘C-c M-g B’ (‘Control+c Meta+g + Shift+b’) would drive anyone up the walls (or to Vim). + + However ‘C-c LETTER’ bindings are reserved for users (see *note + (elisp)Key Binding Conventions::). Packages are forbidden from + using those. Doing so anyway is considered heresy. Therefore if + you want a better binding, you have to add it yourself: + + (define-key magit-file-mode-map + (kbd "C-c g") 'magit-file-dispatch) + + The key bindings shown below assume that you have not improved the +binding for ‘magit-file-dispatch’. + +‘C-c M-g’ (‘magit-file-dispatch’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + +‘C-c M-g s’ (‘magit-stage-file’) + + Stage all changes to the file being visited in the current buffer. + +‘C-c M-g u’ (‘magit-unstage-file’) + + Unstage all changes to the file being visited in the current + buffer. + +‘C-c M-g c’ (‘magit-commit’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. See *note Initiating a + Commit::. + +‘C-c M-g D’ (‘magit-diff’) + + This transient prefix command binds several diff suffix commands + and infix arguments and displays them in a temporary buffer until a + suffix is invoked. See *note Diffing::. + + This is the same command that ‘d’ is bound to in Magit buffers. If + this command is invoked from a file-visiting buffer, then the + initial value of the option (‘--’) that limits the diff to certain + file(s) is set to the visited file. + +‘C-c M-g d’ (‘magit-diff-buffer-file’) + + This command shows the diff for the file of blob that the current + buffer visits. + + -- User Option: magit-diff-buffer-file-locked + + This option controls whether ‘magit-diff-buffer-file’ uses a + dedicated buffer. See *note Modes and Buffers::. + +‘C-c M-g L’ (‘magit-log’) + + This transient prefix command binds several log suffix commands and + infix arguments and displays them in a temporary buffer until a + suffix is invoked. See *note Logging::. + + This is the same command that ‘l’ is bound to in Magit buffers. If + this command is invoked from a file-visiting buffer, then the + initial value of the option (‘--’) that limits the log to certain + file(s) is set to the visited file. + +‘C-c M-g l’ (‘magit-log-buffer-file’) + + This command shows the log for the file of blob that the current + buffer visits. Renames are followed when a prefix argument is used + or when ‘--follow’ is part of ‘magit-log-arguments’. When the + region is active, the log is restricted to the selected line range. + +‘C-c M-g t’ (‘magit-log-trace-definition’) + + This command shows the log for the definition at point. + + -- User Option: magit-log-buffer-file-locked + + This option controls whether ‘magit-log-buffer-file’ uses a + dedicated buffer. See *note Modes and Buffers::. + +‘C-c M-g B’ (‘magit-blame’) + + This transient prefix command binds all blaming suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + For more information about this and the following commands also see + *note Blaming::. + + In addition to the ‘magit-blame’ sub-transient, the dispatch +transient also binds several blaming suffix commands directly. See +*note Blaming:: for information about those commands and bindings. + +‘C-c M-g e’ (‘magit-edit-line-commit’) + + This command makes the commit editable that added the current line. + + With a prefix argument it makes the commit editable that removes + the line, if any. The commit is determined using ‘git blame’ and + made editable using ‘git rebase --interactive’ if it is reachable + from ‘HEAD’, or by checking out the commit (or a branch that points + at it) otherwise. + +‘C-c M-g p’ (‘magit-blob-previous’) + + Visit the previous blob which modified the current file. + + There are a few additional commands that operate on a single file but +are not enabled in the file transient command by default: + + -- Command: magit-file-rename + + This command renames a file read from the user. + + -- Command: magit-file-delete + + This command deletes a file read from the user. + + -- Command: magit-file-untrack + + This command untracks a file read from the user. + + -- Command: magit-file-checkout + + This command updates a file in the working tree and index to the + contents from a revision. Both the revision and file are read from + the user. + + To enable them invoke the transient (‘C-c M-g’), enter "edit mode" +(‘C-x l’), set the "transient level" (‘C-x l’ again), enter ‘5’, and +leave edit mode (‘C-g’). Also see *note (transient)Enabling and +Disabling Suffixes::. + + +File: magit.info, Node: Minor Mode for Buffers Visiting Blobs, Prev: Minor Mode for Buffers Visiting Files, Up: Miscellaneous + +8.9 Minor Mode for Buffers Visiting Blobs +========================================= + +The ‘magit-blob-mode’ enables certain Magit features in blob-visiting +buffers. Such buffers can be created using ‘magit-find-file’ and some +of the commands mentioned below, which also take care of turning on this +minor mode. Currently this mode only establishes a few key bindings, +but this might be extended. + +‘p’ (‘magit-blob-previous’) + + Visit the previous blob which modified the current file. + +‘n’ (‘magit-blob-next’) + + Visit the next blob which modified the current file. + +‘q’ (‘magit-kill-this-buffer’) + + Kill the current buffer. + + +File: magit.info, Node: Customizing, Next: Plumbing, Prev: Miscellaneous, Up: Top + +9 Customizing +************* + +Both Git and Emacs are highly customizable. Magit is both a Git +porcelain as well as an Emacs package, so it makes sense to customize it +using both Git variables as well as Emacs options. However this +flexibility doesn’t come without problems, including but not limited to +the following. + + • Some Git variables automatically have an effect in Magit without + requiring any explicit support. Sometimes that is desirable - in + other cases, it breaks Magit. + + When a certain Git setting breaks Magit but you want to keep using + that setting on the command line, then that can be accomplished by + overriding the value for Magit only by appending something like + ‘("-c" "some.variable=compatible-value")’ to + ‘magit-git-global-arguments’. + + • Certain settings like ‘fetch.prune=true’ are respected by Magit + commands (because they simply call the respective Git command) but + their value is not reflected in the respective transient buffers. + In this case the ‘--prune’ argument in ‘magit-fetch’ might be + active or inactive, but that doesn’t keep the Git variable from + being honored by the suffix commands anyway. So pruning might + happen despite the ‘--prune’ arguments being displayed in a way + that seems to indicate that no pruning will happen. + + I intend to address these and similar issues in a future release. + +* Menu: + +* Per-Repository Configuration:: +* Essential Settings:: + + +File: magit.info, Node: Per-Repository Configuration, Next: Essential Settings, Up: Customizing + +9.1 Per-Repository Configuration +================================ + +Magit can be configured on a per-repository level using both Git +variables as well as Emacs options. + + To set a Git variable for one repository only, simply set it in +‘/path/to/repo/.git/config’ instead of ‘$HOME/.gitconfig’ or +‘/etc/gitconfig’. See *note (gitman)git-config::. + + Similarly, Emacs options can be set for one repository only by +editing ‘/path/to/repo/.dir-locals.el’. See *note (emacs)Directory +Variables::. For example to disable automatic refreshes of +file-visiting buffers in just one huge repository use this: + + • ‘/path/to/huge/repo/.dir-locals.el’ + + ((nil . ((magit-refresh-buffers . nil)))) + + If you want to apply the same settings to several, but not all, +repositories then keeping the repository-local config files in sync +would quickly become annoying. To avoid that you can create config +files for certain classes of repositories (e.g. "huge repositories") +and then include those files in the per-repository config files. For +example: + + • ‘/path/to/huge/repo/.git/config’ + + [include] + path = /path/to/huge-gitconfig + + • ‘/path/to/huge-gitconfig’ + + [status] + showUntrackedFiles = no + + • ‘$HOME/.emacs.d/init.el’ + + (dir-locals-set-class-variables 'huge-git-repository + '((nil . ((magit-refresh-buffers . nil))))) + + (dir-locals-set-directory-class + "/path/to/huge/repo/" 'huge-git-repository) + + +File: magit.info, Node: Essential Settings, Prev: Per-Repository Configuration, Up: Customizing + +9.2 Essential Settings +====================== + +The next two sections list and discuss several variables that many users +might want to customize, for safety and/or performance reasons. + +* Menu: + +* Safety:: +* Performance:: + + +File: magit.info, Node: Safety, Next: Performance, Up: Essential Settings + +9.2.1 Safety +------------ + +This section discusses various variables that you might want to change +(or *not* change) for safety reasons. + + Git keeps *committed* changes around long enough for users to recover +changes they have accidentally been deleted. It does not do the same +for *uncommitted* changes in the working tree and not even the index +(the staging area). Because Magit makes it so easy to modify +uncommitted changes, it also makes it easy to shoot yourself in the foot +in the process. For that reason Magit provides three global modes that +save *tracked* files to work-in-progress references after or before +certain actions. See *note Wip Modes::. + + These modes are not enabled by default because of performance +concerns. Instead a lot of potentially destructive commands require +confirmation every time they are used. In many cases this can be +disabled by adding a symbol to ‘magit-no-confirm’ (see *note Completion +and Confirmation::). If you enable the various wip modes then you +should add ‘safe-with-wip’ to this list. + + Similarly it isn’t necessary to require confirmation before moving a +file to the system trash - if you trashed a file by mistake then you can +recover it from the there. Option ‘magit-delete-by-moving-to-trash’ +controls whether the system trash is used, which is the case by default. +Nevertheless, ‘trash’ isn’t a member of ‘magit-no-confirm’ - you might +want to change that. + + By default buffers visiting files are automatically reverted when the +visited file changes on disk. This isn’t as risky as it might seem, but +to make an informed decision you should see *note Risk of Reverting +Automatically::. + + +File: magit.info, Node: Performance, Prev: Safety, Up: Essential Settings + +9.2.2 Performance +----------------- + +After Magit has run ‘git’ for side-effects, it also refreshes the +current Magit buffer and the respective status buffer. This is +necessary because otherwise outdated information might be displayed +without the user noticing. Magit buffers are updated by recreating +their content from scratch, which makes updating simpler and less +error-prone, but also more costly. Keeping it simple and just +re-creating everything from scratch is an old design decision and +departing from that will require major refactoring. + + I plan to do that in time for the next major release. I also intend +to create logs and diffs asynchronously, which should also help a lot +but also requires major refactoring. + + Meanwhile you can tell Magit to only automatically refresh the +current Magit buffer, but not the status buffer. If you do that, then +the status buffer is only refreshed automatically if it is the current +buffer. + + (setq magit-refresh-status-buffer nil) + + You should also check whether any third-party packages have added +anything to ‘magit-refresh-buffer-hook’, ‘magit-status-refresh-hook’, +‘magit-pre-refresh-hook’, and ‘magit-post-refresh-hook’. If so, then +check whether those additions impact performance significantly. Setting +‘magit-refresh-verbose’ and then inspecting the output in the +‘*Messages*’ buffer, should help doing so. + + Magit also reverts buffers for visited files located inside the +current repository when the visited file changes on disk. That is +implemented on top of ‘auto-revert-mode’ from the built-in library +‘autorevert’. To figure out whether that impacts performance, check +whether performance is significantly worse, when many buffers exist +and/or when some buffers visit files using TRAMP. If so, then this +should help. + + (setq auto-revert-buffer-list-filter + 'magit-auto-revert-repository-buffer-p) + + For alternative approaches see *note Automatic Reverting of +File-Visiting Buffers::. + + If you have enabled any features that are disabled by default, then +you should check whether they impact performance significantly. It’s +likely that they were not enabled by default because it is known that +they reduce performance at least in large repositories. + + If performance is only slow inside certain unusually large +repositories, then you might want to disable certain features on a +per-repository or per-repository-class basis only. See *note +Per-Repository Configuration::. + +* Menu: + +* Microsoft Windows Performance:: +* MacOS Performance:: + +Log Performance +............... + +When showing logs, Magit limits the number of commits initially shown in +the hope that this avoids unnecessary work. When using ‘--graph’ is +used, then this unfortunately does not have the desired effect for large +histories. Junio, Git’s maintainer, said on the git mailing list +(): "‘--graph’ wants to +compute the whole history and the max-count only affects the output +phase after ‘--graph’ does its computation". + + In other words, it’s not that Git is slow at outputting the +differences, or that Magit is slow at parsing the output - the problem +is that Git first goes outside and has a smoke. + + We actually work around this issue by limiting the number of commits +not only by using ‘-’ but by also using a range. But unfortunately +that’s not always possible. + + In repositories with more than a few thousand commits ‘--graph’ +should never be a member of ‘magit-log-section-arguments’. That +variable is used in the status buffer which is refreshed every time you +run any Magit command. + + Using ‘--color --graph’ is even slower. Magit uses code that is part +of Emacs to turn control characters into faces. That code is pretty +slow and this is quite noticeable when showing a log with many branches +and merges. For that reason ‘--color’ is not enabled by default +anymore. Consider leaving it at that. + +Diff Performance +................ + +If diffs are slow, then consider turning off some optional diff features +by setting all or some of the following variables to ‘nil’: +‘magit-diff-highlight-indentation’, ‘magit-diff-highlight-trailing’, +‘magit-diff-paint-whitespace’, ‘magit-diff-highlight-hunk-body’, and +‘magit-diff-refine-hunk’. + + When showing a commit instead of some arbitrary diff, then some +additional information is displayed. Calculating this information can +be quite expensive given certain circumstances. If looking at a commit +using ‘magit-revision-mode’ takes considerably more time than looking at +the same commit in ‘magit-diff-mode’, then consider setting +‘magit-revision-insert-related-refs’ to ‘nil’. + +Refs Buffer Performance +....................... + +When refreshing the "references buffer" is slow, then that’s usually +because several hundred refs are being displayed. The best way to +address that is to display fewer refs, obviously. + + If you are not, or only mildly, interested in seeing the list of +tags, then start by not displaying them: + + (remove-hook 'magit-refs-sections-hook 'magit-insert-tags) + + Then you should also make sure that the listed remote branches +actually all exist. You can do so by pruning branches which no longer +exist using ‘f-pa’. + +Committing Performance +...................... + +When you initiate a commit, then Magit by default automatically shows a +diff of the changes you are about to commit. For large commits this can +take a long time, which is especially distracting when you are +committing large amounts of generated data which you don’t actually +intend to inspect before committing. This behavior can be turned off +using: + + (remove-hook 'server-switch-hook 'magit-commit-diff) + + Then you can type ‘C-c C-d’ to show the diff when you actually want +to see it, but only then. Alternatively you can leave the hook alone +and just type ‘C-g’ in those cases when it takes too long to generate +the diff. If you do that, then you will end up with a broken diff +buffer, but doing it this way has the advantage that you usually get to +see the diff, which is useful because it increases the odds that you +spot potential issues. + +The Built-In VC Package +....................... + +Emacs comes with a version control interface called "VC", see *note +(emacs)Version Control::. It is enabled be default, and if you don’t +use it in addition to Magit, then you should disable it to keep it from +performing unnecessary work: + + (setq vc-handled-backends nil) + + You can also disable its use for Git but keep using it when using +another version control system: + + (setq vc-handled-backends (delq 'Git vc-handled-backends)) +  File: magit.info, Node: Microsoft Windows Performance, Next: MacOS Performance, Up: Performance @@ -92,9 +718,9 @@ abstractions to extend Magit itself or implement a separate extension. A few of the low-level features used by Magit have been factored out into separate libraries/packages, so that they can be used by other -packages, without having to depend on Magit. These libraries are -described in separate manuals, see *note (with-editor)Top:: and *note -(magit-popup)Top::. +packages, without having to depend on Magit. See *note +(with-editor)Top:: for information about ‘with-editor’. ‘transient’ +doesn’t have a manual yet. If you are trying to find an unused key that you can bind to a command provided by your own Magit extension, then checkout @@ -718,11 +1344,11 @@ where ‘*’ may be something like ‘diff’) with the value of arguments. The value is usually set using ‘magit-mode-setup’, but in some - cases it’s also useful to provide commands which can change the - value. For example, the ‘magit-diff-refresh-popup’ can be used to - change any of the arguments used to display the diff, without - having to specify again which differences should be shown. - ‘magit-diff-more-context’, ‘magit-diff-less-context’, and + cases it’s also useful to provide commands that can change the + value. For example, the ‘magit-diff-refresh’ transient can be used + to change any of the arguments used to display the diff, without + having to specify again which differences should be shown, but + ‘magit-diff-more-context’, ‘magit-diff-less-context’ and ‘magit-diff-default-context’ change just the ‘-U’ argument. In both case this is done by changing the value of this variable and then calling this ‘magit-refresh-function’. @@ -1329,99 +1955,110 @@ Appendix C Keystroke Index * !: Running Git Manually. (line 12) * ! !: Running Git Manually. - (line 16) + (line 17) * ! a: Running Git Manually. - (line 57) + (line 58) * ! b: Running Git Manually. - (line 61) + (line 62) * ! g: Running Git Manually. - (line 65) + (line 66) * ! k: Running Git Manually. - (line 53) + (line 54) * ! p: Running Git Manually. - (line 24) + (line 25) * ! s: Running Git Manually. - (line 34) + (line 35) * ! S: Running Git Manually. - (line 39) + (line 40) * $: Viewing Git Output. (line 16) * %: Worktree. (line 8) * % b: Worktree. (line 13) * % c: Worktree. (line 17) * % g: Worktree. (line 26) * % k: Worktree. (line 21) -* +: Log Buffer. (line 59) -* + <1>: Refreshing Diffs. (line 68) -* -: Log Buffer. (line 63) -* - <1>: Refreshing Diffs. (line 64) -* 0: Refreshing Diffs. (line 72) +* +: Log Buffer. (line 61) +* + <1>: Refreshing Diffs. (line 69) +* -: Log Buffer. (line 65) +* - <1>: Refreshing Diffs. (line 65) +* 0: Refreshing Diffs. (line 73) * 1: Section Visibility. (line 26) * 2: Section Visibility. (line 27) * 3: Section Visibility. (line 28) * 4: Section Visibility. (line 29) -* =: Log Buffer. (line 53) +* =: Log Buffer. (line 55) * ^: Section Movement. (line 31) * a: Applying. (line 33) * A: Cherry Picking. (line 8) -* A A: Cherry Picking. (line 16) -* A a: Cherry Picking. (line 23) -* A A <1>: Cherry Picking. (line 89) -* A a <1>: Cherry Picking. (line 97) -* A d: Cherry Picking. (line 53) -* A h: Cherry Picking. (line 41) -* A n: Cherry Picking. (line 64) -* A s: Cherry Picking. (line 75) -* A s <1>: Cherry Picking. (line 93) +* A A: Cherry Picking. (line 17) +* A a: Cherry Picking. (line 24) +* A A <1>: Cherry Picking. (line 90) +* A a <1>: Cherry Picking. (line 98) +* A d: Cherry Picking. (line 54) +* A h: Cherry Picking. (line 42) +* A n: Cherry Picking. (line 65) +* A s: Cherry Picking. (line 76) +* A s <1>: Cherry Picking. (line 94) * B: Bisecting. (line 8) -* b: Blaming. (line 86) -* b <1>: The Branch Popup. (line 12) +* b: Blaming. (line 105) +* b <1>: Branch Commands. (line 12) +* b <2>: Editing Rebase Sequences. + (line 85) * B B: Bisecting. (line 16) * B b: Bisecting. (line 31) -* b b: The Branch Popup. (line 37) -* b C: The Branch Popup. (line 29) -* b c: The Branch Popup. (line 55) +* b b: Branch Commands. (line 49) +* b C: Branch Commands. (line 29) +* b c: Branch Commands. (line 67) * B g: Bisecting. (line 36) * B k: Bisecting. (line 41) -* b k: The Branch Popup. (line 129) -* b l: The Branch Popup. (line 62) -* b n: The Branch Popup. (line 45) +* b k: Branch Commands. (line 147) +* b l: Branch Commands. (line 74) +* b n: Branch Commands. (line 57) * B r: Bisecting. (line 47) -* b r: The Branch Popup. (line 135) +* b r: Branch Commands. (line 153) * B s: Bisecting. (line 24) -* b s: The Branch Popup. (line 85) -* b x: The Branch Popup. (line 113) -* c: Blaming. (line 120) +* b s: Branch Commands. (line 97) +* b S: Branch Commands. (line 125) +* b x: Branch Commands. (line 131) +* c: Blaming. (line 138) +* C: Cloning Repository. (line 20) * c <1>: Initiating a Commit. (line 8) * c <2>: Editing Rebase Sequences. (line 72) -* c a: Initiating a Commit. (line 18) -* c A: Initiating a Commit. (line 66) -* c c: Initiating a Commit. (line 13) -* c e: Initiating a Commit. (line 22) -* c f: Initiating a Commit. (line 42) -* c F: Initiating a Commit. (line 50) -* c s: Initiating a Commit. (line 54) -* c S: Initiating a Commit. (line 62) -* c w: Initiating a Commit. (line 32) -* C-: Diff Buffer. (line 48) +* c a: Initiating a Commit. (line 19) +* c A: Initiating a Commit. (line 67) +* C b: Cloning Repository. (line 41) +* C C: Cloning Repository. (line 29) +* c c: Initiating a Commit. (line 14) +* C d: Cloning Repository. (line 54) +* C e: Cloning Repository. (line 61) +* c e: Initiating a Commit. (line 23) +* c f: Initiating a Commit. (line 43) +* c F: Initiating a Commit. (line 51) +* C m: Cloning Repository. (line 46) +* C s: Cloning Repository. (line 34) +* c s: Initiating a Commit. (line 55) +* c S: Initiating a Commit. (line 63) +* c w: Initiating a Commit. (line 33) +* C-: Visiting Files and Blobs from a Diff. + (line 51) * C-: Section Visibility. (line 13) * C-c C-a: Editing Commit Messages. (line 128) -* C-c C-b: Log Buffer. (line 19) -* C-c C-b <1>: Refreshing Diffs. (line 90) -* C-c C-c: Popup Buffers and Prefix Commands. - (line 20) +* C-c C-b: Log Buffer. (line 21) +* C-c C-b <1>: Refreshing Diffs. (line 91) +* C-c C-c: Transient Commands. (line 18) * C-c C-c <1>: Select from Log. (line 20) * C-c C-c <2>: Editing Commit Messages. (line 19) * C-c C-c <3>: Editing Rebase Sequences. (line 6) -* C-c C-d: Refreshing Diffs. (line 80) +* C-c C-d: Refreshing Diffs. (line 81) * C-c C-d <1>: Editing Commit Messages. (line 57) -* C-c C-e: Diff Buffer. (line 80) -* C-c C-f: Log Buffer. (line 23) -* C-c C-f <1>: Refreshing Diffs. (line 94) +* C-c C-e: Commands Available in Diffs. + (line 25) +* C-c C-f: Log Buffer. (line 25) +* C-c C-f <1>: Refreshing Diffs. (line 95) * C-c C-i: Editing Commit Messages. (line 153) * C-c C-k: Select from Log. (line 26) @@ -1429,7 +2066,7 @@ Appendix C Keystroke Index (line 24) * C-c C-k <2>: Editing Rebase Sequences. (line 11) -* C-c C-n: Log Buffer. (line 27) +* C-c C-n: Log Buffer. (line 29) * C-c C-o: Editing Commit Messages. (line 144) * C-c C-p: Editing Commit Messages. @@ -1438,67 +2075,72 @@ Appendix C Keystroke Index (line 132) * C-c C-s: Editing Commit Messages. (line 136) -* C-c C-t: Diff Buffer. (line 70) +* C-c C-t: Commands Available in Diffs. + (line 14) * C-c C-t <1>: Editing Commit Messages. (line 140) * C-c C-w: Editing Commit Messages. (line 63) * C-c M-g: Minor Mode for Buffers Visiting Files. - (line 19) -* C-c M-g B: Minor Mode for Buffers Visiting Files. - (line 80) -* C-c M-g b: Minor Mode for Buffers Visiting Files. - (line 86) + (line 54) +* C-c M-g B: Blaming. (line 21) +* C-c M-g b: Blaming. (line 32) +* C-c M-g B <1>: Minor Mode for Buffers Visiting Files. + (line 123) +* C-c M-g B b: Blaming. (line 33) +* C-c M-g B e: Blaming. (line 67) +* C-c M-g B f: Blaming. (line 58) +* C-c M-g B r: Blaming. (line 49) * C-c M-g c: Minor Mode for Buffers Visiting Files. - (line 33) + (line 68) * C-c M-g D: Minor Mode for Buffers Visiting Files. - (line 39) + (line 75) * C-c M-g d: Minor Mode for Buffers Visiting Files. - (line 47) -* C-c M-g e: Minor Mode for Buffers Visiting Files. - (line 102) -* C-c M-g f: Minor Mode for Buffers Visiting Files. - (line 96) + (line 86) +* C-c M-g e: Blaming. (line 66) +* C-c M-g e <1>: Minor Mode for Buffers Visiting Files. + (line 136) +* C-c M-g f: Blaming. (line 57) * C-c M-g L: Minor Mode for Buffers Visiting Files. - (line 57) + (line 96) * C-c M-g l: Minor Mode for Buffers Visiting Files. - (line 64) + (line 107) * C-c M-g p: Minor Mode for Buffers Visiting Files. - (line 112) -* C-c M-g r: Minor Mode for Buffers Visiting Files. - (line 91) + (line 146) +* C-c M-g r: Blaming. (line 48) * C-c M-g s: Minor Mode for Buffers Visiting Files. - (line 24) + (line 59) * C-c M-g t: Minor Mode for Buffers Visiting Files. - (line 71) + (line 114) * C-c M-g u: Minor Mode for Buffers Visiting Files. - (line 28) + (line 63) * C-c M-s: Editing Commit Messages. (line 35) * C-w: Common Commands. (line 27) * C-x g: Status Buffer. (line 22) * C-x u: Editing Rebase Sequences. - (line 89) -* d: Diffing. (line 20) + (line 94) +* d: Diffing. (line 21) * D: Refreshing Diffs. (line 11) -* d c: Diffing. (line 67) -* d d: Diffing. (line 25) -* D f: Refreshing Diffs. (line 45) -* D F: Refreshing Diffs. (line 50) -* D g: Refreshing Diffs. (line 16) -* d p: Diffing. (line 59) -* d r: Diffing. (line 29) -* D r: Refreshing Diffs. (line 40) -* d s: Diffing. (line 49) -* D s: Refreshing Diffs. (line 21) -* d t: Diffing. (line 72) -* D t: Refreshing Diffs. (line 36) -* d u: Diffing. (line 55) -* d w: Diffing. (line 43) -* D w: Refreshing Diffs. (line 28) -* DEL: Log Buffer. (line 43) -* DEL <1>: Diff Buffer. (line 109) -* DEL <2>: Blaming. (line 73) +* d c: Diffing. (line 69) +* d d: Diffing. (line 27) +* D f: Refreshing Diffs. (line 46) +* D F: Refreshing Diffs. (line 51) +* D g: Refreshing Diffs. (line 17) +* d p: Diffing. (line 61) +* d r: Diffing. (line 31) +* D r: Refreshing Diffs. (line 41) +* d s: Diffing. (line 51) +* D s: Refreshing Diffs. (line 22) +* d t: Diffing. (line 74) +* D t: Refreshing Diffs. (line 37) +* d u: Diffing. (line 57) +* d w: Diffing. (line 45) +* D w: Refreshing Diffs. (line 29) +* DEL: Log Buffer. (line 45) +* DEL <1>: Commands Available in Diffs. + (line 60) +* DEL <2>: Blaming. (line 92) * DEL <3>: Editing Rebase Sequences. (line 28) * e: Ediffing. (line 9) @@ -1515,66 +2157,71 @@ Appendix C Keystroke Index * E z: Ediffing. (line 69) * f: Editing Rebase Sequences. (line 63) -* f <1>: Fetching. (line 11) -* F: Pulling. (line 11) -* f a: Fetching. (line 38) -* f e: Fetching. (line 24) -* F e: Pulling. (line 24) -* f m: Fetching. (line 42) -* f o: Fetching. (line 28) -* f p: Fetching. (line 16) -* F p: Pulling. (line 16) -* f r: Fetching. (line 33) -* f u: Fetching. (line 20) -* F u: Pulling. (line 20) +* f <1>: Fetching. (line 9) +* F: Pulling. (line 9) +* f a: Fetching. (line 46) +* f C: Branch Commands. (line 30) +* F C: Branch Commands. (line 31) +* f e: Fetching. (line 32) +* F e: Pulling. (line 31) +* f m: Fetching. (line 50) +* f o: Fetching. (line 36) +* f p: Fetching. (line 15) +* F p: Pulling. (line 14) +* f r: Fetching. (line 41) +* f u: Fetching. (line 24) +* F u: Pulling. (line 23) * g: Automatic Refreshing of Magit Buffers. - (line 22) + (line 24) * G: Automatic Refreshing of Magit Buffers. - (line 31) -* j: Diff Buffer. (line 99) + (line 33) +* j: Commands Available in Diffs. + (line 45) * k: Viewing Git Output. (line 24) * k <1>: Applying. (line 40) * k <2>: Editing Rebase Sequences. (line 68) -* k <3>: Stashing. (line 95) -* l: Logging. (line 28) +* k <3>: Stashing. (line 96) +* l: Logging. (line 29) * L: Refreshing Logs. (line 11) * L <1>: Log Buffer. (line 6) * L <2>: Log Margin. (line 47) -* l a: Logging. (line 58) -* l b: Logging. (line 54) +* l <1>: Editing Rebase Sequences. + (line 115) +* l a: Logging. (line 60) +* l b: Logging. (line 56) * L d: Log Margin. (line 64) -* L g: Refreshing Logs. (line 16) -* l h: Logging. (line 46) +* L g: Refreshing Logs. (line 17) +* l h: Logging. (line 48) * l H: Reflog. (line 19) -* l l: Logging. (line 33) -* l L: Logging. (line 50) +* l l: Logging. (line 35) +* l L: Logging. (line 52) * L L: Log Margin. (line 56) * L l: Log Margin. (line 60) -* l o: Logging. (line 39) +* l o: Logging. (line 41) * l O: Reflog. (line 15) * l r: Reflog. (line 11) -* L s: Refreshing Logs. (line 21) -* L t: Refreshing Logs. (line 36) -* L w: Refreshing Logs. (line 28) +* L s: Refreshing Logs. (line 22) +* L t: Refreshing Logs. (line 37) +* L w: Refreshing Logs. (line 29) * m: Merging. (line 9) -* M: The Remote Popup. (line 13) -* m a: Merging. (line 44) -* m a <1>: Merging. (line 94) -* M a: The Remote Popup. (line 35) -* M C: The Remote Popup. (line 26) -* m e: Merging. (line 30) -* m i: Merging. (line 57) -* M k: The Remote Popup. (line 50) -* m m: Merging. (line 17) -* m m <1>: Merging. (line 88) -* m n: Merging. (line 37) -* m p: Merging. (line 80) -* M p: The Remote Popup. (line 54) -* M P: The Remote Popup. (line 59) -* M r: The Remote Popup. (line 40) -* m s: Merging. (line 71) -* M u: The Remote Popup. (line 45) +* M: Remote Commands. (line 13) +* m a: Merging. (line 45) +* m a <1>: Merging. (line 95) +* M a: Remote Commands. (line 50) +* M C: Remote Commands. (line 33) +* m e: Merging. (line 31) +* m i: Merging. (line 58) +* M k: Remote Commands. (line 65) +* m m: Merging. (line 18) +* m m <1>: Merging. (line 89) +* m n: Merging. (line 38) +* m p: Merging. (line 81) +* M p: Remote Commands. (line 69) +* M P: Remote Commands. (line 74) +* M r: Remote Commands. (line 55) +* m s: Merging. (line 72) +* M u: Remote Commands. (line 60) * M-1: Section Visibility. (line 33) * M-2: Section Visibility. (line 34) * M-3: Section Visibility. (line 35) @@ -1590,18 +2237,15 @@ Appendix C Keystroke Index (line 39) * M-p <2>: Editing Rebase Sequences. (line 43) -* M-w: Blaming. (line 112) +* M-w: Blaming. (line 130) * M-w <1>: Common Commands. (line 10) -* M-x magit-clone: Repository Setup. (line 16) * M-x magit-debug-git-executable: Git Executable. (line 45) * M-x magit-debug-git-executable <1>: Debugging Tools. (line 30) * M-x magit-describe-section-briefly: Section Types and Values. (line 13) * M-x magit-describe-section-briefly <1>: Matching Sections. (line 6) * M-x magit-emacs-Q-command: Debugging Tools. (line 16) -* M-x magit-find-file: Visiting Blobs. (line 6) -* M-x magit-find-file-other-window: Visiting Blobs. (line 11) -* M-x magit-init: Repository Setup. (line 6) +* M-x magit-init: Creating Repository. (line 6) * M-x magit-reset-index: Staging and Unstaging. (line 87) * M-x magit-reverse-in-index: Staging and Unstaging. @@ -1615,69 +2259,77 @@ Appendix C Keystroke Index * M-x magit-version <1>: Debugging Tools. (line 10) * M-x magit-wip-commit: Wip Modes. (line 88) * M-x with-editor-debug: Debugging Tools. (line 38) +* MM: Editing Rebase Sequences. + (line 125) +* Mt: Editing Rebase Sequences. + (line 132) * n: Section Movement. (line 16) -* n <1>: Blaming. (line 91) -* N: Blaming. (line 95) +* n <1>: Blaming. (line 109) +* N: Blaming. (line 113) * n <2>: Editing Rebase Sequences. (line 39) * n <3>: Minor Mode for Buffers Visiting Blobs. (line 16) -* o: Submodule Popup. (line 6) +* o: Submodule Transient. (line 6) * O: Subtree. (line 8) -* o a: Submodule Popup. (line 19) -* O a: Subtree. (line 20) -* O c: Subtree. (line 24) -* o d: Submodule Popup. (line 49) -* o f: Submodule Popup. (line 57) -* O f: Subtree. (line 32) -* o l: Submodule Popup. (line 53) -* O m: Subtree. (line 28) -* o p: Submodule Popup. (line 33) -* O p: Subtree. (line 36) -* o r: Submodule Popup. (line 26) -* o s: Submodule Popup. (line 43) -* O s: Subtree. (line 41) -* o u: Submodule Popup. (line 38) +* o a: Submodule Transient. (line 20) +* o d: Submodule Transient. (line 50) +* O e: Subtree. (line 42) +* O e p: Subtree. (line 54) +* O e s: Subtree. (line 59) +* o f: Submodule Transient. (line 58) +* O i: Subtree. (line 13) +* O i a: Subtree. (line 25) +* O i c: Subtree. (line 30) +* O i f: Subtree. (line 38) +* O i m: Subtree. (line 34) +* o l: Submodule Transient. (line 54) +* o p: Submodule Transient. (line 34) +* o r: Submodule Transient. (line 27) +* o s: Submodule Transient. (line 44) +* o u: Submodule Transient. (line 39) * p: Section Movement. (line 10) -* p <1>: Blaming. (line 99) -* P: Blaming. (line 103) +* p <1>: Blaming. (line 117) +* P: Blaming. (line 121) * p <2>: Editing Rebase Sequences. (line 35) -* P <1>: Pushing. (line 11) +* P <1>: Pushing. (line 9) * p <3>: Minor Mode for Buffers Visiting Blobs. (line 12) -* P e: Pushing. (line 35) -* P m: Pushing. (line 53) -* P o: Pushing. (line 39) -* P p: Pushing. (line 16) -* P r: Pushing. (line 44) -* P t: Pushing. (line 59) -* P T: Pushing. (line 65) -* P u: Pushing. (line 26) +* P C: Branch Commands. (line 32) +* P e: Pushing. (line 31) +* P m: Pushing. (line 50) +* P o: Pushing. (line 36) +* P p: Pushing. (line 15) +* P r: Pushing. (line 41) +* P t: Pushing. (line 58) +* P T: Pushing. (line 66) +* P u: Pushing. (line 23) * q: Quitting Windows. (line 6) -* q <1>: Log Buffer. (line 12) -* q <2>: Blaming. (line 107) +* q <1>: Log Buffer. (line 14) +* q <2>: Blaming. (line 125) * q <3>: Minor Mode for Buffers Visiting Blobs. (line 20) * r: Rebasing. (line 9) * r <1>: Editing Rebase Sequences. (line 51) -* r a: Rebasing. (line 107) -* r e: Rebasing. (line 33) -* r e <1>: Rebasing. (line 103) -* r f: Rebasing. (line 73) -* r i: Rebasing. (line 69) -* r k: Rebasing. (line 85) -* r m: Rebasing. (line 77) -* r p: Rebasing. (line 24) -* r r: Rebasing. (line 92) -* r s: Rebasing. (line 39) -* r s <1>: Rebasing. (line 99) -* r u: Rebasing. (line 29) -* r w: Rebasing. (line 81) -* RET: Diff Buffer. (line 8) -* RET <1>: References Buffer. (line 166) -* RET <2>: Blaming. (line 59) +* r a: Rebasing. (line 124) +* r e: Rebasing. (line 45) +* r e <1>: Rebasing. (line 119) +* r f: Rebasing. (line 85) +* r i: Rebasing. (line 81) +* r k: Rebasing. (line 100) +* r m: Rebasing. (line 90) +* r p: Rebasing. (line 28) +* r r: Rebasing. (line 107) +* r s: Rebasing. (line 51) +* r s <1>: Rebasing. (line 114) +* r u: Rebasing. (line 37) +* r w: Rebasing. (line 95) +* RET: References Buffer. (line 174) +* RET <1>: Visiting Files and Blobs from a Diff. + (line 8) +* RET <2>: Blaming. (line 78) * RET <3>: Editing Rebase Sequences. (line 16) * s: Staging and Unstaging. @@ -1687,23 +2339,26 @@ Appendix C Keystroke Index * s <1>: Editing Rebase Sequences. (line 59) * S-: Section Visibility. (line 22) -* SPC: Log Buffer. (line 33) -* SPC <1>: Diff Buffer. (line 105) -* SPC <2>: Blaming. (line 63) +* SPC: Log Buffer. (line 35) +* SPC <1>: Commands Available in Diffs. + (line 56) +* SPC <2>: Blaming. (line 82) * SPC <3>: Editing Rebase Sequences. (line 21) -* t: Tagging. (line 8) +* t: Editing Rebase Sequences. + (line 119) +* t <1>: Tagging. (line 8) * T: Notes. (line 8) -* T a: Notes. (line 51) -* T c: Notes. (line 46) -* t k: Tagging. (line 39) -* T m: Notes. (line 37) -* t p: Tagging. (line 46) -* T p: Notes. (line 29) -* t r: Tagging. (line 18) -* T r: Notes. (line 21) -* t t: Tagging. (line 13) -* T T: Notes. (line 13) +* T a: Notes. (line 52) +* T c: Notes. (line 47) +* t k: Tagging. (line 40) +* T m: Notes. (line 38) +* t p: Tagging. (line 47) +* T p: Notes. (line 30) +* t r: Tagging. (line 19) +* T r: Notes. (line 22) +* t t: Tagging. (line 14) +* T T: Notes. (line 14) * TAB: Section Visibility. (line 9) * u: Staging and Unstaging. (line 43) @@ -1711,25 +2366,22 @@ Appendix C Keystroke Index (line 52) * v: Applying. (line 44) * V: Reverting. (line 6) -* V A: Reverting. (line 30) -* V a: Reverting. (line 38) -* V s: Reverting. (line 34) -* V V: Reverting. (line 14) -* V v: Reverting. (line 20) -* W: Creating and Sending Patches. - (line 6) -* w: Applying Patches. (line 8) -* w a: Applying Patches. (line 34) -* w a <1>: Applying Patches. (line 42) -* w a a: Applying Patches. (line 47) -* w m: Applying Patches. (line 19) -* W p: Creating and Sending Patches. - (line 11) -* W r: Creating and Sending Patches. - (line 17) -* w s: Applying Patches. (line 30) -* w w: Applying Patches. (line 13) -* w w <1>: Applying Patches. (line 26) +* V A: Reverting. (line 31) +* V a: Reverting. (line 39) +* V s: Reverting. (line 35) +* V V: Reverting. (line 15) +* V v: Reverting. (line 21) +* W: Plain Patches. (line 6) +* w: Maildir Patches. (line 8) +* w a: Plain Patches. (line 21) +* w a <1>: Maildir Patches. (line 25) +* w a <2>: Maildir Patches. (line 43) +* W c: Plain Patches. (line 12) +* w m: Maildir Patches. (line 21) +* W s: Plain Patches. (line 28) +* w s: Maildir Patches. (line 38) +* w w: Maildir Patches. (line 14) +* w w <1>: Maildir Patches. (line 34) * x: Editing Rebase Sequences. (line 76) * x <1>: Resetting. (line 8) @@ -1743,26 +2395,26 @@ Appendix C Keystroke Index * Y: Cherries. (line 17) * y: References Buffer. (line 6) * y <1>: Editing Rebase Sequences. - (line 85) -* y c: References Buffer. (line 19) -* y o: References Buffer. (line 24) -* y y: References Buffer. (line 14) + (line 90) +* y c: References Buffer. (line 26) +* y o: References Buffer. (line 32) +* y y: References Buffer. (line 21) * z: Stashing. (line 8) -* z a: Stashing. (line 58) -* z b: Stashing. (line 80) -* z B: Stashing. (line 85) -* z f: Stashing. (line 91) -* z i: Stashing. (line 20) -* z I: Stashing. (line 46) -* z k: Stashing. (line 71) -* z l: Stashing. (line 99) -* z p: Stashing. (line 64) -* z v: Stashing. (line 76) -* z w: Stashing. (line 25) -* z W: Stashing. (line 51) -* z x: Stashing. (line 32) -* z z: Stashing. (line 13) -* z Z: Stashing. (line 39) +* z a: Stashing. (line 59) +* z b: Stashing. (line 81) +* z B: Stashing. (line 86) +* z f: Stashing. (line 92) +* z i: Stashing. (line 21) +* z I: Stashing. (line 47) +* z k: Stashing. (line 72) +* z l: Stashing. (line 100) +* z p: Stashing. (line 65) +* z v: Stashing. (line 77) +* z w: Stashing. (line 26) +* z W: Stashing. (line 52) +* z x: Stashing. (line 33) +* z z: Stashing. (line 14) +* z Z: Stashing. (line 40)  File: magit.info, Node: Command Index, Next: Function Index, Prev: Keystroke Index, Up: Top @@ -1773,8 +2425,6 @@ Appendix D Command Index [index] * Menu: -* auto-revert-mode: Automatic Reverting of File-Visiting Buffers. - (line 62) * forward-line: Editing Rebase Sequences. (line 39) * git-commit-ack: Editing Commit Messages. @@ -1799,6 +2449,8 @@ Appendix D Command Index (line 140) * git-rebase-backward-line: Editing Rebase Sequences. (line 35) +* git-rebase-break: Editing Rebase Sequences. + (line 85) * git-rebase-edit: Editing Rebase Sequences. (line 55) * git-rebase-exec: Editing Rebase Sequences. @@ -1806,15 +2458,23 @@ Appendix D Command Index * git-rebase-fixup: Editing Rebase Sequences. (line 63) * git-rebase-insert: Editing Rebase Sequences. - (line 85) + (line 90) * git-rebase-kill-line: Editing Rebase Sequences. (line 68) +* git-rebase-label: Editing Rebase Sequences. + (line 115) +* git-rebase-merge: Editing Rebase Sequences. + (line 125) +* git-rebase-merge-toggle-editmsg: Editing Rebase Sequences. + (line 132) * git-rebase-move-line-down: Editing Rebase Sequences. (line 47) * git-rebase-move-line-up: Editing Rebase Sequences. (line 43) * git-rebase-pick: Editing Rebase Sequences. (line 72) +* git-rebase-reset: Editing Rebase Sequences. + (line 119) * git-rebase-reword: Editing Rebase Sequences. (line 51) * git-rebase-show-commit: Editing Rebase Sequences. @@ -1826,87 +2486,94 @@ Appendix D Command Index * git-rebase-squash: Editing Rebase Sequences. (line 59) * git-rebase-undo: Editing Rebase Sequences. - (line 89) + (line 94) * ido-enter-magit-status: Status Buffer. (line 72) -* magit-am-abort: Applying Patches. (line 34) -* magit-am-apply-maildir: Applying Patches. (line 19) -* magit-am-apply-patches: Applying Patches. (line 13) -* magit-am-continue: Applying Patches. (line 26) -* magit-am-popup: Applying Patches. (line 8) -* magit-am-skip: Applying Patches. (line 30) +* magit-am: Maildir Patches. (line 8) +* magit-am-abort: Maildir Patches. (line 43) +* magit-am-apply-maildir: Maildir Patches. (line 21) +* magit-am-apply-patches: Maildir Patches. (line 14) +* magit-am-continue: Maildir Patches. (line 34) +* magit-am-skip: Maildir Patches. (line 38) * magit-apply: Applying. (line 33) +* magit-bisect: Bisecting. (line 8) * magit-bisect-bad: Bisecting. (line 31) * magit-bisect-good: Bisecting. (line 36) -* magit-bisect-popup: Bisecting. (line 8) * magit-bisect-reset: Bisecting. (line 47) * magit-bisect-run: Bisecting. (line 24) * magit-bisect-skip: Bisecting. (line 41) * magit-bisect-start: Bisecting. (line 16) -* magit-blame-addition: Blaming. (line 17) -* magit-blame-addition <1>: Minor Mode for Buffers Visiting Files. - (line 86) -* magit-blame-copy-hash: Blaming. (line 112) -* magit-blame-cycle-style: Blaming. (line 120) -* magit-blame-echo: Blaming. (line 32) -* magit-blame-next-chunk: Blaming. (line 91) -* magit-blame-next-chunk-same-commit: Blaming. (line 95) -* magit-blame-popup: Blaming. (line 86) -* magit-blame-popup <1>: Minor Mode for Buffers Visiting Files. - (line 80) -* magit-blame-previous-chunk: Blaming. (line 99) -* magit-blame-previous-chunk-same-commit: Blaming. (line 103) -* magit-blame-quit: Blaming. (line 107) -* magit-blame-removal: Blaming. (line 38) -* magit-blame-removal <1>: Minor Mode for Buffers Visiting Files. - (line 91) -* magit-blame-reverse: Blaming. (line 46) -* magit-blame-reverse <1>: Minor Mode for Buffers Visiting Files. - (line 96) +* magit-blame: Blaming. (line 21) +* magit-blame <1>: Blaming. (line 105) +* magit-blame <2>: Minor Mode for Buffers Visiting Files. + (line 123) +* magit-blame-addition: Blaming. (line 32) +* magit-blame-addition <1>: Blaming. (line 33) +* magit-blame-copy-hash: Blaming. (line 130) +* magit-blame-cycle-style: Blaming. (line 138) +* magit-blame-echo: Blaming. (line 66) +* magit-blame-echo <1>: Blaming. (line 67) +* magit-blame-next-chunk: Blaming. (line 109) +* magit-blame-next-chunk-same-commit: Blaming. (line 113) +* magit-blame-previous-chunk: Blaming. (line 117) +* magit-blame-previous-chunk-same-commit: Blaming. (line 121) +* magit-blame-quit: Blaming. (line 125) +* magit-blame-removal: Blaming. (line 48) +* magit-blame-removal <1>: Blaming. (line 49) +* magit-blame-reverse: Blaming. (line 57) +* magit-blame-reverse <1>: Blaming. (line 58) * magit-blob-next: Minor Mode for Buffers Visiting Blobs. (line 16) * magit-blob-previous: Minor Mode for Buffers Visiting Files. - (line 112) + (line 146) * magit-blob-previous <1>: Minor Mode for Buffers Visiting Blobs. (line 12) -* magit-branch-and-checkout: The Branch Popup. (line 55) -* magit-branch-checkout: The Branch Popup. (line 62) -* magit-branch-config-popup: The Branch Popup. (line 29) -* magit-branch-config-popup <1>: The Branch Config Popup. - (line 6) -* magit-branch-create: The Branch Popup. (line 45) -* magit-branch-delete: The Branch Popup. (line 129) -* magit-branch-or-checkout: The Branch Popup. (line 239) -* magit-branch-orphan: The Branch Popup. (line 234) -* magit-branch-popup: The Branch Popup. (line 12) -* magit-branch-rename: The Branch Popup. (line 135) -* magit-branch-reset: The Branch Popup. (line 113) +* magit-branch: Branch Commands. (line 12) +* magit-branch-and-checkout: Branch Commands. (line 67) +* magit-branch-checkout: Branch Commands. (line 74) +* magit-branch-configure: Branch Commands. (line 29) +* magit-branch-configure <1>: Branch Commands. (line 30) +* magit-branch-configure <2>: Branch Commands. (line 31) +* magit-branch-configure <3>: Branch Commands. (line 32) +* magit-branch-create: Branch Commands. (line 57) +* magit-branch-delete: Branch Commands. (line 147) +* magit-branch-or-checkout: Branch Commands. (line 257) +* magit-branch-orphan: Branch Commands. (line 252) +* magit-branch-rename: Branch Commands. (line 153) +* magit-branch-reset: Branch Commands. (line 131) * magit-branch-shelve: Auxiliary Branch Commands. - (line 8) -* magit-branch-spinoff: The Branch Popup. (line 85) + (line 9) +* magit-branch-spinoff: Branch Commands. (line 97) +* magit-branch-spinout: Branch Commands. (line 125) * magit-branch-unshelve: Auxiliary Branch Commands. - (line 19) -* magit-checkout: The Branch Popup. (line 37) + (line 20) +* magit-checkout: Branch Commands. (line 49) * magit-cherry: Cherries. (line 17) -* magit-cherry-apply: Cherry Picking. (line 23) -* magit-cherry-copy: Cherry Picking. (line 16) -* magit-cherry-donate: Cherry Picking. (line 53) -* magit-cherry-harvest: Cherry Picking. (line 41) -* magit-cherry-pick-popup: Cherry Picking. (line 8) -* magit-cherry-spinoff: Cherry Picking. (line 75) -* magit-cherry-spinout: Cherry Picking. (line 64) -* magit-clone: Repository Setup. (line 16) -* magit-commit-amend: Initiating a Commit. (line 18) -* magit-commit-augment: Initiating a Commit. (line 66) -* magit-commit-create: Initiating a Commit. (line 13) -* magit-commit-extend: Initiating a Commit. (line 22) -* magit-commit-fixup: Initiating a Commit. (line 42) -* magit-commit-instant-fixup: Initiating a Commit. (line 50) -* magit-commit-instant-squash: Initiating a Commit. (line 62) -* magit-commit-popup: Initiating a Commit. (line 8) -* magit-commit-popup <1>: Minor Mode for Buffers Visiting Files. - (line 33) -* magit-commit-reword: Initiating a Commit. (line 32) -* magit-commit-squash: Initiating a Commit. (line 54) +* magit-cherry-apply: Cherry Picking. (line 24) +* magit-cherry-copy: Cherry Picking. (line 17) +* magit-cherry-donate: Cherry Picking. (line 54) +* magit-cherry-harvest: Cherry Picking. (line 42) +* magit-cherry-pick: Cherry Picking. (line 8) +* magit-cherry-spinoff: Cherry Picking. (line 76) +* magit-cherry-spinout: Cherry Picking. (line 65) +* magit-clone: Cloning Repository. (line 20) +* magit-clone-bare: Cloning Repository. (line 41) +* magit-clone-mirror: Cloning Repository. (line 46) +* magit-clone-regular: Cloning Repository. (line 29) +* magit-clone-shallow: Cloning Repository. (line 34) +* magit-clone-shallow-exclude: Cloning Repository. (line 61) +* magit-clone-shallow-since: Cloning Repository. (line 54) +* magit-commit: Initiating a Commit. (line 8) +* magit-commit <1>: Minor Mode for Buffers Visiting Files. + (line 68) +* magit-commit-amend: Initiating a Commit. (line 19) +* magit-commit-augment: Initiating a Commit. (line 67) +* magit-commit-create: Initiating a Commit. (line 14) +* magit-commit-extend: Initiating a Commit. (line 23) +* magit-commit-fixup: Initiating a Commit. (line 43) +* magit-commit-instant-fixup: Initiating a Commit. (line 51) +* magit-commit-instant-squash: Initiating a Commit. (line 63) +* magit-commit-reword: Initiating a Commit. (line 33) +* magit-commit-squash: Initiating a Commit. (line 55) * magit-copy-buffer-revision: Common Commands. (line 27) * magit-copy-section-value: Common Commands. (line 10) * magit-cycle-margin-style: Log Margin. (line 60) @@ -1915,46 +2582,56 @@ Appendix D Command Index * magit-describe-section-briefly: Section Types and Values. (line 13) * magit-describe-section-briefly <1>: Matching Sections. (line 6) +* magit-diff: Diffing. (line 21) +* magit-diff <1>: Minor Mode for Buffers Visiting Files. + (line 75) * magit-diff-buffer-file: Minor Mode for Buffers Visiting Files. - (line 47) -* magit-diff-buffer-file-popup: Minor Mode for Buffers Visiting Files. - (line 39) -* magit-diff-default-context: Refreshing Diffs. (line 72) -* magit-diff-dwim: Diffing. (line 25) -* magit-diff-edit-hunk-commit: Diff Buffer. (line 80) -* magit-diff-flip-revs: Refreshing Diffs. (line 45) -* magit-diff-less-context: Refreshing Diffs. (line 64) -* magit-diff-more-context: Refreshing Diffs. (line 68) -* magit-diff-paths: Diffing. (line 59) -* magit-diff-popup: Diffing. (line 20) -* magit-diff-range: Diffing. (line 29) -* magit-diff-refresh: Refreshing Diffs. (line 16) -* magit-diff-refresh-popup: Refreshing Diffs. (line 11) -* magit-diff-save-default-arguments: Refreshing Diffs. (line 28) -* magit-diff-set-default-arguments: Refreshing Diffs. (line 21) -* magit-diff-show-or-scroll-down: Log Buffer. (line 43) -* magit-diff-show-or-scroll-down <1>: Blaming. (line 73) -* magit-diff-show-or-scroll-up: Log Buffer. (line 33) -* magit-diff-show-or-scroll-up <1>: Blaming. (line 63) -* magit-diff-staged: Diffing. (line 49) -* magit-diff-switch-range-type: Refreshing Diffs. (line 40) -* magit-diff-toggle-file-filter: Refreshing Diffs. (line 50) -* magit-diff-toggle-refine-hunk: Refreshing Diffs. (line 36) -* magit-diff-trace-definition: Diff Buffer. (line 70) -* magit-diff-unstaged: Diffing. (line 55) -* magit-diff-visit-file: Diff Buffer. (line 8) -* magit-diff-visit-file-other-window: Diff Buffer. (line 65) -* magit-diff-visit-file-worktree: Diff Buffer. (line 48) -* magit-diff-while-committing: Refreshing Diffs. (line 80) + (line 86) +* magit-diff-default-context: Refreshing Diffs. (line 73) +* magit-diff-dwim: Diffing. (line 27) +* magit-diff-edit-hunk-commit: Commands Available in Diffs. + (line 25) +* magit-diff-flip-revs: Refreshing Diffs. (line 46) +* magit-diff-less-context: Refreshing Diffs. (line 65) +* magit-diff-more-context: Refreshing Diffs. (line 69) +* magit-diff-paths: Diffing. (line 61) +* magit-diff-range: Diffing. (line 31) +* magit-diff-refresh: Refreshing Diffs. (line 11) +* magit-diff-refresh <1>: Refreshing Diffs. (line 17) +* magit-diff-save-default-arguments: Refreshing Diffs. (line 29) +* magit-diff-set-default-arguments: Refreshing Diffs. (line 22) +* magit-diff-show-or-scroll-down: Log Buffer. (line 45) +* magit-diff-show-or-scroll-down <1>: Blaming. (line 92) +* magit-diff-show-or-scroll-up: Log Buffer. (line 35) +* magit-diff-show-or-scroll-up <1>: Blaming. (line 82) +* magit-diff-staged: Diffing. (line 51) +* magit-diff-switch-range-type: Refreshing Diffs. (line 41) +* magit-diff-toggle-file-filter: Refreshing Diffs. (line 51) +* magit-diff-toggle-refine-hunk: Refreshing Diffs. (line 37) +* magit-diff-trace-definition: Commands Available in Diffs. + (line 14) +* magit-diff-unstaged: Diffing. (line 57) +* magit-diff-visit-file: Visiting Files and Blobs from a Diff. + (line 8) +* magit-diff-visit-file-other-frame: Visiting Files and Blobs from a Diff. + (line 74) +* magit-diff-visit-file-other-window: Visiting Files and Blobs from a Diff. + (line 73) +* magit-diff-visit-file-worktree: Visiting Files and Blobs from a Diff. + (line 51) +* magit-diff-visit-worktree-file-other-frame: Visiting Files and Blobs from a Diff. + (line 76) +* magit-diff-visit-worktree-file-other-window: Visiting Files and Blobs from a Diff. + (line 75) +* magit-diff-while-committing: Refreshing Diffs. (line 81) * magit-diff-while-committing <1>: Editing Commit Messages. (line 57) -* magit-diff-working-tree: Diffing. (line 43) +* magit-diff-working-tree: Diffing. (line 45) * magit-discard: Applying. (line 40) -* magit-dispatch-popup: Popup Buffers and Prefix Commands. - (line 20) +* magit-dispatch: Transient Commands. (line 18) +* magit-ediff: Ediffing. (line 21) * magit-ediff-compare: Ediffing. (line 26) * magit-ediff-dwim: Ediffing. (line 9) -* magit-ediff-popup: Ediffing. (line 21) * magit-ediff-resolve: Ediffing. (line 35) * magit-ediff-show-commit: Ediffing. (line 65) * magit-ediff-show-staged: Ediffing. (line 57) @@ -1963,146 +2640,146 @@ Appendix D Command Index * magit-ediff-show-working-tree: Ediffing. (line 61) * magit-ediff-stage: Ediffing. (line 48) * magit-edit-line-commit: Minor Mode for Buffers Visiting Files. - (line 102) + (line 136) * magit-emacs-Q-command: Debugging Tools. (line 16) -* magit-fetch-all: Fetching. (line 38) -* magit-fetch-branch: Fetching. (line 28) -* magit-fetch-from-pushremote: Fetching. (line 16) -* magit-fetch-from-upstream: Fetching. (line 20) -* magit-fetch-modules: Submodule Popup. (line 57) -* magit-fetch-other: Fetching. (line 24) -* magit-fetch-popup: Fetching. (line 11) -* magit-fetch-refspec: Fetching. (line 33) +* magit-fetch: Fetching. (line 9) +* magit-fetch-all: Fetching. (line 46) +* magit-fetch-branch: Fetching. (line 36) +* magit-fetch-from-pushremote: Fetching. (line 15) +* magit-fetch-from-upstream: Fetching. (line 24) +* magit-fetch-modules: Submodule Transient. (line 58) +* magit-fetch-other: Fetching. (line 32) +* magit-fetch-refspec: Fetching. (line 41) * magit-file-checkout: Resetting. (line 44) * magit-file-checkout <1>: Minor Mode for Buffers Visiting Files. - (line 131) + (line 165) * magit-file-delete: Minor Mode for Buffers Visiting Files. - (line 123) -* magit-file-popup: Minor Mode for Buffers Visiting Files. - (line 19) + (line 157) +* magit-file-dispatch: Minor Mode for Buffers Visiting Files. + (line 54) * magit-file-rename: Minor Mode for Buffers Visiting Files. - (line 119) + (line 153) * magit-file-untrack: Minor Mode for Buffers Visiting Files. - (line 127) -* magit-find-file: Visiting Blobs. (line 6) -* magit-find-file-other-window: Visiting Blobs. (line 11) -* magit-format-patch: Creating and Sending Patches. - (line 11) + (line 161) +* magit-find-file: General-Purpose Visit Commands. + (line 9) +* magit-find-file-other-frame: General-Purpose Visit Commands. + (line 21) +* magit-find-file-other-window: General-Purpose Visit Commands. + (line 15) * magit-git-command: Running Git Manually. - (line 24) + (line 25) * magit-git-command-topdir: Running Git Manually. - (line 16) -* magit-go-backward: Log Buffer. (line 19) -* magit-go-backward <1>: Refreshing Diffs. (line 90) -* magit-go-forward: Log Buffer. (line 23) -* magit-go-forward <1>: Refreshing Diffs. (line 94) -* magit-init: Repository Setup. (line 6) -* magit-jump-to-diffstat-or-diff: Diff Buffer. (line 99) + (line 17) +* magit-go-backward: Log Buffer. (line 21) +* magit-go-backward <1>: Refreshing Diffs. (line 91) +* magit-go-forward: Log Buffer. (line 25) +* magit-go-forward <1>: Refreshing Diffs. (line 95) +* magit-init: Creating Repository. (line 6) +* magit-jump-to-diffstat-or-diff: Commands Available in Diffs. + (line 45) * magit-kill-this-buffer: Minor Mode for Buffers Visiting Blobs. (line 20) * magit-list-repositories: Repository List. (line 6) * magit-list-submodules: Listing Submodules. (line 13) -* magit-list-submodules <1>: Submodule Popup. (line 53) -* magit-log-all: Logging. (line 58) -* magit-log-all-branches: Logging. (line 54) -* magit-log-branches: Logging. (line 50) +* magit-list-submodules <1>: Submodule Transient. (line 54) +* magit-log: Logging. (line 29) +* magit-log <1>: Minor Mode for Buffers Visiting Files. + (line 96) +* magit-log-all: Logging. (line 60) +* magit-log-all-branches: Logging. (line 56) +* magit-log-branches: Logging. (line 52) * magit-log-buffer-file: Minor Mode for Buffers Visiting Files. - (line 64) -* magit-log-buffer-file-popup: Minor Mode for Buffers Visiting Files. - (line 57) -* magit-log-bury-buffer: Log Buffer. (line 12) -* magit-log-current: Logging. (line 33) -* magit-log-double-commit-limit: Log Buffer. (line 59) -* magit-log-half-commit-limit: Log Buffer. (line 63) -* magit-log-head: Logging. (line 46) -* magit-log-move-to-parent: Log Buffer. (line 27) -* magit-log-other: Logging. (line 39) -* magit-log-popup: Logging. (line 28) -* magit-log-refresh: Refreshing Logs. (line 16) -* magit-log-refresh-popup: Refreshing Logs. (line 11) -* magit-log-refresh-popup <1>: Log Buffer. (line 6) -* magit-log-save-default-arguments: Refreshing Logs. (line 28) + (line 107) +* magit-log-bury-buffer: Log Buffer. (line 14) +* magit-log-current: Logging. (line 35) +* magit-log-double-commit-limit: Log Buffer. (line 61) +* magit-log-half-commit-limit: Log Buffer. (line 65) +* magit-log-head: Logging. (line 48) +* magit-log-move-to-parent: Log Buffer. (line 29) +* magit-log-other: Logging. (line 41) +* magit-log-refresh: Refreshing Logs. (line 11) +* magit-log-refresh <1>: Refreshing Logs. (line 17) +* magit-log-refresh <2>: Log Buffer. (line 6) +* magit-log-save-default-arguments: Refreshing Logs. (line 29) * magit-log-select-pick: Select from Log. (line 20) * magit-log-select-quit: Select from Log. (line 26) -* magit-log-set-default-arguments: Refreshing Logs. (line 21) -* magit-log-toggle-commit-limit: Log Buffer. (line 53) +* magit-log-set-default-arguments: Refreshing Logs. (line 22) +* magit-log-toggle-commit-limit: Log Buffer. (line 55) * magit-log-trace-definition: Minor Mode for Buffers Visiting Files. - (line 71) -* magit-margin-popup: Log Margin. (line 47) -* magit-merge: Merging. (line 88) -* magit-merge-abort: Merging. (line 94) -* magit-merge-absorb: Merging. (line 44) -* magit-merge-editmsg: Merging. (line 30) -* magit-merge-into: Merging. (line 57) -* magit-merge-nocommit: Merging. (line 37) -* magit-merge-plain: Merging. (line 17) -* magit-merge-popup: Merging. (line 9) -* magit-merge-preview: Merging. (line 80) -* magit-merge-squash: Merging. (line 71) + (line 114) +* magit-margin-settings: Log Margin. (line 47) +* magit-merge: Merging. (line 9) +* magit-merge <1>: Merging. (line 89) +* magit-merge-abort: Merging. (line 95) +* magit-merge-absorb: Merging. (line 45) +* magit-merge-editmsg: Merging. (line 31) +* magit-merge-into: Merging. (line 58) +* magit-merge-nocommit: Merging. (line 38) +* magit-merge-plain: Merging. (line 18) +* magit-merge-preview: Merging. (line 81) +* magit-merge-squash: Merging. (line 72) * magit-mode-bury-buffer: Quitting Windows. (line 6) -* magit-notes-edit: Notes. (line 13) -* magit-notes-merge: Notes. (line 37) -* magit-notes-merge-abort: Notes. (line 51) -* magit-notes-merge-commit: Notes. (line 46) -* magit-notes-popup: Notes. (line 8) -* magit-notes-prune: Notes. (line 29) -* magit-notes-remove: Notes. (line 21) -* magit-patch-apply: Applying Patches. (line 47) -* magit-patch-apply-popup: Applying Patches. (line 42) -* magit-patch-popup: Creating and Sending Patches. - (line 6) +* magit-notes: Notes. (line 8) +* magit-notes-edit: Notes. (line 14) +* magit-notes-merge: Notes. (line 38) +* magit-notes-merge-abort: Notes. (line 52) +* magit-notes-merge-commit: Notes. (line 47) +* magit-notes-prune: Notes. (line 30) +* magit-notes-remove: Notes. (line 22) +* magit-patch: Plain Patches. (line 6) +* magit-patch-apply: Plain Patches. (line 21) +* magit-patch-apply <1>: Maildir Patches. (line 25) +* magit-patch-create: Plain Patches. (line 12) +* magit-patch-save: Plain Patches. (line 28) * magit-pop-revision-stack: Editing Commit Messages. (line 63) * magit-process: Viewing Git Output. (line 16) * magit-process-kill: Viewing Git Output. (line 24) -* magit-pull-branch: Pulling. (line 24) -* magit-pull-from-pushremote: Pulling. (line 16) -* magit-pull-from-upstream: Pulling. (line 20) -* magit-pull-popup: Pulling. (line 11) -* magit-push-current: Pushing. (line 35) -* magit-push-current-to-pushremote: Pushing. (line 16) -* magit-push-current-to-upstream: Pushing. (line 26) -* magit-push-implicitly args: Pushing. (line 73) -* magit-push-matching: Pushing. (line 53) -* magit-push-other: Pushing. (line 39) -* magit-push-popup: Pushing. (line 11) -* magit-push-refspecs: Pushing. (line 44) -* magit-push-tag: Pushing. (line 65) -* magit-push-tags: Pushing. (line 59) -* magit-push-to-remote remote args: Pushing. (line 84) -* magit-rebase-abort: Rebasing. (line 107) -* magit-rebase-autosquash: Rebasing. (line 73) -* magit-rebase-branch: Rebasing. (line 33) -* magit-rebase-continue: Rebasing. (line 92) -* magit-rebase-edit: Rebasing. (line 103) -* magit-rebase-edit-commit: Rebasing. (line 77) -* magit-rebase-interactive: Rebasing. (line 69) -* magit-rebase-onto-pushremote: Rebasing. (line 24) -* magit-rebase-onto-upstream: Rebasing. (line 29) -* magit-rebase-popup: Rebasing. (line 9) -* magit-rebase-remove-commit: Rebasing. (line 85) -* magit-rebase-reword-commit: Rebasing. (line 81) -* magit-rebase-skip: Rebasing. (line 99) -* magit-rebase-subset: Rebasing. (line 39) +* magit-pull: Pulling. (line 9) +* magit-pull-branch: Pulling. (line 31) +* magit-pull-from-pushremote: Pulling. (line 14) +* magit-pull-from-upstream: Pulling. (line 23) +* magit-push: Pushing. (line 9) +* magit-push-current: Pushing. (line 31) +* magit-push-current-to-pushremote: Pushing. (line 15) +* magit-push-current-to-upstream: Pushing. (line 23) +* magit-push-implicitly args: Pushing. (line 74) +* magit-push-matching: Pushing. (line 50) +* magit-push-other: Pushing. (line 36) +* magit-push-refspecs: Pushing. (line 41) +* magit-push-tag: Pushing. (line 66) +* magit-push-tags: Pushing. (line 58) +* magit-push-to-remote remote args: Pushing. (line 85) +* magit-rebase: Rebasing. (line 9) +* magit-rebase-abort: Rebasing. (line 124) +* magit-rebase-autosquash: Rebasing. (line 85) +* magit-rebase-branch: Rebasing. (line 45) +* magit-rebase-continue: Rebasing. (line 107) +* magit-rebase-edit: Rebasing. (line 119) +* magit-rebase-edit-commit: Rebasing. (line 90) +* magit-rebase-interactive: Rebasing. (line 81) +* magit-rebase-onto-pushremote: Rebasing. (line 28) +* magit-rebase-onto-upstream: Rebasing. (line 37) +* magit-rebase-remove-commit: Rebasing. (line 100) +* magit-rebase-reword-commit: Rebasing. (line 95) +* magit-rebase-skip: Rebasing. (line 114) +* magit-rebase-subset: Rebasing. (line 51) * magit-reflog-current: Reflog. (line 11) * magit-reflog-head: Reflog. (line 19) * magit-reflog-other: Reflog. (line 15) * magit-refresh: Automatic Refreshing of Magit Buffers. - (line 22) + (line 24) * magit-refresh-all: Automatic Refreshing of Magit Buffers. - (line 31) -* magit-remote-add: The Remote Popup. (line 35) -* magit-remote-config-popup: The Remote Popup. (line 26) -* magit-remote-config-popup <1>: The Remote Config Popup. - (line 6) -* magit-remote-popup: The Remote Popup. (line 13) -* magit-remote-prune: The Remote Popup. (line 54) -* magit-remote-prune-refspecs: The Remote Popup. (line 59) -* magit-remote-remove: The Remote Popup. (line 50) -* magit-remote-rename: The Remote Popup. (line 40) -* magit-remote-set-url: The Remote Popup. (line 45) -* magit-request-pull: Creating and Sending Patches. - (line 17) + (line 33) +* magit-remote: Remote Commands. (line 13) +* magit-remote-add: Remote Commands. (line 50) +* magit-remote-configure: Remote Commands. (line 33) +* magit-remote-prune: Remote Commands. (line 69) +* magit-remote-prune-refspecs: Remote Commands. (line 74) +* magit-remote-remove: Remote Commands. (line 65) +* magit-remote-rename: Remote Commands. (line 55) +* magit-remote-set-url: Remote Commands. (line 60) * magit-reset-hard: Resetting. (line 26) * magit-reset-index: Staging and Unstaging. (line 87) @@ -2115,19 +2792,19 @@ Appendix D Command Index * magit-reverse: Applying. (line 44) * magit-reverse-in-index: Staging and Unstaging. (line 62) -* magit-revert-and-commit: Reverting. (line 14) -* magit-revert-no-commit: Reverting. (line 20) -* magit-revert-popup: Reverting. (line 6) +* magit-revert: Reverting. (line 6) +* magit-revert-and-commit: Reverting. (line 15) +* magit-revert-no-commit: Reverting. (line 21) +* magit-run: Running Git Manually. + (line 12) * magit-run-git-gui: Running Git Manually. - (line 65) + (line 66) * magit-run-gitk: Running Git Manually. - (line 53) + (line 54) * magit-run-gitk-all: Running Git Manually. - (line 57) + (line 58) * magit-run-gitk-branches: Running Git Manually. - (line 61) -* magit-run-popup: Running Git Manually. - (line 12) + (line 62) * magit-section-backward: Section Movement. (line 10) * magit-section-backward-siblings: Section Movement. (line 20) * magit-section-cycle: Section Visibility. (line 13) @@ -2151,73 +2828,75 @@ Appendix D Command Index * magit-section-toggle: Section Visibility. (line 9) * magit-section-toggle-children: Section Visibility. (line 68) * magit-section-up: Section Movement. (line 31) -* magit-sequence-abort: Cherry Picking. (line 97) -* magit-sequence-abort <1>: Reverting. (line 38) -* magit-sequence-continue: Cherry Picking. (line 89) -* magit-sequence-continue <1>: Reverting. (line 30) -* magit-sequence-skip: Cherry Picking. (line 93) -* magit-sequence-skip <1>: Reverting. (line 34) +* magit-sequence-abort: Cherry Picking. (line 98) +* magit-sequence-abort <1>: Reverting. (line 39) +* magit-sequence-continue: Cherry Picking. (line 90) +* magit-sequence-continue <1>: Reverting. (line 31) +* magit-sequence-skip: Cherry Picking. (line 94) +* magit-sequence-skip <1>: Reverting. (line 35) * magit-shell-command: Running Git Manually. - (line 39) + (line 40) * magit-shell-command-topdir: Running Git Manually. - (line 34) -* magit-show-commit: Diffing. (line 67) -* magit-show-commit <1>: Blaming. (line 59) -* magit-show-refs: References Buffer. (line 24) -* magit-show-refs-current: References Buffer. (line 19) -* magit-show-refs-head: References Buffer. (line 14) -* magit-show-refs-popup: References Buffer. (line 6) -* magit-snapshot-both: Stashing. (line 39) -* magit-snapshot-index: Stashing. (line 46) -* magit-snapshot-worktree: Stashing. (line 51) + (line 35) +* magit-show-commit: Diffing. (line 69) +* magit-show-commit <1>: Blaming. (line 78) +* magit-show-refs: References Buffer. (line 6) +* magit-show-refs-current: References Buffer. (line 26) +* magit-show-refs-head: References Buffer. (line 21) +* magit-show-refs-other: References Buffer. (line 32) +* magit-snapshot-both: Stashing. (line 40) +* magit-snapshot-index: Stashing. (line 47) +* magit-snapshot-worktree: Stashing. (line 52) * magit-stage: Staging and Unstaging. (line 28) * magit-stage-file: Staging from File-Visiting Buffers. (line 10) * magit-stage-file <1>: Minor Mode for Buffers Visiting Files. - (line 24) + (line 59) * magit-stage-modified: Staging and Unstaging. (line 36) -* magit-stash-apply: Stashing. (line 58) -* magit-stash-both: Stashing. (line 13) -* magit-stash-branch: Stashing. (line 80) -* magit-stash-branch-here: Stashing. (line 85) -* magit-stash-clear: Stashing. (line 95) -* magit-stash-drop: Stashing. (line 71) -* magit-stash-format-patch: Stashing. (line 91) -* magit-stash-index: Stashing. (line 20) -* magit-stash-keep-index: Stashing. (line 32) -* magit-stash-list: Stashing. (line 99) -* magit-stash-pop: Stashing. (line 64) -* magit-stash-popup: Stashing. (line 8) -* magit-stash-show: Diffing. (line 72) -* magit-stash-show <1>: Stashing. (line 76) -* magit-stash-worktree: Stashing. (line 25) +* magit-stash: Stashing. (line 8) +* magit-stash-apply: Stashing. (line 59) +* magit-stash-both: Stashing. (line 14) +* magit-stash-branch: Stashing. (line 81) +* magit-stash-branch-here: Stashing. (line 86) +* magit-stash-clear: Stashing. (line 96) +* magit-stash-drop: Stashing. (line 72) +* magit-stash-format-patch: Stashing. (line 92) +* magit-stash-index: Stashing. (line 21) +* magit-stash-keep-index: Stashing. (line 33) +* magit-stash-list: Stashing. (line 100) +* magit-stash-pop: Stashing. (line 65) +* magit-stash-show: Diffing. (line 74) +* magit-stash-show <1>: Stashing. (line 77) +* magit-stash-worktree: Stashing. (line 26) * magit-status: Status Buffer. (line 22) -* magit-submodule-add: Submodule Popup. (line 19) -* magit-submodule-fetch: Fetching. (line 42) -* magit-submodule-populate: Submodule Popup. (line 33) -* magit-submodule-popup: Submodule Popup. (line 6) -* magit-submodule-register: Submodule Popup. (line 26) -* magit-submodule-synchronize: Submodule Popup. (line 43) -* magit-submodule-unpopulate: Submodule Popup. (line 49) -* magit-submodule-update: Submodule Popup. (line 38) -* magit-subtree-add: Subtree. (line 20) -* magit-subtree-add-commit: Subtree. (line 24) -* magit-subtree-merge: Subtree. (line 28) -* magit-subtree-pull: Subtree. (line 32) -* magit-subtree-push: Subtree. (line 36) -* magit-subtree-split: Subtree. (line 41) -* magit-tag-create: Tagging. (line 13) -* magit-tag-delete: Tagging. (line 39) -* magit-tag-popup: Tagging. (line 8) -* magit-tag-prune: Tagging. (line 46) -* magit-tag-release: Tagging. (line 18) +* magit-submodule: Submodule Transient. (line 6) +* magit-submodule-add: Submodule Transient. (line 20) +* magit-submodule-fetch: Fetching. (line 50) +* magit-submodule-populate: Submodule Transient. (line 34) +* magit-submodule-register: Submodule Transient. (line 27) +* magit-submodule-synchronize: Submodule Transient. (line 44) +* magit-submodule-unpopulate: Submodule Transient. (line 50) +* magit-submodule-update: Submodule Transient. (line 39) +* magit-subtree: Subtree. (line 8) +* magit-subtree-add: Subtree. (line 25) +* magit-subtree-add-commit: Subtree. (line 30) +* magit-subtree-export: Subtree. (line 42) +* magit-subtree-import: Subtree. (line 13) +* magit-subtree-merge: Subtree. (line 34) +* magit-subtree-pull: Subtree. (line 38) +* magit-subtree-push: Subtree. (line 54) +* magit-subtree-split: Subtree. (line 59) +* magit-tag: Tagging. (line 8) +* magit-tag-create: Tagging. (line 14) +* magit-tag-delete: Tagging. (line 40) +* magit-tag-prune: Tagging. (line 47) +* magit-tag-release: Tagging. (line 19) * magit-toggle-buffer-lock: Modes and Buffers. (line 17) -* magit-toggle-margin: Refreshing Logs. (line 36) +* magit-toggle-margin: Refreshing Logs. (line 37) * magit-toggle-margin <1>: Log Margin. (line 56) * magit-toggle-margin-details: Log Margin. (line 64) -* magit-tree-popup: Subtree. (line 8) * magit-unstage: Staging and Unstaging. (line 43) * magit-unstage-all: Staging and Unstaging. @@ -2225,20 +2904,22 @@ Appendix D Command Index * magit-unstage-file: Staging from File-Visiting Buffers. (line 18) * magit-unstage-file <1>: Minor Mode for Buffers Visiting Files. - (line 28) + (line 63) * magit-version: Git Executable. (line 17) * magit-version <1>: Debugging Tools. (line 10) -* magit-visit-ref: References Buffer. (line 166) +* magit-visit-ref: References Buffer. (line 174) * magit-wip-commit: Wip Modes. (line 88) * magit-wip-log: Wip Modes. (line 48) * magit-wip-log-current: Wip Modes. (line 57) +* magit-worktree: Worktree. (line 8) * magit-worktree-branch: Worktree. (line 17) * magit-worktree-checkout: Worktree. (line 13) * magit-worktree-delete: Worktree. (line 21) -* magit-worktree-popup: Worktree. (line 8) * magit-worktree-status: Worktree. (line 26) -* scroll-down: Diff Buffer. (line 109) -* scroll-up: Diff Buffer. (line 105) +* scroll-down: Commands Available in Diffs. + (line 60) +* scroll-up: Commands Available in Diffs. + (line 56) * with-editor-cancel: Editing Commit Messages. (line 24) * with-editor-cancel <1>: Editing Rebase Sequences. @@ -2258,8 +2939,6 @@ Appendix E Function Index [index] * Menu: -* auto-revert-mode: Automatic Reverting of File-Visiting Buffers. - (line 62) * git-commit-check-style-conventions: Editing Commit Messages. (line 247) * git-commit-propertize-diff: Editing Commit Messages. @@ -2275,19 +2954,13 @@ Appendix E Function Index * ido-enter-magit-status: Status Buffer. (line 72) * magit-add-section-hook: Section Hooks. (line 20) * magit-after-save-refresh-status: Automatic Refreshing of Magit Buffers. - (line 56) -* magit-blame-addition: Blaming. (line 17) -* magit-blame-echo: Blaming. (line 32) -* magit-blame-removal: Blaming. (line 38) -* magit-blame-reverse: Blaming. (line 46) -* magit-branch-config-popup: The Branch Config Popup. - (line 6) -* magit-branch-or-checkout: The Branch Popup. (line 239) -* magit-branch-orphan: The Branch Popup. (line 234) + (line 58) +* magit-branch-or-checkout: Branch Commands. (line 257) +* magit-branch-orphan: Branch Commands. (line 252) * magit-branch-shelve: Auxiliary Branch Commands. - (line 8) + (line 9) * magit-branch-unshelve: Auxiliary Branch Commands. - (line 19) + (line 20) * magit-builtin-completing-read: Support for Completion Frameworks. (line 42) * magit-call-git: Calling Git for Effect. @@ -2301,7 +2974,14 @@ Appendix E Function Index * magit-define-section-jumper: Creating Sections. (line 77) * magit-diff-scope: Matching Sections. (line 118) * magit-diff-type: Matching Sections. (line 95) -* magit-diff-visit-file-other-window: Diff Buffer. (line 65) +* magit-diff-visit-file-other-frame: Visiting Files and Blobs from a Diff. + (line 74) +* magit-diff-visit-file-other-window: Visiting Files and Blobs from a Diff. + (line 73) +* magit-diff-visit-worktree-file-other-frame: Visiting Files and Blobs from a Diff. + (line 76) +* magit-diff-visit-worktree-file-other-window: Visiting Files and Blobs from a Diff. + (line 75) * magit-display-buffer: Switching Buffers. (line 6) * magit-display-buffer-fullcolumn-most-v1: Switching Buffers. (line 76) * magit-display-buffer-fullframe-status-topleft-v1: Switching Buffers. @@ -2312,13 +2992,19 @@ Appendix E Function Index (line 54) * magit-display-buffer-traditional: Switching Buffers. (line 46) * magit-file-checkout: Minor Mode for Buffers Visiting Files. - (line 131) + (line 165) * magit-file-delete: Minor Mode for Buffers Visiting Files. - (line 123) + (line 157) * magit-file-rename: Minor Mode for Buffers Visiting Files. - (line 119) + (line 153) * magit-file-untrack: Minor Mode for Buffers Visiting Files. - (line 127) + (line 161) +* magit-find-file: General-Purpose Visit Commands. + (line 9) +* magit-find-file-other-frame: General-Purpose Visit Commands. + (line 21) +* magit-find-file-other-window: General-Purpose Visit Commands. + (line 15) * magit-generate-buffer-name-default-function: Naming Buffers. (line 17) * magit-get-section: Matching Sections. (line 16) @@ -2415,14 +3101,12 @@ Appendix E Function Index * magit-log-maybe-update-revision-buffer: Section Movement. (line 64) * magit-maybe-set-dedicated: Switching Buffers. (line 101) * magit-mode-display-buffer: Refreshing Buffers. (line 33) -* magit-mode-quit-window: Quitting Windows. (line 31) +* magit-mode-quit-window: Quitting Windows. (line 34) * magit-mode-setup: Refreshing Buffers. (line 17) -* magit-push-implicitly: Pushing. (line 73) -* magit-push-to-remote: Pushing. (line 84) +* magit-push-implicitly: Pushing. (line 74) +* magit-push-to-remote: Pushing. (line 85) * magit-region-sections: Section Selection. (line 10) * magit-region-values: Section Selection. (line 37) -* magit-remote-config-popup: The Remote Config Popup. - (line 6) * magit-repolist-column-ident: Repository List. (line 30) * magit-repolist-column-path: Repository List. (line 35) * magit-repolist-column-unpulled-from-pushremote: Repository List. @@ -2434,7 +3118,7 @@ Appendix E Function Index * magit-repolist-column-unpushed-to-upstream: Repository List. (line 54) * magit-repolist-column-version: Repository List. (line 39) -* magit-restore-window-configuration: Quitting Windows. (line 20) +* magit-restore-window-configuration: Quitting Windows. (line 23) * magit-revert-buffers: Editing Commit Messages. (line 178) * magit-run-git: Calling Git for Effect. @@ -2484,27 +3168,29 @@ Appendix F Variable Index (line 81) * auto-revert-interval: Automatic Reverting of File-Visiting Buffers. (line 76) +* auto-revert-mode: Automatic Reverting of File-Visiting Buffers. + (line 62) * auto-revert-stop-on-user-input: Automatic Reverting of File-Visiting Buffers. (line 71) * auto-revert-use-notify: Automatic Reverting of File-Visiting Buffers. (line 49) * auto-revert-verbose: Automatic Reverting of File-Visiting Buffers. (line 103) -* branch.autoSetupMerge: The Branch Config Popup. - (line 94) -* branch.autoSetupRebase: The Branch Config Popup. - (line 111) -* branch.NAME.description: The Branch Config Popup. - (line 61) -* branch.NAME.merge: The Branch Config Popup. - (line 23) -* branch.NAME.pushRemote: The Branch Config Popup. - (line 47) -* branch.NAME.rebase: The Branch Config Popup. - (line 35) -* branch.NAME.remote: The Branch Config Popup. - (line 29) -* core.notesRef: Notes. (line 59) +* branch.autoSetupMerge: Branch Git Variables. + (line 81) +* branch.autoSetupRebase: Branch Git Variables. + (line 98) +* branch.NAME.description: Branch Git Variables. + (line 48) +* branch.NAME.merge: Branch Git Variables. + (line 10) +* branch.NAME.pushRemote: Branch Git Variables. + (line 34) +* branch.NAME.rebase: Branch Git Variables. + (line 22) +* branch.NAME.remote: Branch Git Variables. + (line 16) +* core.notesRef: Notes. (line 60) * git-commit-fill-column: Editing Commit Messages. (line 228) * git-commit-finish-query-functions: Editing Commit Messages. @@ -2518,13 +3204,15 @@ Appendix F Variable Index * git-commit-summary-max-length: Editing Commit Messages. (line 222) * git-rebase-auto-advance: Editing Rebase Sequences. - (line 94) + (line 99) * git-rebase-confirm-cancel: Editing Rebase Sequences. - (line 102) + (line 107) * git-rebase-show-instructions: Editing Rebase Sequences. - (line 98) + (line 103) * global-auto-revert-mode: Automatic Reverting of File-Visiting Buffers. (line 22) +* global-magit-file-mode: Minor Mode for Buffers Visiting Files. + (line 13) * magit-auto-revert-immediately: Automatic Reverting of File-Visiting Buffers. (line 32) * magit-auto-revert-mode: Automatic Reverting of File-Visiting Buffers. @@ -2532,30 +3220,34 @@ Appendix F Variable Index * magit-auto-revert-tracked-only: Automatic Reverting of File-Visiting Buffers. (line 55) * magit-bisect-show-graph: Bisecting. (line 55) -* magit-blame-disable-modes: Blaming. (line 150) -* magit-blame-echo-style: Blaming. (line 133) -* magit-blame-goto-chunk-hook: Blaming. (line 156) -* magit-blame-read-only: Blaming. (line 145) -* magit-blame-styles: Blaming. (line 128) -* magit-blame-time-format: Blaming. (line 140) -* magit-branch-adjust-remote-upstream-alist: The Branch Popup. - (line 192) -* magit-branch-popup-show-variables: The Branch Popup. (line 21) -* magit-branch-prefer-remote-upstream: The Branch Popup. (line 147) -* magit-branch-read-upstream-first: The Branch Popup. (line 141) +* magit-blame-disable-modes: Blaming. (line 168) +* magit-blame-echo-style: Blaming. (line 151) +* magit-blame-goto-chunk-hook: Blaming. (line 174) +* magit-blame-read-only: Blaming. (line 163) +* magit-blame-styles: Blaming. (line 146) +* magit-blame-time-format: Blaming. (line 158) +* magit-branch-adjust-remote-upstream-alist: Branch Commands. (line 210) +* magit-branch-direct-configure: Branch Commands. (line 20) +* magit-branch-prefer-remote-upstream: Branch Commands. (line 165) +* magit-branch-read-upstream-first: Branch Commands. (line 159) * magit-buffer-name-format: Naming Buffers. (line 27) -* magit-bury-buffer-function: Quitting Windows. (line 11) +* magit-bury-buffer-function: Quitting Windows. (line 14) * magit-cherry-margin: Cherries. (line 22) -* magit-clone-set-remote.pushDefault: Repository Setup. (line 23) -* magit-commit-ask-to-stage: Initiating a Commit. (line 74) -* magit-commit-extend-override-date: Initiating a Commit. (line 79) -* magit-commit-reword-override-date: Initiating a Commit. (line 83) -* magit-commit-squash-confirm: Initiating a Commit. (line 87) +* magit-clone-always-transient: Cloning Repository. (line 12) +* magit-clone-default-directory: Cloning Repository. (line 90) +* magit-clone-name-alist: Cloning Repository. (line 103) +* magit-clone-set-remote-head: Cloning Repository. (line 68) +* magit-clone-set-remote.pushDefault: Cloning Repository. (line 78) +* magit-clone-url-format: Cloning Repository. (line 124) +* magit-commit-ask-to-stage: Initiating a Commit. (line 75) +* magit-commit-extend-override-date: Initiating a Commit. (line 80) +* magit-commit-reword-override-date: Initiating a Commit. (line 84) +* magit-commit-squash-confirm: Initiating a Commit. (line 88) * magit-completing-read-function: Support for Completion Frameworks. (line 27) * magit-diff-adjust-tab-width: Diff Options. (line 21) * magit-diff-buffer-file-locked: Minor Mode for Buffers Visiting Files. - (line 52) + (line 91) * magit-diff-hide-trailing-cr-characters: Diff Options. (line 90) * magit-diff-highlight-hunk-region-functions: Diff Options. (line 94) * magit-diff-highlight-indentation: Diff Options. (line 75) @@ -2565,7 +3257,10 @@ Appendix F Variable Index * magit-diff-refine-hunk: Diff Options. (line 6) * magit-diff-refine-ignore-whitespace: Diff Options. (line 16) * magit-diff-unmarked-lines-keep-foreground: Diff Options. (line 120) -* magit-diff-visit-previous-blob: Diff Buffer. (line 37) +* magit-diff-visit-previous-blob: Visiting Files and Blobs from a Diff. + (line 39) +* magit-direct-use-buffer-arguments: Transient Arguments and Buffer Variables. + (line 73) * magit-display-buffer-function: Switching Buffers. (line 27) * magit-display-buffer-noselect: Switching Buffers. (line 18) * magit-dwim-selection: Completion and Confirmation. @@ -2573,8 +3268,8 @@ Appendix F Variable Index * magit-ediff-dwim-show-on-hunks: Ediffing. (line 73) * magit-ediff-quit-hook: Ediffing. (line 88) * magit-ediff-show-stash-with-index: Ediffing. (line 81) -* magit-file-mode: Minor Mode for Buffers Visiting Files. - (line 11) +* magit-file-mode-map: Minor Mode for Buffers Visiting Files. + (line 20) * magit-generate-buffer-name-function: Naming Buffers. (line 6) * magit-git-debug: Viewing Git Output. (line 28) * magit-git-debug <1>: Getting a Value from Git. @@ -2585,15 +3280,16 @@ Appendix F Variable Index * magit-keep-region-overlay: The Selection. (line 52) * magit-list-refs-sortby: Additional Completion Options. (line 6) -* magit-log-auto-more: Log Buffer. (line 67) +* magit-log-auto-more: Log Buffer. (line 69) * magit-log-buffer-file-locked: Minor Mode for Buffers Visiting Files. - (line 75) + (line 118) * magit-log-margin: Log Margin. (line 12) * magit-log-section-args: Status Options. (line 36) * magit-log-section-commit-count: Status Sections. (line 120) * magit-log-select-margin: Select from Log. (line 30) -* magit-log-show-refname-after-summary: Log Buffer. (line 73) -* magit-log-trace-definition-function: Diff Buffer. (line 74) +* magit-log-show-refname-after-summary: Log Buffer. (line 75) +* magit-log-trace-definition-function: Commands Available in Diffs. + (line 18) * magit-module-sections-hook: Status Module Sections. (line 20) * magit-module-sections-nested: Status Module Sections. @@ -2603,31 +3299,36 @@ Appendix F Variable Index (line 92) * magit-post-display-buffer-hook: Switching Buffers. (line 96) * magit-pre-display-buffer-hook: Switching Buffers. (line 85) -* magit-prefer-remote-upstream: The Branch Config Popup. - (line 139) +* magit-prefer-remote-upstream: Branch Git Variables. + (line 126) +* magit-prefix-use-buffer-arguments: Transient Arguments and Buffer Variables. + (line 64) * magit-process-raise-error: Calling Git for Effect. (line 151) -* magit-push-current-set-remote-if-missing: Pushing. (line 96) +* magit-pull-or-fetch: Fetching. (line 55) * magit-reflog-margin: Reflog. (line 23) * magit-refresh-args: Refreshing Buffers. (line 55) * magit-refresh-buffer-hook: Automatic Refreshing of Magit Buffers. - (line 40) + (line 42) * magit-refresh-function: Refreshing Buffers. (line 49) * magit-refresh-status-buffer: Automatic Refreshing of Magit Buffers. - (line 46) -* magit-refs-filter-alist: References Buffer. (line 149) -* magit-refs-focus-column-width: References Buffer. (line 74) -* magit-refs-margin: References Buffer. (line 89) -* magit-refs-margin-for-tags: References Buffer. (line 115) -* magit-refs-pad-commit-counts: References Buffer. (line 41) -* magit-refs-primary-column-width: References Buffer. (line 61) + (line 48) +* magit-refs-filter-alist: References Buffer. (line 157) +* magit-refs-focus-column-width: References Buffer. (line 82) +* magit-refs-margin: References Buffer. (line 97) +* magit-refs-margin-for-tags: References Buffer. (line 123) +* magit-refs-pad-commit-counts: References Buffer. (line 49) +* magit-refs-primary-column-width: References Buffer. (line 69) * magit-refs-sections-hook: References Sections. (line 13) -* magit-refs-show-commit-count: References Buffer. (line 29) -* magit-refs-show-remote-prefix: References Buffer. (line 54) -* magit-remote-add-set-remote.pushDefault: The Remote Popup. (line 77) -* magit-remote-popup-show-variables: The Remote Popup. (line 18) +* magit-refs-show-commit-count: References Buffer. (line 37) +* magit-refs-show-remote-prefix: References Buffer. (line 62) +* magit-remote-add-set-remote.pushDefault: Remote Commands. (line 92) +* magit-remote-direct-configure: Remote Commands. (line 21) +* magit-remote-set-if-missing: Remote Git Variables. + (line 39) * magit-repolist-columns: Repository List. (line 14) * magit-repository-directories: Status Buffer. (line 58) +* magit-revision-filter-files-on-follow: Revision Buffer. (line 64) * magit-revision-insert-related-refs: Revision Buffer. (line 6) * magit-revision-show-gravatars: Revision Buffer. (line 19) * magit-revision-use-hash-sections: Revision Buffer. (line 36) @@ -2641,8 +3342,8 @@ Appendix F Variable Index * magit-section-show-child-count: Section Options. (line 9) * magit-section-visibility-indicator: Section Visibility. (line 124) * magit-shell-command-verbose-prompt: Running Git Manually. - (line 46) -* magit-stashes-margin: Stashing. (line 103) + (line 47) +* magit-stashes-margin: Stashing. (line 104) * magit-status-headers-hook: Status Header Sections. (line 18) * magit-status-margin: Status Options. (line 10) @@ -2655,9 +3356,7 @@ Appendix F Variable Index * magit-unstage-committed: Staging and Unstaging. (line 56) * magit-update-other-window-delay: Section Movement. (line 89) -* magit-use-sticky-arguments: Popup Buffers and Prefix Commands. - (line 36) -* magit-visit-ref-behavior: References Buffer. (line 177) +* magit-visit-ref-behavior: References Buffer. (line 185) * magit-wip-after-apply-mode: Legacy Wip Modes. (line 19) * magit-wip-after-apply-mode-lighter: Legacy Wip Modes. (line 59) * magit-wip-after-save-local-mode-lighter: Legacy Wip Modes. (line 55) @@ -2670,19 +3369,19 @@ Appendix F Variable Index * magit-wip-mode: Wip Modes. (line 30) * magit-wip-mode-lighter: Wip Modes. (line 104) * magit-wip-namespace: Wip Modes. (line 96) -* notes.displayRef: Notes. (line 64) -* pull.rebase: The Branch Config Popup. - (line 70) -* remote.NAME.fetch: The Remote Config Popup. - (line 25) -* remote.NAME.push: The Remote Config Popup. - (line 36) -* remote.NAME.pushurl: The Remote Config Popup. - (line 30) -* remote.NAME.tagOpts: The Remote Config Popup. - (line 41) -* remote.NAME.url: The Remote Config Popup. +* notes.displayRef: Notes. (line 65) +* pull.rebase: Branch Git Variables. + (line 57) +* remote.NAME.fetch: Remote Git Variables. + (line 15) +* remote.NAME.push: Remote Git Variables. + (line 26) +* remote.NAME.pushurl: Remote Git Variables. (line 20) -* remote.pushDefault: The Branch Config Popup. - (line 84) +* remote.NAME.tagOpts: Remote Git Variables. + (line 31) +* remote.NAME.url: Remote Git Variables. + (line 10) +* remote.pushDefault: Branch Git Variables. + (line 71) diff --git a/elpa/magit-popup-20181204.2031/dir b/elpa/magit-popup-20190223.2234/dir similarity index 100% rename from elpa/magit-popup-20181204.2031/dir rename to elpa/magit-popup-20190223.2234/dir diff --git a/elpa/magit-popup-20181204.2031/magit-popup-autoloads.el b/elpa/magit-popup-20190223.2234/magit-popup-autoloads.el similarity index 100% rename from elpa/magit-popup-20181204.2031/magit-popup-autoloads.el rename to elpa/magit-popup-20190223.2234/magit-popup-autoloads.el diff --git a/elpa/magit-popup-20181204.2031/magit-popup-pkg.el b/elpa/magit-popup-20190223.2234/magit-popup-pkg.el similarity index 83% rename from elpa/magit-popup-20181204.2031/magit-popup-pkg.el rename to elpa/magit-popup-20190223.2234/magit-popup-pkg.el index 3af4d3e8..de7b0c0e 100644 --- a/elpa/magit-popup-20181204.2031/magit-popup-pkg.el +++ b/elpa/magit-popup-20190223.2234/magit-popup-pkg.el @@ -1,4 +1,4 @@ -(define-package "magit-popup" "20181204.2031" "Define prefix-infix-suffix command combos" +(define-package "magit-popup" "20190223.2234" "Define prefix-infix-suffix command combos" '((emacs "24.4") (async "1.9.2") (dash "2.13.0")) diff --git a/elpa/magit-popup-20181204.2031/magit-popup.el b/elpa/magit-popup-20190223.2234/magit-popup.el similarity index 98% rename from elpa/magit-popup-20181204.2031/magit-popup.el rename to elpa/magit-popup-20190223.2234/magit-popup.el index 7bc3b782..658b2aca 100644 --- a/elpa/magit-popup-20181204.2031/magit-popup.el +++ b/elpa/magit-popup-20190223.2234/magit-popup.el @@ -1,6 +1,6 @@ ;;; magit-popup.el --- Define prefix-infix-suffix command combos -*- lexical-binding: t -*- -;; Copyright (C) 2010-2018 The Magit Project Contributors +;; Copyright (C) 2010-2019 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -32,19 +32,12 @@ ;;; Commentary: ;; This package implements a generic interface for toggling switches -;; and setting options and then invoking an Emacs command which does -;; something with these arguments. The prototypical use is for the -;; command to call an external process, passing on the arguments as -;; command line arguments. But this is only one of many possible -;; uses (though the one this library is optimized for). - -;; With the Emacs concept of "prefix arguments" in mind this could be -;; described as "infix arguments with feedback in a buffer". - -;; Commands that set the prefix argument for the subsequent command do -;; not limit what that next command could be. But entering a command -;; console popup does limit the selection to the commands defined for -;; that popup, and so we use the term "infix" instead of "prefix". +;; and setting options and then invoking an Emacs command that does +;; something with these arguments. Usually the command calls an +;; external process with the specified arguments. + +;; This package has been superseded by Transient. No new features +;; will be added but bugs will be fixes. ;;; Code: diff --git a/elpa/magit-popup-20181204.2031/magit-popup.info b/elpa/magit-popup-20190223.2234/magit-popup.info similarity index 96% rename from elpa/magit-popup-20181204.2031/magit-popup.info rename to elpa/magit-popup-20190223.2234/magit-popup.info index 2c1e18fb..5232b03c 100644 --- a/elpa/magit-popup-20181204.2031/magit-popup.info +++ b/elpa/magit-popup-20190223.2234/magit-popup.info @@ -1,7 +1,7 @@ This is magit-popup.info, produced by makeinfo version 6.5 from magit-popup.texi. - Copyright (C) 2015-2018 Jonas Bernoulli + Copyright (C) 2015-2019 Jonas Bernoulli You can redistribute this document and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -12,6 +12,7 @@ magit-popup.texi. but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + INFO-DIR-SECTION Emacs START-INFO-DIR-ENTRY * Magit-Popup: (magit-popup). Infix arguments with feedback. @@ -23,14 +24,18 @@ File: magit-popup.info, Node: Top, Next: Introduction, Up: (dir) Magit-Popup User Manual *********************** -Taking inspiration from regular prefix commands and prefix arguments, -this library implements a similar abstraction; a new kind of prefix -command that is associated with a specific set of infix arguments and -suffix commands. +This package implements a generic interface for toggling switches and +setting options and then invoking an Emacs command that does something +with these arguments. Usually the command calls an external process +with the specified arguments. + + This package has been superseded by Transient (*note +(transient)Top::). No new features will be added but bugs will be +fixes. -This manual is for Magit-Popup version 2.12.4 (v2.12.4+1). +This manual is for Magit-Popup version 2.13.0. - Copyright (C) 2015-2018 Jonas Bernoulli + Copyright (C) 2015-2019 Jonas Bernoulli You can redistribute this document and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -126,15 +131,9 @@ This should illustrate the most basic differences: '--------' (refresh buffer) - This library was written as a replacement for ‘magit-key-mode’, which -was used in Magit releases before 2.1.0. It is used to implement all -"popups" in the current Magit release but a future release will switch -to yet another implementation. - - This library does not depend on any other Magit libraries and it is -distributed as a separate package, which makes it possible to use it in -packages that are not related to Magit. But keep in mind that it will -be deprecated eventually. + This package has been superseded by Transient (*note +(transient)Top::). No new features will be added but bugs will be +fixes.  File: magit-popup.info, Node: Usage, Next: Defining Prefix and Suffix Commands, Prev: Introduction, Up: Top @@ -728,14 +727,14 @@ directly.  Tag Table: -Node: Top769 -Node: Introduction2004 -Node: Usage4703 -Node: Customizing Existing Popups9400 -Node: Other Options15541 -Node: Defining Prefix and Suffix Commands17084 -Node: Defining Prefix Commands19236 -Node: Defining Suffix Commands27931 +Node: Top770 +Node: Introduction2139 +Node: Usage4478 +Node: Customizing Existing Popups9175 +Node: Other Options15316 +Node: Defining Prefix and Suffix Commands16859 +Node: Defining Prefix Commands19011 +Node: Defining Suffix Commands27706  End Tag Table diff --git a/elpa/magit-popup-readme.txt b/elpa/magit-popup-readme.txt index cf647390..0e0a56f6 100644 --- a/elpa/magit-popup-readme.txt +++ b/elpa/magit-popup-readme.txt @@ -1,14 +1,7 @@ This package implements a generic interface for toggling switches -and setting options and then invoking an Emacs command which does -something with these arguments. The prototypical use is for the -command to call an external process, passing on the arguments as -command line arguments. But this is only one of many possible -uses (though the one this library is optimized for). +and setting options and then invoking an Emacs command that does +something with these arguments. Usually the command calls an +external process with the specified arguments. -With the Emacs concept of "prefix arguments" in mind this could be -described as "infix arguments with feedback in a buffer". - -Commands that set the prefix argument for the subsequent command do -not limit what that next command could be. But entering a command -console popup does limit the selection to the commands defined for -that popup, and so we use the term "infix" instead of "prefix". +This package has been superseded by Transient. No new features +will be added but bugs will be fixes. diff --git a/elpa/magit-readme.txt b/elpa/magit-readme.txt new file mode 100644 index 00000000..52bcc521 --- /dev/null +++ b/elpa/magit-readme.txt @@ -0,0 +1,8 @@ +Magit is an interface to the version control system Git, +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. diff --git a/elpa/magit-todos-20190114.1450/magit-todos-pkg.el b/elpa/magit-todos-20190114.1450/magit-todos-pkg.el deleted file mode 100644 index dfe52493..00000000 --- a/elpa/magit-todos-20190114.1450/magit-todos-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; -*- no-byte-compile: t -*- -(define-package "magit-todos" "20190114.1450" "Show source file TODOs in Magit" '((emacs "25.2") (async "1.9.2") (dash "2.13.0") (f "0.17.2") (hl-todo "1.9.0") (magit "2.13.0") (pcre2el "1.8") (s "1.12.0")) :commit "14e5347c98f42166ad7061b8663d368bb0d4fba4" :keywords '("magit" "vc") :authors '(("Adam Porter" . "adam@alphapapa.net")) :maintainer '("Adam Porter" . "adam@alphapapa.net") :url "http://github.com/alphapapa/magit-todos") diff --git a/elpa/magit-todos-20190114.1450/magit-todos-autoloads.el b/elpa/magit-todos-20190508.757/magit-todos-autoloads.el similarity index 100% rename from elpa/magit-todos-20190114.1450/magit-todos-autoloads.el rename to elpa/magit-todos-20190508.757/magit-todos-autoloads.el diff --git a/elpa/magit-todos-20190508.757/magit-todos-pkg.el b/elpa/magit-todos-20190508.757/magit-todos-pkg.el new file mode 100644 index 00000000..e5dab75b --- /dev/null +++ b/elpa/magit-todos-20190508.757/magit-todos-pkg.el @@ -0,0 +1,2 @@ +;;; -*- no-byte-compile: t -*- +(define-package "magit-todos" "20190508.757" "Show source file TODOs in Magit" '((emacs "25.2") (async "1.9.2") (dash "2.13.0") (f "0.17.2") (hl-todo "1.9.0") (magit "2.13.0") (pcre2el "1.8") (s "1.12.0")) :commit "3c59aa03b217b55b1baa0e88470e10996aaeea9b" :keywords '("magit" "vc") :authors '(("Adam Porter" . "adam@alphapapa.net")) :maintainer '("Adam Porter" . "adam@alphapapa.net") :url "http://github.com/alphapapa/magit-todos") diff --git a/elpa/magit-todos-20190114.1450/magit-todos.el b/elpa/magit-todos-20190508.757/magit-todos.el similarity index 87% rename from elpa/magit-todos-20190114.1450/magit-todos.el rename to elpa/magit-todos-20190508.757/magit-todos.el index 0baf563b..3128e792 100644 --- a/elpa/magit-todos-20190114.1450/magit-todos.el +++ b/elpa/magit-todos-20190508.757/magit-todos.el @@ -4,8 +4,8 @@ ;; Author: Adam Porter ;; URL: http://github.com/alphapapa/magit-todos -;; Package-Version: 20190114.1450 -;; Version: 1.2-pre +;; Package-Version: 20190508.757 +;; Version: 1.3-pre ;; Package-Requires: ((emacs "25.2") (async "1.9.2") (dash "2.13.0") (f "0.17.2") (hl-todo "1.9.0") (magit "2.13.0") (pcre2el "1.8") (s "1.12.0")) ;; Keywords: magit, vc @@ -122,6 +122,7 @@ magit-status buffer.") (let ((map (make-sparse-keymap))) (define-key map "jT" #'magit-todos-jump-to-todos) (define-key map "jl" #'magit-todos-list) + (define-key map "b" #'magit-todos-toggle-branch-list) (define-key map (kbd "RET") #'magit-todos-list) map) "Keymap for `magit-todos' top-level section.") @@ -152,6 +153,9 @@ A time value as returned by `current-time'.") (defvar magit-todos-scanners nil "Scanners defined by `magit-todos-defscanner'.") +(defvar magit-todos-section-heading "TODOs" + "Allows overriding of section heading.") + ;;;; Customization (defgroup magit-todos nil @@ -322,6 +326,17 @@ used." "Glob patterns to exclude from searches." :type '(repeat string)) +(defcustom magit-todos-show-branch-list 'branch + "Show branch diff to-do list. +In the master branch, this shows whatever items are listed by +\"git diff HEAD^\". + +This can be toggled locally in Magit buffers with command +`magit-todos-toggle-branch-list'." + :type '(choice (const :tag "Never" nil) + (const :tag "In non-master branches" branch) + (const :tag "Always" t))) + ;;;; Commands ;;;###autoload @@ -332,16 +347,17 @@ used." :global t (if magit-todos-mode (progn - (if (lookup-key magit-status-mode-map "jT") - (message "magit-todos: Not overriding bind of \"jT\" in `magit-status-mode-map'.") - (define-key magit-status-mode-map "jT" #'magit-todos-jump-to-todos)) + (pcase (lookup-key magit-status-mode-map "jT") + ('nil (define-key magit-status-mode-map "jT" #'magit-todos-jump-to-todos)) + ('magit-todos-jump-to-todos nil) + (_ (message "magit-todos: Not overriding bind of \"jT\" in `magit-status-mode-map'."))) (magit-add-section-hook 'magit-status-sections-hook #'magit-todos--insert-todos 'magit-insert-staged-changes 'append) (add-hook 'magit-status-mode-hook #'magit-todos--add-to-status-buffer-kill-hook 'append)) ;; Disable mode - (when (equal (lookup-key magit-status-mode-map "jT") #'magit-jump-to-todos) + (when (equal (lookup-key magit-status-mode-map "jT") #'magit-todos-jump-to-todos) (define-key magit-status-mode-map "jT" nil)) (remove-hook 'magit-status-sections-hook #'magit-todos--insert-todos) (remove-hook 'magit-status-mode-hook #'magit-todos--add-to-status-buffer-kill-hook))) @@ -353,11 +369,19 @@ Only necessary when option `magit-todos-update' is nil." (unless magit-todos-mode (user-error "Please activate `magit-todos-mode'")) (let ((inhibit-read-only t)) + ;; Delete twice since there might also be the branch-local section. + (magit-todos--delete-section [* todos]) (magit-todos--delete-section [* todos]) ;; HACK: See other note on `magit-todos-updating'. (setq magit-todos-updating t) (magit-todos--insert-todos))) +(defun magit-todos-toggle-branch-list () + "Toggle branch diff to-do list in current Magit buffer." + (interactive) + (setq-local magit-todos-show-branch-list (not magit-todos-show-branch-list)) + (magit-todos-update)) + (defun magit-todos-jump-to-item (&optional peek) "Show current item. If PEEK is non-nil, keep focus in status buffer window." @@ -482,7 +506,7 @@ Chooses automatically in order defined in `magit-todos-scanners'." when (eval (alist-get 'test scanner)) return (alist-get 'function scanner))) -(defun magit-todos--scan-callback (magit-status-buffer results-regexp process) +(cl-defun magit-todos--scan-callback (&key magit-status-buffer results-regexp process &allow-other-keys) "Callback for `magit-todos--git-grep-scan-async'." ;; SOMEDAY: Perhaps move process buffer parsing into separate function. (with-current-buffer (process-buffer process) @@ -493,6 +517,52 @@ Chooses automatically in order defined in `magit-todos-scanners'." collect item do (forward-line 1))))) +(cl-defun magit-todos--git-diff-callback (&key magit-status-buffer results-regexp search-regexp-elisp process heading + &allow-other-keys) + "Callback for git diff scanner output." + ;; NOTE: Doesn't handle newlines in filenames or diff.mnemonicPrefix. + (cl-macrolet ((next-diff () `(re-search-forward (rx bol "diff --git ") nil t)) + (next-filename () `(when (re-search-forward (rx bol "+++ b/" (group (1+ nonl))) nil t) + (match-string 1))) + (next-hunk-line-number () `(when (re-search-forward (rx bol "@@ -" + (1+ digit) (optional "," (1+ digit)) (1+ space) + "+" (group (1+ digit)) (optional "," (1+ digit))) + file-end t) + (string-to-number (match-string 1)))) + (file-end () `(or (save-excursion + (when (re-search-forward (rx bol "diff --git ") + nil t) + (match-beginning 0))) + (point-max))) + (hunk-end () `(or (save-excursion + (when (re-search-forward (rx (or (seq bol "diff --git ") + (seq bol "@@ "))) + nil t) + (match-beginning 0))) + (point-max)))) + (with-current-buffer (process-buffer process) + (goto-char (point-min)) + (let (items filename file-end hunk-end line-number) + (while (next-diff) + (while (setf filename (next-filename)) + (setf file-end (file-end)) + (while (setf line-number (next-hunk-line-number)) + (setf hunk-end (hunk-end)) + (while (re-search-forward (rx bol "+") hunk-end t) + ;; Since "git diff-index" doesn't accept PCREs to its "-G" option, we have to test the search regexp ourselves. + (when (re-search-forward search-regexp-elisp (line-end-position) t) + (when-let* ((line (buffer-substring (line-beginning-position) (line-end-position))) + (item (with-temp-buffer + ;; NOTE: We fake grep output by inserting the filename, line number, position, etc. + ;; This lets us use the same results regexp that's used for grep-like output. + (save-excursion + (insert filename ":" (number-to-string line-number) ":0: " line)) + (magit-todos--line-item results-regexp filename)))) + (push item items))) + (cl-incf line-number))))) + (let ((magit-todos-section-heading heading)) + (magit-todos--insert-items magit-status-buffer items)))))) + (defun magit-todos--delete-section (condition) "Delete the section specified by CONDITION from the Magit status buffer. See `magit-section-match'. Also delete it from root section's children." @@ -562,13 +632,22 @@ This function should be called from inside a ‘magit-status’ buffer." :magit-status-buffer (current-buffer) :directory default-directory :depth magit-todos-depth))) - (_ ; Caching and cache not expired, or not automatic and not manually updating now - (magit-todos--insert-items (current-buffer) magit-todos-item-cache)))) + (_ ; Caching and cache not expired, or not automatic and not manually updating now + (magit-todos--insert-items (current-buffer) magit-todos-item-cache))) + (when (or (eq magit-todos-show-branch-list t) + (and (eq magit-todos-show-branch-list 'branch) + (not (string= "master" (magit-get-current-branch))))) + ;; Insert branch-local items. + (magit-todos--scan-with-git-diff :magit-status-buffer (current-buffer) + :directory default-directory + :depth magit-todos-depth + :heading "TODOs (branch)"))) (defun magit-todos--insert-items (magit-status-buffer items) "Insert to-do ITEMS into MAGIT-STATUS-BUFFER." (declare (indent defun)) ;; NOTE: This could be factored out into some kind of `magit-insert-section-async' macro if necessary. + ;; MAYBE: Use `magit-insert-section-body'. (when (not (buffer-live-p magit-status-buffer)) (message "`magit-todos--insert-items-callback': Callback called for deleted buffer")) (let* ((items (magit-todos--sort items)) @@ -615,12 +694,11 @@ This function should be called from inside a ‘magit-status’ buffer." ;; Manual updates: Insert section to remind user (let ((magit-insert-section--parent magit-root-section)) (magit-insert-section (todos) - (magit-insert-heading (concat (propertize "TODOs" 'face 'magit-section-heading) - " (0)" reminder))) - (insert "\n"))) + (magit-insert-heading (concat (propertize magit-todos-section-heading 'face 'magit-section-heading) + " (0)" reminder "\n"))))) (let ((section (magit-todos--insert-groups :type 'todos :heading (format "%s (%s)%s" - (propertize "TODOs" 'face 'magit-section-heading) + (propertize magit-todos-section-heading 'face 'magit-section-heading) num-items reminder) :group-fns group-fns :items items @@ -728,8 +806,7 @@ sections." item)) (truncate-string-to-width it width)))) (magit-insert-section (todos-item item) - (insert string)) - (insert "\n")))))) + (insert string "\n"))))))) (magit-todos--set-visibility :depth depth :num-items (length items) :section section) ;; Don't forget to return the section! section)) @@ -946,7 +1023,8 @@ if the process's buffer has already been deleted." ;;;; Scanners -(cl-defmacro magit-todos-defscanner (name &key test command results-regexp) +(cl-defmacro magit-todos-defscanner (name &key test command results-regexp + (callback (function 'magit-todos--scan-callback))) "Define a `magit-todos' scanner named NAME. NAME is a string, which may contain spaces. It is only used for @@ -975,8 +1053,11 @@ be passed to the scanner's max-depth option (i.e. `magit-todos-depth'). `keywords': List of item keywords defined in `magit-todos-keywords-list'. -`search-regexp': The regular expression to be passed to the -scanner. +`search-regexp-pcre': PCRE-compatible regular expression to be passed +to the scanner process. + +`search-regexp-elisp': Emacs regular expression, which may be +used for scanners written as Emacs Lisp functions. RESULTS-REGEXP is an optional string or unquoted sexp which is used to match results in the scanner process's output buffer. @@ -991,6 +1072,11 @@ appropriate. Custom regexps may also match column numbers or byte offsets in the appropriate numbered groups; see `make-magit-todos-item'. +CALLBACK is a function which is called to parse the scanner +process's buffer. For grep-like scanners that output results in +a format suitable for RESULTS-REGEXP, the default callback, +`magit-todos--scan-callback', should be used. + The macro defines the following: \"magit-todos-NAME-extra-args\": A customization setting, a list @@ -1017,31 +1103,31 @@ It also adds the scanner to the customization variable (defcustom ,extra-args-var nil ,(format "Extra arguments passed to %s." name) :type '(repeat string)) - (cl-defun ,scan-fn-symbol (&key magit-status-buffer directory depth) - ,(format "Scan for to-dos with %s, then call `magit-todos--scan-callback'. -MAGIT-STATUS-BUFFER is what it says. DIRECTORY is the directory in which to run the scan. DEPTH should be an integer, typically the value of `magit-todos-depth'." - name) + (cl-defun ,scan-fn-symbol (&key magit-status-buffer directory depth heading) + ,(format "Scan for to-dos with %s, then call `%s'. +MAGIT-STATUS-BUFFER is what it says. DIRECTORY is the directory in which to run the scan. DEPTH should be an integer, typically the value of `magit-todos-depth'. HEADING is passed to `%s'." + name callback callback) (let* ((process-connection-type 'pipe) (directory (f-relative directory default-directory)) (extra-args (when ,extra-args-var (--map (s-split (rx (1+ space)) it 'omit-nulls) ,extra-args-var))) (keywords magit-todos-keywords-list) - (search-regexp (rxt-elisp-to-pcre - (rx-to-string - `(or - ;; Org item - (seq bol (group (1+ "*")) - (1+ blank) - (group (or ,@keywords)) - (1+ space) - (group (1+ not-newline))) - ;; Non-Org - (seq (or bol (1+ blank)) - (group (or ,@keywords)) - (regexp ,magit-todos-keyword-suffix) - (optional (1+ blank) - (group (1+ not-newline)))))))) + (search-regexp-elisp (rx-to-string + `(or + ;; Org item + (seq bol (group (1+ "*")) + (1+ blank) + (group (or ,@keywords)) + (1+ space) + (group (1+ not-newline))) + ;; Non-Org + (seq (or bol (1+ blank)) + (group (or ,@keywords)) + (regexp ,magit-todos-keyword-suffix) + (optional (1+ blank) + (group (1+ not-newline))))))) + (search-regexp-pcre (rxt-elisp-to-pcre search-regexp-elisp)) (results-regexp (or ,results-regexp (rx-to-string `(seq bol @@ -1073,7 +1159,11 @@ MAGIT-STATUS-BUFFER is what it says. DIRECTORY is the directory in which to run do (setf elt (number-to-string elt))) (magit-todos--async-start-process ,scan-fn-name :command command - :finish-func (apply-partially #'magit-todos--scan-callback magit-status-buffer results-regexp)))) + :finish-func (apply-partially ,callback + :magit-status-buffer magit-status-buffer :results-regexp results-regexp + :search-regexp-elisp search-regexp-elisp + :heading heading + :process)))) ; Process is appended to the list. (magit-todos--add-to-custom-type 'magit-todos-scanner (list 'const :tag ,name #',scan-fn-symbol)) (add-to-list 'magit-todos-scanners @@ -1101,7 +1191,7 @@ MAGIT-STATUS-BUFFER is what it says. DIRECTORY is the directory in which to run (when magit-todos-exclude-globs (--map (list "--glob" (concat "!" it)) magit-todos-exclude-globs)) - extra-args search-regexp directory)) + extra-args search-regexp-pcre directory)) (magit-todos-defscanner "git grep" :test (string-match "--perl-regexp" (shell-command-to-string "git grep --help")) @@ -1112,12 +1202,19 @@ MAGIT-STATUS-BUFFER is what it says. DIRECTORY is the directory in which to run (when magit-todos-ignore-case "--ignore-case") "--perl-regexp" - "-e" search-regexp + "-e" search-regexp-pcre extra-args "--" directory (when magit-todos-exclude-globs (--map (concat ":!" it) magit-todos-exclude-globs)))) +(magit-todos-defscanner "git diff" + ;; NOTE: This scanner implements the regexp *searching* in elisp rather than in the + ;; external process because, unlike "git grep", "git diff" does not support PCRE. + :test t + :command (list "git" "--no-pager" "diff" "--no-color" "-U0" "HEAD^") + :callback #'magit-todos--git-diff-callback) + (magit-todos-defscanner "find|grep" ;; NOTE: The filenames output by find|grep have a leading "./". I don't expect this scanner to be ;; used much, if at all, so I'm not going to go to the trouble to fix this now. @@ -1175,7 +1272,7 @@ MAGIT-STATUS-BUFFER is what it says. DIRECTORY is the directory in which to run (when magit-todos-ignore-case "--ignore-case") extra-args - search-regexp "{}" "+")))) + search-regexp-pcre "{}" "+")))) ;;;;; Set scanner default value -- 2.47.3