about summary refs log tree commit diff
path: root/configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-wip.el
diff options
context:
space:
mode:
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-wip.el')
-rw-r--r--configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-wip.el370
1 files changed, 370 insertions, 0 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-wip.el b/configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-wip.el
new file mode 100644
index 000000000000..0bb7efc5b7cb
--- /dev/null
+++ b/configs/shared/emacs/.emacs.d/elpa/magit-20180913.1247/magit-wip.el
@@ -0,0 +1,370 @@
+;;; magit-wip.el --- commit snapshots to work-in-progress refs  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2010-2018  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 <jonas@bernoul.li>
+;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
+
+;; 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 tree global modes which automatically commit
+;; snapshots to branch-specific work-in-progress refs before and after
+;; making changes, and two commands which can be used to do so on
+;; demand.
+
+;;; Code:
+
+(require 'magit-core)
+(require 'magit-log)
+
+;;; Options
+
+(defgroup magit-wip nil
+  "Automatically commit to work-in-progress refs."
+  :link '(info-link "(magit)Wip Modes")
+  :group 'magit-modes
+  :group 'magit-essentials)
+
+(defcustom magit-wip-after-save-local-mode-lighter " sWip"
+  "Lighter for Magit-Wip-After-Save-Local mode."
+  :package-version '(magit . "2.1.0")
+  :group 'magit-wip
+  :type 'string)
+
+(defcustom magit-wip-after-apply-mode-lighter " aWip"
+  "Lighter for Magit-Wip-After-Apply mode."
+  :package-version '(magit . "2.1.0")
+  :group 'magit-wip
+  :type 'string)
+
+(defcustom magit-wip-before-change-mode-lighter " cWip"
+  "Lighter for Magit-Wip-Before-Change mode."
+  :package-version '(magit . "2.1.0")
+  :group 'magit-wip
+  :type 'string)
+
+(defcustom magit-wip-merge-branch nil
+  "Whether to merge the current branch into its wip ref.
+
+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."
+  :package-version '(magit . "2.90.0")
+  :group 'magit-wip
+  :type 'boolean)
+
+(defcustom magit-wip-namespace "refs/wip/"
+  "Namespace used for work-in-progress refs.
+The wip refs are named \"<namespace/>index/<branchref>\"
+and \"<namespace/>wtree/<branchref>\".  When snapshots
+are created while the `HEAD' is detached then \"HEAD\"
+is used as `branch-ref'."
+  :package-version '(magit . "2.1.0")
+  :group 'magit-wip
+  :type 'string)
+
+;;; Modes
+
+(define-minor-mode magit-wip-after-save-local-mode
+  "After saving, also commit to a worktree work-in-progress ref.
+
+After saving the current file-visiting buffer this mode also
+commits the changes to the worktree work-in-progress ref for
+the current branch.
+
+This mode should be enabled globally by turning on the globalized
+variant `magit-wip-after-save-mode'."
+  :package-version '(magit . "2.1.0")
+  :lighter magit-wip-after-save-local-mode-lighter
+  (if magit-wip-after-save-local-mode
+      (if (and buffer-file-name (magit-inside-worktree-p t))
+          (add-hook 'after-save-hook 'magit-wip-commit-buffer-file t t)
+        (setq magit-wip-after-save-local-mode nil)
+        (user-error "Need a worktree and a file"))
+    (remove-hook 'after-save-hook 'magit-wip-commit-buffer-file t)))
+
+(defun magit-wip-after-save-local-mode-turn-on ()
+  (and buffer-file-name
+       (magit-inside-worktree-p t)
+       (magit-file-tracked-p buffer-file-name)
+       (magit-wip-after-save-local-mode)))
+
+;;;###autoload
+(define-globalized-minor-mode magit-wip-after-save-mode
+  magit-wip-after-save-local-mode magit-wip-after-save-local-mode-turn-on
+  :package-version '(magit . "2.1.0")
+  :group 'magit-wip)
+
+(defun magit-wip-commit-buffer-file (&optional msg)
+  "Commit visited file to a worktree work-in-progress ref.
+
+Also see `magit-wip-after-save-mode' which calls this function
+automatically whenever a buffer visiting a tracked file is saved."
+  (interactive)
+  (--when-let (magit-wip-get-ref)
+    (magit-with-toplevel
+      (let ((file (file-relative-name buffer-file-name)))
+        (magit-wip-commit-worktree
+         it (list file)
+         (format (cond (msg)
+                       ((called-interactively-p 'any)
+                        "wip-save %s after save")
+                       (t
+                        "autosave %s after save"))
+                 file))))))
+
+;;;###autoload
+(define-minor-mode magit-wip-after-apply-mode
+  "Commit to work-in-progress refs.
+
+After applying a change using any \"apply variant\"
+command (apply, stage, unstage, discard, and reverse) commit the
+affected files to the current wip refs.  For each branch there
+may be two wip refs; one contains snapshots of the files as found
+in the worktree and the other contains snapshots of the entries
+in the index."
+  :package-version '(magit . "2.1.0")
+  :group 'magit-wip
+  :lighter magit-wip-after-apply-mode-lighter
+  :global t)
+
+(defun magit-wip-commit-after-apply (&optional files msg)
+  (when magit-wip-after-apply-mode
+    (magit-wip-commit files msg)))
+
+;;;###autoload
+(define-minor-mode magit-wip-before-change-mode
+  "Commit to work-in-progress refs before certain destructive changes.
+
+Before invoking a revert command or an \"apply variant\"
+command (apply, stage, unstage, discard, and reverse) commit the
+affected tracked files to the current wip refs.  For each branch
+there may be two wip refs; one contains snapshots of the files
+as found in the worktree and the other contains snapshots of the
+entries in the index.
+
+Only changes to files which could potentially be affected by the
+command which is about to be called are committed."
+  :package-version '(magit . "2.1.0")
+  :group 'magit-wip
+  :lighter magit-wip-before-change-mode-lighter
+  :global t)
+
+(defun magit-wip-commit-before-change (&optional files msg)
+  (when magit-wip-before-change-mode
+    (magit-with-toplevel
+      (magit-wip-commit files msg))))
+
+;;; Extras
+
+(defvar-local magit-wip-buffer-backed-up nil)
+(put 'magit-wip-buffer-backed-up 'permanent-local t)
+
+;;;###autoload
+(defun magit-wip-commit-initial-backup ()
+  "Before saving, commit current file to a worktree wip ref.
+
+The user has to add this function to `before-save-hook'.
+
+Commit the current state of the visited file before saving the
+current buffer to that file.  This backs up the same version of
+the file as `backup-buffer' would, but stores the backup in the
+worktree wip ref, which is also used by the various Magit Wip
+modes, instead of in a backup file as `backup-buffer' would.
+
+This function ignores the variables that affect `backup-buffer'
+and can be used along-side that function, which is recommended
+because this function only backs up files that are tracked in
+a Git repository."
+  (when (and (not magit-wip-buffer-backed-up)
+             buffer-file-name
+             (magit-inside-worktree-p t)
+             (magit-file-tracked-p buffer-file-name))
+    (let ((magit-save-repository-buffers nil))
+      (magit-wip-commit-buffer-file "autosave %s before save"))
+    (setq magit-wip-buffer-backed-up t)))
+
+;;; Core
+
+(defun magit-wip-commit (&optional files msg)
+  "Commit all tracked files to the work-in-progress refs.
+
+Interactively, commit all changes to all tracked files using
+a generic commit message.  With a prefix-argument the commit
+message is read in the minibuffer.
+
+Non-interactively, only commit changes to FILES using MSG as
+commit message."
+  (interactive (list nil (if current-prefix-arg
+                             (magit-read-string "Wip commit message")
+                           "wip-save tracked files")))
+  (--when-let (magit-wip-get-ref)
+    (magit-wip-commit-index it files msg)
+    (magit-wip-commit-worktree it files msg)))
+
+(defun magit-wip-commit-index (ref files msg)
+  (let* ((wipref (magit--wip-index-ref ref))
+         (parent (magit-wip-get-parent ref wipref))
+         (tree   (magit-git-string "write-tree")))
+    (magit-wip-update-wipref ref wipref tree parent files msg "index")))
+
+(defun magit-wip-commit-worktree (ref files msg)
+  (let* ((wipref (magit--wip-wtree-ref ref))
+         (parent (magit-wip-get-parent ref wipref))
+         (tree (magit-with-temp-index parent "--reset"
+                 (if files
+                     (magit-call-git "add" "--" files)
+                   (magit-with-toplevel
+                     (magit-call-git "add" "-u" ".")))
+                 (magit-git-string "write-tree"))))
+    (magit-wip-update-wipref ref wipref tree parent files msg "worktree")))
+
+(defun magit-wip-update-wipref (ref wipref tree parent files msg start-msg)
+  (cond
+   ((and (not (equal parent wipref))
+         (or (not magit-wip-merge-branch)
+             (not (magit-rev-verify wipref))))
+    (setq start-msg (concat "start autosaving " start-msg))
+    (magit-update-ref wipref start-msg
+                      (magit-git-string "commit-tree" "--no-gpg-sign"
+                                        "-p" parent "-m" start-msg
+                                        (concat parent "^{tree}")))
+    (setq parent wipref))
+   ((and magit-wip-merge-branch
+         (or (not (magit-rev-ancestor-p ref wipref))
+             (not (magit-rev-ancestor-p
+                   (concat (magit-git-string "log" "--format=%H"
+                                             "-1" "--merges" wipref)
+                           "^2")
+                   ref))))
+    (setq start-msg (format "merge %s into %s" ref start-msg))
+    (magit-update-ref wipref start-msg
+                      (magit-git-string "commit-tree" "--no-gpg-sign"
+                                        "-p" wipref "-p" ref
+                                        "-m" start-msg
+                                        (concat ref "^{tree}")))
+    (setq parent wipref)))
+  (when (magit-git-failure "diff-tree" "--quiet" parent tree "--" files)
+    (unless (and msg (not (= (aref msg 0) ?\s)))
+      (let ((len (length files)))
+        (setq msg (concat
+                   (cond ((= len 0) "autosave tracked files")
+                         ((> len 1) (format "autosave %s files" len))
+                         (t (concat "autosave "
+                                    (file-relative-name (car files)
+                                                        (magit-toplevel)))))
+                   msg))))
+    (magit-update-ref wipref msg
+                      (magit-git-string "commit-tree" "--no-gpg-sign"
+                                        "-p" parent "-m" msg tree))))
+
+(defun magit-wip-get-ref ()
+  (let ((ref (or (magit-git-string "symbolic-ref" "HEAD") "HEAD")))
+    (and (magit-rev-verify ref)
+         ref)))
+
+(defun magit-wip-get-parent (ref wipref)
+  (if (and (magit-rev-verify wipref)
+           (equal (magit-git-string "merge-base" wipref ref)
+                  (magit-rev-verify ref)))
+      wipref
+    ref))
+
+(defun magit--wip-index-ref (&optional ref)
+  (magit--wip-ref "index/" ref))
+
+(defun magit--wip-wtree-ref (&optional ref)
+  (magit--wip-ref "wtree/" ref))
+
+(defun magit--wip-ref (namespace &optional ref)
+  (concat magit-wip-namespace namespace
+          (or (and ref (string-prefix-p "refs/" ref) ref)
+              (when-let ((branch (or ref (magit-get-current-branch))))
+                (concat "refs/heads/" branch))
+              "HEAD")))
+
+;;; Log
+
+(defun magit-wip-log-index (args files)
+  "Show log for the index wip ref of the current branch."
+  (interactive (magit-log-arguments))
+  (magit-log (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-log (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.
+With a negative prefix argument only show the worktree wip ref.
+The absolute numeric value of the prefix argument controls how
+many \"branches\" of each wip ref are shown."
+  (interactive
+   (nconc (list (or (magit-get-current-branch) "HEAD"))
+          (magit-log-arguments)
+          (list (prefix-numeric-value current-prefix-arg))))
+  (magit-wip-log branch args files count))
+
+(defun magit-wip-log (branch args files count)
+  "Show log for a branch and its wip refs.
+With a negative prefix argument only show the worktree wip ref.
+The absolute numeric value of the prefix argument controls how
+many \"branches\" of each wip ref are shown."
+  (interactive
+   (nconc (list (magit-completing-read
+                 "Log branch and its wip refs"
+                 (-snoc (magit-list-local-branch-names) "HEAD")
+                 nil t nil 'magit-revision-history
+                 (or (magit-branch-at-point)
+                     (magit-get-current-branch)
+                     "HEAD")))
+          (magit-log-arguments)
+          (list (prefix-numeric-value current-prefix-arg))))
+  (magit-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))
+
+(defun magit-wip-log-get-tips (wipref count)
+  (when-let ((reflog (magit-git-lines "reflog" wipref)))
+    (let (tips)
+      (while (and reflog (> count 1))
+        (setq reflog (cl-member "^[^ ]+ [^:]+: restart autosaving"
+                                reflog :test #'string-match-p))
+        (when (and (cadr reflog)
+                   (string-match "^[^ ]+ \\([^:]+\\)" (cadr reflog)))
+          (push (match-string 1 (cadr reflog)) tips))
+        (setq reflog (cddr reflog))
+        (cl-decf count))
+      (cons wipref (nreverse tips)))))
+
+(provide 'magit-wip)
+;;; magit-wip.el ends here