From 96f48ebd97c19384f487c8a9c4cf474705ce1e37 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Tue, 24 Apr 2012 23:19:57 +0200 Subject: emacs.d/lisp/magit: version bump --- emacs.d/lisp/magit/magit-bisect.el | 196 +++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 emacs.d/lisp/magit/magit-bisect.el (limited to 'emacs.d/lisp/magit/magit-bisect.el') diff --git a/emacs.d/lisp/magit/magit-bisect.el b/emacs.d/lisp/magit/magit-bisect.el new file mode 100644 index 0000000..fbbfa95 --- /dev/null +++ b/emacs.d/lisp/magit/magit-bisect.el @@ -0,0 +1,196 @@ +(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-get-top-dir default-directory) + ".git/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)) + (chmod 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) -- cgit v1.2.3