commit - 43c93a89a7024d8b8556207cd1404c6b563249e8
commit + 6b6c8a7882362c36787a7522e0b0cecc463f6e3d
blob - 68acf98232b6d7e8aaef75c327e3280e38f8d46b
blob + b1e208b6d15542a4a4be80b779f8281785a743c2
--- Makefile
+++ Makefile
EMACS = emacs
-compile: vc-got.elc
+compile: vc-got.elc vc-got-stage.elc
clean:
rm -f *.elc
blob - 3a035360e11b5efb8001874a0012799e0abf45b2
blob + 32a11f72a6c4ea4dee043dc99a9a350e5785d8cb
--- vc-got.el
+++ vc-got.el
(require 'seq)
(require 'vc)
(require 'vc-annotate)
+
+(require 'vc-got-stage)
(defgroup vc-got nil
"VC GoT backend."
(apply #'vc-got--call "diff"
(append (vc-switches 'got 'diff)
(mapcar #'file-relative-name args))))
+
+(defun vc-got--unstage (file-or-directory)
+ "Unstage all the staged hunks at or within FILE-OR-DIRECTORY.
+If it's nil, unstage every staged changes across the entire work
+tree."
+ (vc-got--call "unstage" file-or-directory))
(defun vc-got--remove (file &optional force keep-local)
"Internal helper to removing FILE from got."
blob - /dev/null
blob + baf0e43679ec4f8185715c304432836c0872e230 (mode 644)
--- /dev/null
+++ vc-got-stage.el
+;;; vc-got-stage.el --- Stage functionalities for vc-got -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Omar Polo
+
+;; Author: Omar Polo <op@omarpolo.com>
+;; Keywords: vc
+
+;; This program 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 of the License, or
+;; (at your option) any later version.
+
+;; This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Stage-related functions for vc-got. This allows vc-got to stage
+;; and commit individual chunks and not entire filesets.
+
+;;; Code:
+
+(require 'vc)
+
+(defvar vc-got-program) ;vc-got.el
+(declare-function vc-got--diff "vc-got")
+(declare-function vc-got--unstage "vc-got" (file))
+
+(defvar vc-got-stage--process nil
+ "The got stage process.")
+
+(defvar vc-got-stage--fileset nil
+ "Remaining fileset to process.")
+
+(defun vc-got-stage--assert-proc ()
+ "Assert no vc-got-stage process is running."
+ (when (process-live-p vc-got-stage--process)
+ (error "A vc-got-stage-files is already in progress")))
+
+(defun vc-got-stage-files (fileset)
+ "Interactively stage hunks from files in FILESET."
+ (interactive (list (cadr (vc-deduce-fileset))))
+ (vc-got-stage--assert-proc)
+ (if (not fileset)
+ (message "[vc-got] nothing to stage.")
+ (setq vc-got-stage--fileset fileset)
+ (vc-got-stage--next)))
+
+(defun vc-got-stage--next ()
+ "Process next file in stage list."
+ (vc-got-stage--assert-proc)
+ (let ((file (car vc-got-stage--fileset)))
+ (if (not file)
+ (progn (kill-buffer (process-buffer vc-got-stage--process))
+ (message "[vc-got] stage done."))
+ (setq vc-got-stage--fileset (cdr vc-got-stage--fileset))
+ (let ((buf (get-buffer-create "*vc-got-stage*")))
+ (pop-to-buffer buf)
+ (with-current-buffer buf
+ (buffer-disable-undo)
+ (erase-buffer)
+ (read-only-mode)
+ (unless (derived-mode-p 'diff-mode)
+ (diff-mode)))
+ (setq vc-got-stage--process
+ (make-process :name "got"
+ :buffer buf
+ :command (list vc-got-program "stage" "-p" file)
+ :connection 'pty
+ :filter #'vc-got-stage--filter
+ :sentinel #'vc-got-stage--sentinel))))))
+
+(defun vc-got-stage--filter (proc string)
+ "Filter for got stage process.
+PROC is the process, STRING part of its output."
+ (let ((buf (process-buffer proc)))
+ (when (buffer-live-p buf)
+ (let ((inhibit-read-only t))
+ (with-current-buffer buf
+ (goto-char (point-max))
+ (insert string)
+ (save-excursion
+ (beginning-of-line)
+ (let ((msg (cond ((looking-at "^stage this change?")
+ "Stage this change? ")
+ ((looking-at "^stage this addition?")
+ "Stage this addition? "))))
+ (when msg
+ (kill-line)
+ (process-send-string buf (if (y-or-n-p msg) "y\n" "n\n"))
+ (erase-buffer)))))))))
+
+(defun vc-got-stage--sentinel (_proc event)
+ "Sentinel for got stage process.
+Should be only called when EVENT is finished."
+ (when (string= event "finished\n")
+ (vc-got-stage--next)))
+
+;; TODO: make this interactive just as stage is
+(defun vc-got-stage-unstage (fileset)
+ "Unstage staged hunks in FILESET."
+ (interactive (list (cadr (vc-deduce-fileset))))
+ (vc-got-stage--assert-proc)
+ (if fileset
+ (dolist (file fileset)
+ (vc-got--unstage file))
+ (vc-got--unstage nil)))
+
+(defun vc-got-stage-diff (fileset)
+ "Pop a buffer with the staged diff for FILESET.
+If FILESET is nil, show the diff for every staged hunks."
+ (interactive (list (cadr (vc-deduce-fileset))))
+ (with-current-buffer (get-buffer-create "*vc-diff*")
+ (pop-to-buffer (current-buffer))
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (diff-mode)
+ (if fileset
+ (dolist (file fileset)
+ (vc-got--diff "-s" file))
+ (vc-got--diff "-s")))))
+
+(provide 'vc-got-stage)
+;;; vc-got-stage.el ends here