argument. Add a new method: root.
* vc-hooks.el (vc-prefix-map, vc-menu-map): Add bindings for
vc-print-root-log and vc-print-root-diff.
* vc-bzr.el (vc-bzr-log-view-mode, vc-bzr-print-log):
* vc-git.el (vc-git-print-log, vc-git-log-view-mode):
* vc-hg.el (vc-hg-print-log, vc-hg-log-view-mode): Add support for
short logs.
* vc-cvs.el (vc-cvs-print-log):
* vc-mtn.el (vc-mtn-print-log):
* vc-rcs.el (vc-rcs-print-log):
* vc-sccs.el (vc-sccs-print-log):
* vc-svn.el (vc-svn-print-log): Add an optional argument shortlog
that is ignored for now.
** VC and related modes
+*** FIXME: add info about the new VC functions: vc-root-diff and
+vc-root-print-log once they stabilize.
+
*** When a file is not found, VC will not try to check it out of RCS anymore.
*** vc-git changes
+2009-09-14 Dan Nicolaescu <dann@ics.uci.edu>
+
+ * vc.el (top): print-log method now takes an optional SHORTLOG
+ argument. Add a new method: root.
+
+ (vc-root-diff, vc-print-root-log): New functions.
+ (vc-log-short-style): New variable.
+ (vc-print-log-internal): Add support for showing short logs.
+
+ * vc-hooks.el (vc-prefix-map, vc-menu-map): Add bindings for
+ vc-print-root-log and vc-print-root-diff.
+
+ * vc-bzr.el (vc-bzr-log-view-mode, vc-bzr-print-log):
+ * vc-git.el (vc-git-print-log, vc-git-log-view-mode):
+ * vc-hg.el (vc-hg-print-log, vc-hg-log-view-mode): Add support for
+ short logs.
+
+ * vc-cvs.el (vc-cvs-print-log):
+ * vc-mtn.el (vc-mtn-print-log):
+ * vc-rcs.el (vc-rcs-print-log):
+ * vc-sccs.el (vc-sccs-print-log):
+ * vc-svn.el (vc-svn-print-log): Add an optional argument shortlog
+ that is ignored for now.
+
2009-09-14 Stefan Monnier <monnier@iro.umontreal.ca>
* simple.el: Add mapping for backspace/delete/clear/tab/escape/return
(defvar log-view-font-lock-keywords)
(defvar log-view-current-tag-function)
(defvar log-view-per-file-logs)
+(defvar vc-short-log)
(define-derived-mode vc-bzr-log-view-mode log-view-mode "Bzr-Log-View"
(remove-hook 'log-view-mode-hook 'vc-bzr-log-view-mode) ;Deactivate the hack.
(set (make-local-variable 'log-view-per-file-logs) nil)
(set (make-local-variable 'log-view-file-re) "\\`a\\`")
(set (make-local-variable 'log-view-message-re)
- "^ *\\(?:revno: \\([0-9.]+\\)\\|merged: .+\\)")
+ (if vc-short-log
+ "^ +\\([0-9]+\\) \\(.*?\\)[ \t]+\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)\\( \\[merge\\]\\)?"
+ "^ *\\(?:revno: \\([0-9.]+\\)\\|merged: .+\\)"))
(set (make-local-variable 'log-view-font-lock-keywords)
;; log-view-font-lock-keywords is careful to use the buffer-local
;; value of log-view-message-re only since Emacs-23.
- (append `((,log-view-message-re . 'log-view-message-face))
- ;; log-view-font-lock-keywords
- '(("^ *committer: \
+ (if vc-short-log
+ (append `((,log-view-message-re
+ (1 'log-view-message-face)
+ (2 'change-log-name)
+ (3 'change-log-date)
+ (4 'change-log-list))))
+ (append `((,log-view-message-re . 'log-view-message-face))
+ ;; log-view-font-lock-keywords
+ '(("^ *committer: \
\\([^<(]+?\\)[ ]*[(<]\\([[:alnum:]_.+-]+@[[:alnum:]_.-]+\\)[>)]"
- (1 'change-log-name)
- (2 'change-log-email))
- ("^ *timestamp: \\(.*\\)" (1 'change-log-date-face))))))
+ (1 'change-log-name)
+ (2 'change-log-email))
+ ("^ *timestamp: \\(.*\\)" (1 'change-log-date-face)))))))
-(defun vc-bzr-print-log (files &optional buffer) ; get buffer arg in Emacs 22
+(defun vc-bzr-print-log (files &optional buffer shortlog) ; get buffer arg in Emacs 22
"Get bzr change log for FILES into specified BUFFER."
;; `vc-do-command' creates the buffer, but we need it before running
;; the command.
;; way of getting the above regexps working.
(with-current-buffer buffer
(apply 'vc-bzr-command "log" buffer 'async files
+ (if shortlog "--short")
(if (stringp vc-bzr-log-switches)
(list vc-bzr-log-switches)
vc-bzr-log-switches))))
(declare-function vc-rcs-print-log-cleanup "vc-rcs" ())
-(defun vc-cvs-print-log (files &optional buffer)
+(defun vc-cvs-print-log (files &optional buffer shortlog)
"Get change logs associated with FILES."
(require 'vc-rcs)
;; It's just the catenation of the individual logs.
;;; HISTORY FUNCTIONS
-(defun vc-git-print-log (files &optional buffer)
+(defun vc-git-print-log (files &optional buffer shortlog)
"Get change log associated with FILES."
(let ((coding-system-for-read git-commits-coding-system)
;; Support both the old print-log interface that passes a
(let ((inhibit-read-only t))
(with-current-buffer
buffer
+ (if shortlog
(vc-git-command buffer 'async files
- "rev-list" "--pretty" "HEAD" "--")))))
+ "log" ;; "--graph"
+ "--date=short" "--pretty=format:%h %ad %s" "--abbrev-commit"
+ "--")
+ (vc-git-command buffer 'async files
+ "rev-list" ;; "--graph"
+ "--pretty" "HEAD" "--"))))))
(defvar log-view-message-re)
(defvar log-view-file-re)
(defvar log-view-font-lock-keywords)
(defvar log-view-per-file-logs)
+;; Dynamically bound.
+(defvar vc-short-log)
+
(define-derived-mode vc-git-log-view-mode log-view-mode "Git-Log-View"
(require 'add-log) ;; we need the faces add-log
;; Don't have file markers, so use impossible regexp.
(set (make-local-variable 'log-view-file-re) "\\`a\\`")
(set (make-local-variable 'log-view-per-file-logs) nil)
(set (make-local-variable 'log-view-message-re)
- "^commit *\\([0-9a-z]+\\)")
+ (if vc-short-log
+ "^\\(?:[*/\\| ]+ \\)?\\([0-9a-z]+\\) \\([-a-z0-9]+\\) \\(.*\\)"
+ "^[ */\\|]+commit *\\([0-9a-z]+\\)"))
(set (make-local-variable 'log-view-font-lock-keywords)
+ (if vc-short-log
+ (append
+ `((,log-view-message-re
+ (1 'change-log-acknowledgement)
+ (2 'change-log-date))))
(append
`((,log-view-message-re (1 'change-log-acknowledgement)))
;; Handle the case:
(1 'change-log-acknowledgement)
(2 'change-log-acknowledgement))
("^Date: \\(.+\\)" (1 'change-log-date))
- ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message))))))
+ ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message)))))))
+
(defun vc-git-show-log-entry (revision)
"Move to the log entry for REVISION.
(defun vc-git-extra-status-menu () vc-git-extra-menu-map)
+(defun vc-git-root (file)
+ (vc-find-root file ".git"))
+
(defun vc-git-toggle-signoff ()
(interactive)
(setq vc-git-add-signoff (not vc-git-add-signoff)))
\f
;;; Internal commands
-(defun vc-git-root (file)
- (vc-find-root file ".git"))
-
(defun vc-git-command (buffer okstatus file-or-list &rest flags)
"A wrapper around `vc-do-command' for use in vc-git.el.
The difference to vc-do-command is that this function always invokes `git'."
;; - merge-news (file) NEEDED
;; - steal-lock (file &optional revision) NOT NEEDED
;; HISTORY FUNCTIONS
-;; * print-log (files &optional buffer) OK
+;; * print-log (files &optional buffer shortlog)OK
;; - log-view-mode () OK
;; - show-log-entry (revision) NOT NEEDED, DEFAULT IS GOOD
;; - comment-history (file) NOT NEEDED
(repeat :tag "Argument List" :value ("") string))
:group 'vc-hg)
-(defun vc-hg-print-log (files &optional buffer)
+(defun vc-hg-print-log (files &optional buffer shortlog)
"Get change log associated with FILES."
;; `log-view-mode' needs to have the file names in order to function
;; correctly. "hg log" does not print it, so we insert it here by
(let ((inhibit-read-only t))
(with-current-buffer
buffer
- (apply 'vc-hg-command buffer 0 files "log" vc-hg-log-switches))))
+ (apply 'vc-hg-command buffer 0 files "log"
+ (if shortlog '("--style" "compact"))
+ vc-hg-log-switches))))
(defvar log-view-message-re)
(defvar log-view-file-re)
(defvar log-view-font-lock-keywords)
(defvar log-view-per-file-logs)
+(defvar vc-short-log)
(define-derived-mode vc-hg-log-view-mode log-view-mode "Hg-Log-View"
(require 'add-log) ;; we need the add-log faces
(set (make-local-variable 'log-view-file-re) "\\`a\\`")
(set (make-local-variable 'log-view-per-file-logs) nil)
(set (make-local-variable 'log-view-message-re)
- "^changeset:[ \t]*\\([0-9]+\\):\\(.+\\)")
+ (if vc-short-log
+ "^\\([0-9]+\\)\\(?:\\[.*\\]\\)? +\\([0-9a-z]\\{12\\}\\) +\\(\\(?:[0-9]+\\)-\\(?:[0-9]+\\)-\\(?:[0-9]+\\) \\(?:[0-9]+\\):\\(?:[0-9]+\\) \\(?:[-+0-9]+\\)\\) +\\(.*\\)$"
+ "^changeset:[ \t]*\\([0-9]+\\):\\(.+\\)"))
(set (make-local-variable 'log-view-font-lock-keywords)
+ (if vc-short-log
+ (append `((,log-view-message-re
+ (1 'log-view-message-face)
+ (2 'log-view-message-face)
+ (3 'change-log-date)
+ (4 'change-log-name))))
(append
log-view-font-lock-keywords
'(
("^user:[ \t]+\\([A-Za-z0-9_.+-]+\\(?:@[A-Za-z0-9_.-]+\\)?\\)"
(1 'change-log-email))
("^date: \\(.+\\)" (1 'change-log-date))
- ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message))))))
+ ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message)))))))
(defun vc-hg-diff (files &optional oldvers newvers buffer)
"Get a difference report using hg between two revisions of FILES."
(define-key map "h" 'vc-insert-headers)
(define-key map "i" 'vc-register)
(define-key map "l" 'vc-print-log)
+ (define-key map "L" 'vc-print-root-log)
(define-key map "m" 'vc-merge)
(define-key map "r" 'vc-retrieve-tag)
(define-key map "s" 'vc-create-tag)
(define-key map "v" 'vc-next-action)
(define-key map "+" 'vc-update)
(define-key map "=" 'vc-diff)
+ (define-key map "D" 'vc-root-diff)
(define-key map "~" 'vc-revision-other-window)
map))
(fset 'vc-prefix-map vc-prefix-map)
(define-key map [vc-diff]
'(menu-item "Compare with Base Version" vc-diff
:help "Compare file set with the base version"))
+ (define-key map [vc-root-diff]
+ '(menu-item "Compare Tree with Base Version" vc-root-diff
+ :help "Compare current tree with the base version"))
(define-key map [vc-update-change-log]
'(menu-item "Update ChangeLog" vc-update-change-log
:help "Find change log file and add entries from recent version control logs"))
(define-key map [vc-print-log]
'(menu-item "Show History" vc-print-log
:help "List the change log of the current file set in a window"))
+ (define-key map [vc-print-root-log]
+ '(menu-item "Show Top of the Tree History " vc-print-root-log
+ :help "List the change log for the current tree in a window"))
(define-key map [separator2] '("----"))
(define-key map [vc-insert-header]
'(menu-item "Insert Header" vc-insert-headers
;; (defun vc-mtn-roolback (files)
;; )
-(defun vc-mtn-print-log (files &optional buffer)
+(defun vc-mtn-print-log (files &optional buffer shortlog)
(vc-mtn-command buffer 0 files "log"))
(defvar log-view-message-re)
(when (looking-at "[\b\t\n\v\f\r ]+")
(delete-char (- (match-end 0) (match-beginning 0))))))
-(defun vc-rcs-print-log (files &optional buffer)
+(defun vc-rcs-print-log (files &optional buffer shortlog)
"Get change log associated with FILE. If FILE is a
directory the operation is applied to all registered files beneath it."
(vc-do-command (or buffer "*vc*") 0 "rlog" (mapcar 'vc-name (vc-expand-dirs files)))
;;; History functions
;;;
-(defun vc-sccs-print-log (files &optional buffer)
+(defun vc-sccs-print-log (files &optional buffer shortlog)
"Get change log associated with FILES."
(setq files (vc-expand-dirs files))
(vc-sccs-do-command buffer 0 "prs" (mapcar 'vc-name files)))
(require 'add-log)
(set (make-local-variable 'log-view-per-file-logs) nil))
-(defun vc-svn-print-log (files &optional buffer)
+(defun vc-svn-print-log (files &optional buffer shortlog)
"Get change log(s) associated with FILES."
(save-current-buffer
(vc-setup-buffer buffer)
;;
;; HISTORY FUNCTIONS
;;
-;; * print-log (files &optional buffer)
+;; * print-log (files &optional buffer shortlog)
;;
;; Insert the revision log for FILES into BUFFER, or the *vc* buffer
;; if BUFFER is nil. (Note: older versions of this function expected
;; only a single file argument.)
+;; If SHORTLOG is true insert a short version of the log.
;;
;; - log-view-mode ()
;;
;; `revert' operations itself, without calling the backend system. The
;; default implementation always returns nil.
;;
+;; - root (file)
+;; Return the root of the VC controlled hierarchy for file.
+;;
;; - repository-hostname (dirname)
;;
;; Return the hostname that the backend will have to contact
(when buffer-file-name (vc-buffer-sync not-urgent))
(vc-diff-internal t (vc-deduce-fileset) nil nil (interactive-p))))
+;;;###autoload
+(defun vc-root-diff (historic &optional not-urgent)
+ "Display diffs between file revisions.
+Normally this compares the currently selected fileset with their
+working revisions. With a prefix argument HISTORIC, it reads two revision
+designators specifying which revisions to compare.
+
+The optional argument NOT-URGENT non-nil means it is ok to say no to
+saving the buffer."
+ (interactive (list current-prefix-arg t))
+ (if historic
+ ;; FIXME: this does not work right, `vc-version-diff' ends up
+ ;; calling `vc-deduce-fileset' to find the files to diff, and
+ ;; that's not what we want here, we want the diff for the VC root dir.
+ (call-interactively 'vc-version-diff)
+ (when buffer-file-name (vc-buffer-sync not-urgent))
+ (let ((backend
+ (cond ((derived-mode-p 'vc-dir-mode) vc-dir-backend)
+ (vc-mode (vc-backend buffer-file-name))))
+ rootdir working-revision)
+ (unless backend
+ (error "Buffer is not version controlled"))
+ (setq rootdir (vc-call-backend backend 'root default-directory))
+ (setq working-revision (vc-working-revision rootdir))
+ (vc-diff-internal
+ t (list backend (list rootdir) working-revision) nil nil (interactive-p)))))
+
;;;###autoload
(defun vc-revision-other-window (rev)
"Visit revision REV of the current file in another window.
;; Miscellaneous other entry points
+;; FIXME: this should be a defcustom
+;; FIXME: maybe add another choice:
+;; `root-directory' (or somesuch), which would mean show a short log
+;; for the root directory.
+(defvar vc-log-short-style '(directory)
+ "Whether or not to show a short log.
+If it contains `directory' then if the fileset contains a directory show a short log.
+If it contains `file' then show short logs for files.
+Not all VC backends support short logs!")
+
(defun vc-print-log-internal (backend files working-revision)
;; Don't switch to the output buffer before running the command,
;; so that any buffer-local settings in the vc-controlled
;; buffer can be accessed by the command.
- (vc-call-backend backend 'print-log files "*vc-change-log*")
- (pop-to-buffer "*vc-change-log*")
- (vc-exec-after
- `(let ((inhibit-read-only t))
- (vc-call-backend ',backend 'log-view-mode)
- (set (make-local-variable 'log-view-vc-backend) ',backend)
- (set (make-local-variable 'log-view-vc-fileset) ',files)
-
- (shrink-window-if-larger-than-buffer)
- ;; move point to the log entry for the working revision
- (vc-call-backend ',backend 'show-log-entry ',working-revision)
- (setq vc-sentinel-movepoint (point))
- (set-buffer-modified-p nil))))
+ (let ((dir-present nil)
+ (vc-short-log nil))
+ (dolist (file files)
+ (when (file-directory-p file)
+ (setq dir-present t)))
+ (setq vc-short-log
+ (not (null (if dir-present
+ (memq 'directory vc-log-short-style)
+ (memq 'file vc-log-short-style)))))
+ (vc-call-backend backend 'print-log files "*vc-change-log*" vc-short-log)
+ (pop-to-buffer "*vc-change-log*")
+ (vc-exec-after
+ `(let ((inhibit-read-only t)
+ (vc-short-log ,vc-short-log))
+ (vc-call-backend ',backend 'log-view-mode)
+ (set (make-local-variable 'log-view-vc-backend) ',backend)
+ (set (make-local-variable 'log-view-vc-fileset) ',files)
+
+ (shrink-window-if-larger-than-buffer)
+ ;; move point to the log entry for the working revision
+ (vc-call-backend ',backend 'show-log-entry ',working-revision)
+ (setq vc-sentinel-movepoint (point))
+ (set-buffer-modified-p nil)))))
;;;###autoload
(defun vc-print-log (&optional working-revision)
(working-revision (or working-revision (vc-working-revision (car files)))))
(vc-print-log-internal backend files working-revision)))
+;;;###autoload
+(defun vc-print-root-log ()
+ "List the change log of for the current VC controlled tree in a window."
+ (interactive)
+ (let ((backend
+ (cond ((derived-mode-p 'vc-dir-mode) vc-dir-backend)
+ (vc-mode (vc-backend buffer-file-name))))
+ rootdir working-revision)
+ (unless backend
+ (error "Buffer is not version controlled"))
+ (setq rootdir (vc-call-backend backend 'root default-directory))
+ (setq working-revision (vc-working-revision rootdir))
+ (vc-print-log-internal backend (list rootdir) working-revision)))
+
;;;###autoload
(defun vc-revert ()
"Revert working copies of the selected fileset to their repository contents.