From 2c0373c35259b55f7e4c04247214d1aeba69df29 Mon Sep 17 00:00:00 2001 From: 10sr <8.slashes@gmail.com> Date: Tue, 16 Oct 2018 17:59:59 +0900 Subject: [PATCH] Implement -parent-revision --- emacs.el | 95 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 25 deletions(-) diff --git a/emacs.el b/emacs.el index 5e81167..6a41ce2 100644 --- a/emacs.el +++ b/emacs.el @@ -1,6 +1,6 @@ ;;; emacs.el --- 10sr emacs initialization -;; Time-stamp: <2018-10-16 15:25:14 JST 10sr> +;; Time-stamp: <2018-10-16 17:54:31 JST 10sr> ;;; Code: @@ -2462,14 +2462,22 @@ without checking it." (error "Type cannot handle: %s" type))))) (defun git-walktree--resolve-object (commitish path) - "Return object id of COMMITISIH:PATH." + "Return object id of COMMITISIH:PATH. +If path is equal to \".\" return COMMITISH's tree object" ;; TODO: use --full-tree - (with-temp-buffer - (cd (git-walktree--git-plumbing "rev-parse" "--show-toplevel")) - (let ((info (git-walktree--parse-lstree-line (git-walktree--git-plumbing "ls-tree" - commitish - path)))) - (plist-get info :object)))) + (cl-assert commitish) + (cl-assert path) + (if (string= path ".") + (git-walktree--git-plumbing "show" + "--no-patch" + "--pretty=format:%T" + commitish) + (with-temp-buffer + (cd (git-walktree--git-plumbing "rev-parse" "--show-toplevel")) + (let ((info (git-walktree--parse-lstree-line (git-walktree--git-plumbing "ls-tree" + commitish + path)))) + (plist-get info :object))))) (defun git-walktree-open (commitish &optional path object) "Open git tree buffer of COMMITISH. @@ -2650,29 +2658,66 @@ This function do nothing when current line is not ls-tree output." "Face used for tree objects.") (defvar git-walktree-known-child-revisions '() - "List of already known child reivions of currnet buffer in string format.") + "List of already known child reivions of currnet buffer in sha1 string.") (make-variable-buffer-local 'git-walktree-known-child-revisions) +(defun git-walktree--parent-revision-1 (revision) + "Open parent revision REVISION. + +This function does the following things: + +- Check if current path exists in REVISION. If not, go up until path was found. +- Create buffer for REVISION and path found. +- Add revision sha1 of source buffer to created buffer's + `git-wwalktree-known-child-revisions'. +- Switch to new buffer." + (let* ((child-revision git-walktree-current-commitish) + (path git-walktree-current-path) + (obj (git-walktree--resolve-object revision path))) + (cl-assert path) + (while (not obj) + (setq path + (git-walktree--parent-directory path)) + (setq obj + (git-walktree--resolve-object revision path))) + (with-current-buffer (switch-to-buffer (git-walktree--open-noselect revision + path + obj)) + (add-to-list 'git-walktree-known-child-revisions + child-revision)))) + (defun git-walktree-parent-revision () "Open parent revision of current path. -If given path is not found in the parent revision try to go up path." - (interactive)) - -(defun git-walktree--is-a-merge-commit (commitish) - "Return non-nil if COMMITISH is a merge commit." +If current path was not found in the parent revision try to go up path." + (interactive) + (if git-walktree-current-commitish + (let ((parents (git-walktree--parent-sha1 git-walktree-current-commitish))) + (cl-case (length parents) + (0 + (message "This revision has no parent revision")) + (1 + (git-walktree--parent-revision-1 (car parents))) + (t + (let ((parent (completing-read "This revision has multiple parents. Which to open? (default is the left one): " + parents + nil + t + (car parents)))) + (git-walktree--parent-revision-1 parent))))))) + +(defun git-walktree--parent-sha1 (commitish) + "Return list of parent commits of COMMITISH in sha1 string." (let ((type (git-walktree--git-plumbing "cat-file" "-t" commitish))) (cl-assert (string= type "commit"))) - (let* ((parents (git-walktree--git-plumbing "show" - "--no-patch" - "--pretty=format:%P" - commitish)) - (num (length (split-string parents)))) - (and (> num 1) - num))) -;; (git-walktree--is-a-merge-commit "HEAD") -;; (git-walktree--is-a-merge-commit "ae4b80f") + (let ((parents (git-walktree--git-plumbing "show" + "--no-patch" + "--pretty=format:%P" + commitish))) + (split-string parents))) +;; (git-walktree--parent-sha1 "HEAD") +;; (git-walktree--parent-sha1 "ae4b80f") (defvar git-walktree-mode-map (let ((map (make-sparse-keymap))) @@ -2681,8 +2726,8 @@ If given path is not found in the parent revision try to go up path." (define-key map (kbd "C-n") 'git-walktree-mode-next-line) (define-key map (kbd "C-p") 'git-walktree-mode-previous-line) ;; TODO: Review keybind - (define-key map "N" 'git-walktree-parent-revision) - (define-key map "P" 'git-walktree-known-child-revision) + (define-key map "P" 'git-walktree-parent-revision) + (define-key map "N" 'git-walktree-known-child-revision) (define-key map "^" 'git-walktree-up) (define-key map (kbd "C-m") 'git-walktree-mode-open-this) map))