:group 'stgit
:link '(variable-link stgit-show-ignored))
+(defcustom stgit-default-show-svn t
+ "Set to non-nil to by default show subversion information in a
+new stgit buffer.
+
+Use \\<stgit-mode-map>\\[stgit-toggle-svn] to toggle this \
+setting in an already-started StGit buffer."
+ :type 'boolean
+ :group 'stgit
+ :link '(variable-link stgit-show-worktree))
+
(defcustom stgit-find-copies-harder nil
"Try harder to find copied files when listing patches.
(error "Bad element in stgit-make-run-args args: %S" x))))
args))
-(defun stgit-run-silent (&rest args)
- (setq args (stgit-make-run-args args))
- (apply 'call-process "stg" nil standard-output nil args))
+(defvar stgit-inhibit-messages nil
+ "Set to non-nil to inhibit messages when running `stg' commands.
+See also `stgit-message'.")
+(defun stgit-message (format-spec &rest args)
+ "Call `message' on the arguments unless `stgit-inhibit-messages' is non-nil."
+ (unless stgit-inhibit-messages
+ (apply 'message format-spec args)))
(defun stgit-run (&rest args)
(setq args (stgit-make-run-args args))
(let ((msgcmd (mapconcat #'identity args " ")))
- (message "Running stg %s..." msgcmd)
- (apply 'call-process "stg" nil standard-output nil args)
- (message "Running stg %s...done" msgcmd)))
+ (stgit-message "Running stg %s..." msgcmd)
+ (prog1
+ (apply 'call-process "stg" nil standard-output nil args)
+ (stgit-message "Running stg %s...done" msgcmd))))
+
+(defun stgit-run-silent (&rest args)
+ (let ((stgit-inhibit-messages t))
+ (apply 'stgit-run args)))
(defun stgit-run-git (&rest args)
(setq args (stgit-make-run-args args))
(let ((msgcmd (mapconcat #'identity args " ")))
- (message "Running git %s..." msgcmd)
- (apply 'call-process "git" nil standard-output nil args)
- (message "Running git %s...done" msgcmd)))
+ (stgit-message "Running git %s..." msgcmd)
+ (prog1
+ (apply 'call-process "git" nil standard-output nil args)
+ (stgit-message "Running git %s...done" msgcmd))))
(defun stgit-run-git-silent (&rest args)
- (setq args (stgit-make-run-args args))
- (apply 'call-process "git" nil standard-output nil args))
+ (let ((stgit-inhibit-messages t))
+ (apply 'stgit-run-git args)))
(defun stgit-index-empty-p ()
"Returns non-nil if the index contains no changes from HEAD."
"Returns non-nil if the work tree contains no changes from index."
(zerop (stgit-run-git-silent "diff-files" "--quiet")))
-(defvar stgit-index-node)
-(defvar stgit-worktree-node)
-
(defvar stgit-did-advise nil
"Set to non-nil if appropriate (non-stgit) git functions have
been advised to update the stgit status when necessary.")
:desc nil
:empty nil)))))
+(defun stgit-svn-find-rev (sha1 hash)
+ "Return the subversion revision corresponding to SHA1 as
+reported by git svn.
+
+Cached data is stored in HASH, which must have been created
+using (make-hash-table :test 'equal)."
+ (let ((result (gethash sha1 hash t)))
+ (when (eq result t)
+ (let ((svn-rev (with-output-to-string
+ (stgit-run-git-silent "svn" "find-rev"
+ "--" sha1))))
+ (setq result (when (string-match "\\`[0-9]+" svn-rev)
+ (string-to-number (match-string 0 svn-rev))))
+ (puthash sha1 result hash)))
+ result))
+
(defun stgit-run-series (ewoc)
(setq stgit-index-node nil
stgit-worktree-node nil)
(let (all-patchsyms)
(when stgit-show-committed
- (let* ((base (stgit-id "{base}"))
+ (let* ((show-svn stgit-show-svn)
+ (svn-hash stgit-svn-find-rev-hash)
+ (base (stgit-id "{base}"))
(range (format "%s~%d..%s" base stgit-committed-count base)))
(with-temp-buffer
(let* ((standard-output (current-buffer))
(fmt (stgit-line-format))
(commit-abbrev (when (string-match "%-\\([0-9]+\\)n" fmt)
- (list (format "--abbrev=%s"
- (match-string 1 fmt)))))
- (exit-status (apply 'stgit-run-git-silent
- "--no-pager"
- "log" "--reverse" "--pretty=oneline"
- "--abbrev-commit"
- `(,@commit-abbrev
- ,range))))
+ (string-to-number (match-string 1 fmt))))
+ (exit-status (stgit-run-git-silent "--no-pager" "log"
+ "--reverse"
+ "--pretty=oneline"
+ range)))
(goto-char (point-min))
(if (not (zerop exit-status))
(message "Failed to run git log")
"\\([0-9a-f]+\\)\\(\\.\\.\\.\\)? \\(.*\\)")
(error "Syntax error in output from git log"))
(let* ((state 'committed)
- (name (intern (match-string 1)))
+ (name (match-string 1))
(desc (match-string 3))
(empty nil))
+
+ (when show-svn
+ (let ((svn-rev (stgit-svn-find-rev name svn-hash)))
+ (when svn-rev
+ (setq desc (format "(r%s) %s" svn-rev desc)))))
+
+ (and commit-abbrev
+ (< commit-abbrev (length name))
+ (setq name (substring name 0 commit-abbrev)))
+
+ (setq name (intern name))
+
(setq all-patchsyms (cons name all-patchsyms))
(ewoc-enter-last ewoc
(make-stgit-patch
(stgit-run-silent "branch"))
0 -1))
-(defun stgit-reload ()
- "Update the contents of the StGit buffer."
+(defun stgit-reload (&optional description)
+ "Update the contents of the StGit buffer.
+
+If DESCRIPTION is non-nil, it is displayed as a status message
+during the operation."
(interactive)
(stgit-assert-mode)
+ (when description
+ (message "%s..." description))
(let ((inhibit-read-only t)
(curline (line-number-at-pos))
(curpatch (stgit-patch-name-at-point))
- (curfile (stgit-patched-file-at-point)))
+ (curfile (stgit-patched-file-at-point))
+ (stgit-inhibit-messages description))
(ewoc-filter stgit-ewoc #'(lambda (x) nil))
(ewoc-set-hf stgit-ewoc
(concat "Branch: "
(unless (and curpatch
(stgit-goto-patch curpatch
(and curfile (stgit-file->file curfile))))
- (goto-line curline)))
- (stgit-refresh-git-status))
+ (goto-char (point-min))
+ (forward-line (1- curline))
+ (move-to-column (stgit-goal-column)))
+ (stgit-refresh-git-status))
+ (when description
+ (message "%s...done" description)))
(defconst stgit-file-status-code-strings
(mapcar (lambda (arg)
("t" . stgit-toggle-worktree)
("h" . stgit-toggle-committed)
("i" . stgit-toggle-ignored)
- ("u" . stgit-toggle-unknown)))
+ ("u" . stgit-toggle-unknown)
+ ("s" . stgit-toggle-svn)))
(setq stgit-mode-map (make-keymap))
(suppress-keymap stgit-mode-map)
(mapc (lambda (arg) (define-key stgit-mode-map (car arg) (cdr arg)))
:selected stgit-show-patch-names]
["Show recent commits" stgit-toggle-committed :style toggle
:selected stgit-show-committed]
+ ["Show subversion info" stgit-toggle-svn :style toggle
+ :selected stgit-show-svn]
"-"
["Switch branches" stgit-branch t
:help "Switch to or create another branch"]
\\[stgit-toggle-unknown] Toggle showing unknown files
\\[stgit-toggle-ignored] Toggle showing ignored files
\\[stgit-toggle-committed] Toggle showing recent commits
+\\[stgit-toggle-svn] Toggle showing subversion information
Commands for diffs:
\\[stgit-diff] Show diff of patch or file
`stgit-default-show-unknown'
`stgit-default-show-worktree'
`stgit-default-show-committed'
+`stgit-default-show-svn'
`stgit-default-committed-count'
`stgit-find-copies-harder'
`stgit-show-worktree-mode'
(stgit-index-node . nil)
(stgit-worktree-node . nil)
(stgit-marked-patches . nil)
+ (stgit-svn-find-rev-hash . ,(make-hash-table :test 'equal))
(stgit-committed-count . ,stgit-default-committed-count)
(stgit-show-committed . ,stgit-default-show-committed)
(stgit-show-ignored . ,stgit-default-show-ignored)
(stgit-show-patch-names . ,stgit-default-show-patch-names)
+ (stgit-show-svn . ,stgit-default-show-svn)
(stgit-show-unknown . ,stgit-default-show-unknown)
(stgit-show-worktree . ,stgit-default-show-worktree)))
(set-variable 'truncate-lines 't)
(list unmerged-stage))
(t
(list (concat patch-id "^") patch-id)))
+ (and (eq (stgit-file->status patched-file) 'copy)
+ '("--diff-filter=C"))
'("--")
(if (stgit-file->copy-or-rename patched-file)
(list (stgit-file->cr-from patched-file)
(if (eq patch-id :index)
'("--cached")
(list unmerged-stage))))
- (let ((args (append '("show" "-O" "--patch-with-stat" "-O" "-M")
+ (let ((args (append '("show" "-O" "--patch-with-stat")
+ `("-O" ,(stgit-find-copies-harder-diff-arg))
(and space-arg (list "-O" space-arg))
'("--")
(list (stgit-patch-name-at-point)))))
(error "Can only show diff range for applied patches"))
(stgit-capture-output (format "*StGit diff %s..%s*"
first-patch second-patch)
- (apply 'stgit-run-git (append '("diff" "--patch-with-stat")
- (and whitespace-arg (list whitespace-arg))
- (list (format "%s^" (stgit-id first-patch))
- (stgit-id second-patch))))
+ (apply 'stgit-run-git
+ "diff" "--patch-with-stat"
+ (stgit-find-copies-harder-diff-arg)
+ (append (and whitespace-arg (list whitespace-arg))
+ (list (format "%s^" (stgit-id first-patch))
+ (stgit-id second-patch))))
(with-current-buffer standard-output
(goto-char (point-min))
(diff-mode)))))
PATCHSYMS must not contain duplicate entries, unless
ALLOW-DUPLICATES is not nil."
- (let (sorted-patchsyms
- (series (with-output-to-string
- (with-current-buffer standard-output
- (stgit-run-silent "series" "--noprefix"))))
- start)
- (while (string-match "^\\(.+\\)" series start)
- (let ((patchsym (intern (match-string 1 series))))
- (when (memq patchsym patchsyms)
- (setq sorted-patchsyms (cons patchsym sorted-patchsyms))))
- (setq start (match-end 0)))
+ (let (sorted-patchsyms)
+ (ewoc-map #'(lambda (patch)
+ (let ((name (stgit-patch->name patch)))
+ (when (memq name patchsyms)
+ (setq sorted-patchsyms (cons name sorted-patchsyms))))
+ nil)
+ stgit-ewoc)
(setq sorted-patchsyms (nreverse sorted-patchsyms))
(unless allow-duplicates
(unless at-pmark
(goto-char old-point)))))
-(defun stgit-execute ()
+(defun stgit-execute (&optional git-mode)
"Prompt for an stg command to execute in a shell.
The names of any marked patches or the patch at point are
inserted in the command to be executed.
+With a prefix argument, or if GIT-MODE is non-nil, insert SHA1
+sums of the marked patches instead, and prompt for a git command.
+
If the command ends in an ampersand, run it asynchronously.
When the command has finished, reload the stgit buffer."
- (interactive)
+ (interactive "P")
(stgit-assert-mode)
- (let* ((patches (stgit-patches-marked-or-at-point nil 'allow-committed))
+ (let* ((patches (stgit-sort-patches
+ (stgit-patches-marked-or-at-point nil 'allow-committed)))
(patch-names (mapcar 'symbol-name patches))
(hyphens (find-if (lambda (s) (string-match "^-" s)) patch-names))
(defaultcmd (if patches
- (concat "stg "
+ (concat (if git-mode "git" "stg") " "
(and hyphens "-- ")
- (mapconcat 'identity patch-names " "))
+ (mapconcat (if git-mode 'stgit-id 'identity)
+ patch-names " "))
"stg "))
(cmd (read-from-minibuffer "Shell command: " (cons defaultcmd 5)
nil nil 'shell-command-history))
(defvar stgit-show-committed nil
"If nil, inhibit showing recent commits.")
+(defvar stgit-show-svn nil
+ "If nil, inhibit showing git svn information.")
+
(defvar stgit-committed-count nil
"The number of recent commits to show.")
-(defmacro stgit-define-toggle-view (sym help)
+(defmacro stgit-define-toggle-view (sym desc help)
(declare (indent 1))
(let* ((name (symbol-name sym))
(fun (intern (concat "stgit-toggle-" name)))
(setq ,flag (if arg
(> (prefix-numeric-value arg) 0)
(not ,flag)))
- (stgit-reload))))
+ (stgit-reload (format "%s %s" (if ,flag "Showing" "Hiding") ,desc)))))
(stgit-define-toggle-view worktree
+ "work tree and index"
"Toggle the visibility of the work tree.
With ARG, show the work tree if ARG is positive.
work tree will show up.")
(stgit-define-toggle-view ignored
+ "ignored files"
"Toggle the visibility of files ignored by git in the work
tree. With ARG, show these files if ARG is positive.
Use \\[stgit-toggle-worktree] to show the work tree.")
(stgit-define-toggle-view unknown
+ "unknown files"
"Toggle the visibility of files not registered with git in the
work tree. With ARG, show these files if ARG is positive.
Use \\[stgit-toggle-worktree] to show the work tree.")
(stgit-define-toggle-view patch-names
+ "patch names"
"Toggle the visibility of patch names. With ARG, show patch names
if ARG is positive.
The initial setting is controlled by `stgit-default-show-patch-names'.")
+(stgit-define-toggle-view svn
+ "subversion revisions"
+ "Toggle showing subversion information from git svn. With ARG,
+show svn information if ARG is positive.
+
+The initial setting is controlled by `stgit-default-show-svn'.")
+
(defun stgit-toggle-committed (&optional arg)
"Toggle the visibility of historical git commits.
With ARG, set the number of commits to show to ARG, and disable
(let ((n (prefix-numeric-value arg)))
(setq stgit-show-committed (> n 0))
(setq stgit-committed-count n)))
- (stgit-reload))
+ (stgit-reload (format "%s historical commits"
+ (if (and stgit-show-committed
+ (> stgit-committed-count 0))
+ "Showing"
+ "Hiding"))))
(provide 'stgit)