;;; vc-hg.el --- VC backend for the mercurial version control system -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2012 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2013 Free Software Foundation, Inc.
;; Author: Ivan Kanis
;; Maintainer: FSF
;; - clear-headers () ??
;; - delete-file (file) TEST IT
;; - rename-file (old new) OK
-;; - find-file-hook () PROBABLY NOT NEEDED
+;; - find-file-hook () added for bug#10709
;; 2) Implement Stefan Monnier's advice:
;; vc-hg-registered and vc-hg-state
(2 'change-log-list)
(3 'change-log-name)
(4 'change-log-date)))
- "Mercurial log template for `vc-print-root-log'.
+ "Mercurial log template for `vc-hg-print-log' short format.
This should be a list (TEMPLATE REGEXP KEYWORDS), where TEMPLATE
is the \"--template\" argument string to pass to Mercurial,
REGEXP is a regular expression matching the resulting Mercurial
;;;###autoload "Return non-nil if FILE is registered with hg."
;;;###autoload (if (vc-find-root file ".hg") ; short cut
;;;###autoload (progn
-;;;###autoload (load "vc-hg")
+;;;###autoload (load "vc-hg" nil t)
;;;###autoload (vc-hg-registered file))))
;; Modeled after the similar function in vc-bzr.el
(repeat :tag "Argument List" :value ("") string))
:group 'vc-hg)
+(autoload 'vc-setup-buffer "vc-dispatcher")
+
(defun vc-hg-print-log (files buffer &optional shortlog start-revision limit)
- "Get change log associated with FILES."
+ "Print commit log associated with FILES into specified BUFFER.
+If SHORTLOG is non-nil, use a short format based on `vc-hg-root-log-format'.
+If START-REVISION is non-nil, it is the newest revision to show.
+If LIMIT is non-nil, show no more than this many entries."
;; `vc-do-command' creates the buffer, but we need it before running
;; the command.
(vc-setup-buffer buffer)
buffer
(apply 'vc-hg-command buffer 0 files "log"
(nconc
- (when start-revision (list (format "-r%s:" start-revision)))
+ (when start-revision (list (format "-r%s:0" start-revision)))
(when limit (list "-l" (format "%s" limit)))
(when shortlog (list "--template" (car vc-hg-root-log-format)))
vc-hg-log-switches)))))
("^tag: +\\([^ ]+\\)$" (1 'highlight))
("^summary:[ \t]+\\(.+\\)" (1 'log-view-message)))))))
+(autoload 'vc-switches "vc")
+
(defun vc-hg-diff (files &optional oldvers newvers buffer)
"Get a difference report using hg between two revisions of FILES."
(let* ((firstfile (car files))
;;215 Wed Jun 20 21:22:58 2007 -0700 foo.c: CONTENTS
;; i.e. VERSION_NUMBER DATE FILENAME: CONTENTS
(defconst vc-hg-annotate-re
- "^[ \t]*\\([0-9]+\\) \\(.\\{30\\}\\)\\(?:\\(: \\)\\|\\(?: +\\(.+\\): \\)\\)")
+ "^[ \t]*\\([0-9]+\\) \\(.\\{30\\}\\)\\(?:\\(: \\)\\|\\(?: +\\([^:\n]+\\(?::\\(?:[^: \n][^:\n]*\\)?\\)*\\): \\)\\)")
(defun vc-hg-annotate-time ()
(when (looking-at vc-hg-annotate-re)
(let ((newrev (1+ (string-to-number rev)))
(tip-revision
(with-temp-buffer
- (vc-hg-command t 0 nil "tip")
+ (vc-hg-command t 0 nil "tip" "--style=default")
(goto-char (point-min))
(re-search-forward "^changeset:[ \t]*\\([0-9]+\\):")
(string-to-number (match-string-no-properties 1)))))
(vc-hg-command buffer 0 file "cat" "-r" rev)
(vc-hg-command buffer 0 file "cat"))))
+(defun vc-hg-find-ignore-file (file)
+ "Return the root directory of the repository of FILE."
+ (expand-file-name ".hgignore"
+ (vc-hg-root file)))
+
;; Modeled after the similar function in vc-bzr.el
(defun vc-hg-checkout (file &optional _editable rev)
"Retrieve a revision of FILE.
(vc-hg-command t 0 file "cat" "-r" rev)
(vc-hg-command t 0 file "cat")))))
+(defun vc-hg-resolve-when-done ()
+ "Call \"hg resolve -m\" if the conflict markers have been removed."
+ (save-excursion
+ (goto-char (point-min))
+ (unless (re-search-forward "^<<<<<<< " nil t)
+ (vc-hg-command nil 0 buffer-file-name "resolve" "-m")
+ ;; Remove the hook so that it is not called multiple times.
+ (remove-hook 'after-save-hook 'vc-hg-resolve-when-done t))))
+
+(defun vc-hg-find-file-hook ()
+ (when (and buffer-file-name
+ (file-exists-p (concat buffer-file-name ".orig"))
+ ;; Hg does not seem to have a "conflict" status, eg
+ ;; hg http://bz.selenic.com/show_bug.cgi?id=2724
+ (memq (vc-file-getprop buffer-file-name 'vc-state)
+ '(edited conflict))
+ ;; Maybe go on to check that "hg resolve -l" says "U"?
+ ;; If "hg resolve -l" says there's a conflict but there are no
+ ;; conflict markers, it's not clear what we should do.
+ (save-excursion
+ (goto-char (point-min))
+ (re-search-forward "^<<<<<<< " nil t)))
+ ;; Hg may not recognize "conflict" as a state, but we can do better.
+ (vc-file-setprop buffer-file-name 'vc-state 'conflict)
+ (smerge-start-session)
+ (add-hook 'after-save-hook 'vc-hg-resolve-when-done nil t)
+ (message "There are unresolved conflicts in this file")))
+
+
;; Modeled after the similar function in vc-bzr.el
(defun vc-hg-workfile-unchanged-p (file)
(eq 'up-to-date (vc-hg-state file)))
(forward-line))
(funcall update-function result)))
+;; Follows vc-hg-command (or vc-do-async-command), which uses vc-do-command
+;; from vc-dispatcher.
+(declare-function vc-exec-after "vc-dispatcher" (code))
+;; Follows vc-exec-after.
+(declare-function vc-set-async-update "vc-dispatcher" (process-buffer))
+
(defun vc-hg-dir-status (dir update-function)
(vc-hg-command (current-buffer) 'async dir "status" "-C")
- (vc-exec-after
- `(vc-hg-after-dir-status (quote ,update-function))))
+ (vc-run-delayed
+ (vc-hg-after-dir-status update-function)))
(defun vc-hg-dir-status-files (dir files _default-state update-function)
(apply 'vc-hg-command (current-buffer) 'async dir "status" "-C" files)
- (vc-exec-after
- `(vc-hg-after-dir-status (quote ,update-function))))
+ (vc-run-delayed
+ (vc-hg-after-dir-status update-function)))
(defun vc-hg-dir-extra-header (name &rest commands)
(concat (propertize name 'face 'font-lock-type-face)
;; modified files
"Value of `compilation-error-regexp-alist' in *vc-hg* buffers.")
+(autoload 'vc-do-async-command "vc-dispatcher")
+
(defun vc-hg-pull (prompt)
"Issue a Mercurial pull command.
If called interactively with a set of marked Log View buffers,
args (cddr args)))
(apply 'vc-do-async-command buffer root hg-program
command args)
- (with-current-buffer buffer (vc-exec-after '(vc-compilation-mode 'hg)))
+ (with-current-buffer buffer
+ (vc-run-delayed (vc-compilation-mode 'hg)))
(vc-set-async-update buffer)))))
(defun vc-hg-merge-branch ()
(let* ((root (vc-hg-root default-directory))
(buffer (format "*vc-hg : %s*" (expand-file-name root))))
(apply 'vc-do-async-command buffer root vc-hg-program '("merge"))
- (with-current-buffer buffer (vc-exec-after '(vc-compilation-mode 'hg)))
+ (with-current-buffer buffer (vc-run-delayed (vc-compilation-mode 'hg)))
(vc-set-async-update buffer)))
;;; Internal functions