diff options
Diffstat (limited to 'lisp/vc')
-rw-r--r-- | lisp/vc/add-log.el | 104 | ||||
-rw-r--r-- | lisp/vc/compare-w.el | 6 | ||||
-rw-r--r-- | lisp/vc/diff-mode.el | 40 | ||||
-rw-r--r-- | lisp/vc/diff.el | 27 | ||||
-rw-r--r-- | lisp/vc/ediff-diff.el | 145 | ||||
-rw-r--r-- | lisp/vc/ediff-ptch.el | 6 | ||||
-rw-r--r-- | lisp/vc/ediff-util.el | 32 | ||||
-rw-r--r-- | lisp/vc/log-edit.el | 15 | ||||
-rw-r--r-- | lisp/vc/pcvs.el | 20 | ||||
-rw-r--r-- | lisp/vc/vc-arch.el | 2 | ||||
-rw-r--r-- | lisp/vc/vc-bzr.el | 55 | ||||
-rw-r--r-- | lisp/vc/vc-cvs.el | 17 | ||||
-rw-r--r-- | lisp/vc/vc-dir.el | 29 | ||||
-rw-r--r-- | lisp/vc/vc-dispatcher.el | 49 | ||||
-rw-r--r-- | lisp/vc/vc-git.el | 12 | ||||
-rw-r--r-- | lisp/vc/vc-hg.el | 46 | ||||
-rw-r--r-- | lisp/vc/vc-hooks.el | 46 | ||||
-rw-r--r-- | lisp/vc/vc-mtn.el | 6 | ||||
-rw-r--r-- | lisp/vc/vc-rcs.el | 12 | ||||
-rw-r--r-- | lisp/vc/vc-sccs.el | 3 | ||||
-rw-r--r-- | lisp/vc/vc-svn.el | 55 | ||||
-rw-r--r-- | lisp/vc/vc.el | 78 |
22 files changed, 447 insertions, 358 deletions
diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el index bc07b61acff..f0ea9c68464 100644 --- a/lisp/vc/add-log.el +++ b/lisp/vc/add-log.el @@ -61,8 +61,9 @@ ;;;###autoload (defcustom add-log-current-defun-function nil "If non-nil, function to guess name of surrounding function. -It is used by `add-log-current-defun' in preference to built-in rules. -Returns function's name as a string, or nil if outside a function." +It is called by `add-log-current-defun' with no argument, and +should return the function's name as a string, or nil if point is +outside a function." :type '(choice (const nil) function) :group 'change-log) @@ -1118,21 +1119,6 @@ parentheses." :type 'regexp :group 'change-log) -;;;###autoload -(defvar add-log-lisp-like-modes - '(emacs-lisp-mode lisp-mode scheme-mode dsssl-mode lisp-interaction-mode) - "Modes that look like Lisp to `add-log-current-defun'.") - -;;;###autoload -(defvar add-log-c-like-modes - '(c-mode c++-mode c++-c-mode objc-mode) - "Modes that look like C to `add-log-current-defun'.") - -;;;###autoload -(defvar add-log-tex-like-modes - '(TeX-mode plain-TeX-mode LaTeX-mode tex-mode) - "Modes that look like TeX to `add-log-current-defun'.") - (declare-function c-cpp-define-name "cc-cmds" ()) (declare-function c-defun-name "cc-cmds" ()) @@ -1152,75 +1138,21 @@ identifiers followed by `:' or `='. See variables Has a preference of looking backwards." (condition-case nil (save-excursion - (let ((location (point))) - (cond (add-log-current-defun-function - (funcall add-log-current-defun-function)) - ((apply 'derived-mode-p add-log-lisp-like-modes) - ;; If we are now precisely at the beginning of a defun, - ;; make sure beginning-of-defun finds that one - ;; rather than the previous one. - (or (eobp) (forward-char 1)) - (beginning-of-defun) - ;; Make sure we are really inside the defun found, - ;; not after it. - (when (and (looking-at "\\s(") - (progn (end-of-defun) - (< location (point))) - (progn (forward-sexp -1) - (>= location (point)))) - (if (looking-at "\\s(") - (forward-char 1)) - ;; Skip the defining construct name, typically "defun" - ;; or "defvar". - (forward-sexp 1) - ;; The second element is usually a symbol being defined. - ;; If it is not, use the first symbol in it. - (skip-chars-forward " \t\n'(") - (buffer-substring-no-properties (point) - (progn (forward-sexp 1) - (point))))) - ((apply 'derived-mode-p add-log-c-like-modes) - (or (c-cpp-define-name) - (c-defun-name))) - ((apply #'derived-mode-p add-log-tex-like-modes) - (if (re-search-backward - "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)" - nil t) - (progn - (goto-char (match-beginning 0)) - (buffer-substring-no-properties - (1+ (point)) ; without initial backslash - (line-end-position))))) - ((derived-mode-p 'texinfo-mode) - (if (re-search-backward "^@node[ \t]+\\([^,\n]+\\)" nil t) - (match-string-no-properties 1))) - ((derived-mode-p 'perl-mode 'cperl-mode) - (if (re-search-backward "^sub[ \t]+\\([^({ \t\n]+\\)" nil t) - (match-string-no-properties 1))) - ;; Emacs's autoconf-mode installs its own - ;; `add-log-current-defun-function'. This applies to - ;; a different mode apparently for editing .m4 - ;; autoconf source. - ((derived-mode-p 'autoconf-mode) - (if (re-search-backward - "^\\(\\(m4_\\)?define\\|A._DEFUN\\)(\\[?\\([A-Za-z0-9_]+\\)" nil t) - (match-string-no-properties 3))) - (t - ;; If all else fails, try heuristics - (let (case-fold-search - result) - (end-of-line) - (when (re-search-backward - add-log-current-defun-header-regexp - (- (point) 10000) - t) - (setq result (or (match-string-no-properties 1) - (match-string-no-properties 0))) - ;; Strip whitespace away - (when (string-match "\\([^ \t\n\r\f].*[^ \t\n\r\f]\\)" - result) - (setq result (match-string-no-properties 1 result))) - result)))))) + (if add-log-current-defun-function + (funcall add-log-current-defun-function) + ;; If all else fails, try heuristics + (let (case-fold-search + result) + (end-of-line) + (when (re-search-backward add-log-current-defun-header-regexp + (- (point) 10000) t) + (setq result (or (match-string-no-properties 1) + (match-string-no-properties 0))) + ;; Strip whitespace away + (when (string-match "\\([^ \t\n\r\f].*[^ \t\n\r\f]\\)" + result) + (setq result (match-string-no-properties 1 result))) + result)))) (error nil))) (defvar change-log-get-method-definition-md) diff --git a/lisp/vc/compare-w.el b/lisp/vc/compare-w.el index 2423d322460..fa451ccbe20 100644 --- a/lisp/vc/compare-w.el +++ b/lisp/vc/compare-w.el @@ -53,13 +53,13 @@ whitespace is considered to match, and is skipped." :group 'compare-windows) (defcustom compare-ignore-whitespace nil - "Non-nil means `compare-windows' ignores whitespace." + "Non-nil means command `compare-windows' ignores whitespace." :type 'boolean :group 'compare-windows :version "22.1") (defcustom compare-ignore-case nil - "Non-nil means `compare-windows' ignores case differences." + "Non-nil means command `compare-windows' ignores case differences." :type 'boolean :group 'compare-windows) @@ -379,7 +379,7 @@ on third call it again advances points to the next difference and so on." (delete-overlay compare-windows-overlay2))))) (defun compare-windows-dehighlight () - "Remove highlighting created by `compare-windows-highlight'." + "Remove highlighting created by function `compare-windows-highlight'." (interactive) (remove-hook 'pre-command-hook 'compare-windows-dehighlight) (mapc 'delete-overlay compare-windows-overlays1) diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 1647e6bca96..e945d6ef160 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -124,7 +124,6 @@ when editing big diffs)." ("A" . diff-ediff-patch) ("r" . diff-restrict-view) ("R" . diff-reverse-direction) - ("/" . diff-undo) ([remap undo] . diff-undo)) "Basic keymap for `diff-mode', bound to various prefix keys." :inherit special-mode-map) @@ -575,19 +574,21 @@ next hunk if TRY-HARDER is non-nil; otherwise signal an error." (easy-mmode-define-navigation diff-hunk diff-hunk-header-re "hunk" diff-end-of-hunk diff-restrict-view (when diff-auto-refine-mode - (setq diff--auto-refine-data (cons (current-buffer) (point-marker))) - (run-at-time 0.0 nil - (lambda () - (when diff--auto-refine-data - (let ((buffer (car diff--auto-refine-data)) - (point (cdr diff--auto-refine-data))) - (setq diff--auto-refine-data nil) - (with-local-quit - (when (buffer-live-p buffer) - (with-current-buffer buffer - (save-excursion - (goto-char point) - (diff-refine-hunk))))))))))) + (unless (prog1 diff--auto-refine-data + (setq diff--auto-refine-data + (cons (current-buffer) (point-marker)))) + (run-at-time 0.0 nil + (lambda () + (when diff--auto-refine-data + (let ((buffer (car diff--auto-refine-data)) + (point (cdr diff--auto-refine-data))) + (setq diff--auto-refine-data nil) + (with-local-quit + (when (buffer-live-p buffer) + (with-current-buffer buffer + (save-excursion + (goto-char point) + (diff-refine-hunk)))))))))))) (easy-mmode-define-navigation diff-file diff-file-header-re "file" diff-end-of-file) @@ -819,9 +820,11 @@ If the OLD prefix arg is passed, tell the file NAME of the old file." (progn (diff-hunk-prev) (point)) (error (point-min))))) (header-files - (if (looking-at "[-*][-*][-*] \\(\\S-+\\)\\(\\s-.*\\)?\n[-+][-+][-+] \\(\\S-+\\)") - (list (if old (match-string 1) (match-string 3)) - (if old (match-string 3) (match-string 1))) + ;; handle filenames with spaces; + ;; cf. diff-font-lock-keywords / diff-file-header-face + (if (looking-at "[-*][-*][-*] \\([^\t]+\\)\t.*\n[-+][-+][-+] \\([^\t]+\\)") + (list (if old (match-string 1) (match-string 2)) + (if old (match-string 2) (match-string 1))) (forward-line 1) nil))) (delq nil (append @@ -830,6 +833,7 @@ If the OLD prefix arg is passed, tell the file NAME of the old file." (re-search-backward "^Index: \\(.+\\)" limit t))) (list (match-string 1))) header-files + ;; this assumes that there are no spaces in filenames (when (re-search-backward "^diff \\(-\\S-+ +\\)*\\(\\S-+\\)\\( +\\(\\S-+\\)\\)?" nil t) @@ -1296,7 +1300,7 @@ See `after-change-functions' for the meaning of BEG, END and LEN." (re-search-forward diff-context-mid-hunk-header-re nil t))))) (when (and ;; Don't try to fixup changes in the hunk header. - (> (car diff-unhandled-changes) start) + (>= (car diff-unhandled-changes) start) ;; Don't try to fixup changes in the mid-hunk header either. (or (not mid) (< (cdr diff-unhandled-changes) (match-beginning 0)) diff --git a/lisp/vc/diff.el b/lisp/vc/diff.el index d0e496d2d21..0fc0d2e3f73 100644 --- a/lisp/vc/diff.el +++ b/lisp/vc/diff.el @@ -86,7 +86,7 @@ exists. If NO-ASYNC is non-nil, call diff synchronously. When called interactively with a prefix argument, prompt interactively for diff switches. Otherwise, the switches -specified in `diff-switches' are passed to the diff command." +specified in the variable `diff-switches' are passed to the diff command." (interactive (let* ((newf (if (and buffer-file-name (file-exists-p buffer-file-name)) (read-file-name @@ -114,6 +114,13 @@ specified in `diff-switches' are passed to the diff command." tempfile)) (file-local-copy file-or-buf))) +(defvar diff-use-labels 'check + "Whether `diff-command' understands the \"--label\" option. +Possible values are: + t -- yes, it does + nil -- no, it does not + check -- try to probe whether it does") + (defun diff-no-select (old new &optional switches no-async buf) ;; Noninteractive helper for creating and reverting diff buffers (unless (bufferp new) (setq new (expand-file-name new))) @@ -121,6 +128,11 @@ specified in `diff-switches' are passed to the diff command." (or switches (setq switches diff-switches)) ; If not specified, use default. (unless (listp switches) (setq switches (list switches))) (or buf (setq buf (get-buffer-create "*Diff*"))) + (when (eq 'check diff-use-labels) + (setq diff-use-labels + (with-temp-buffer + (when (ignore-errors (call-process diff-command nil t nil "--help")) + (if (search-backward "--label" nil t) t))))) (let* ((old-alt (diff-file-local-copy old)) (new-alt (diff-file-local-copy new)) (command @@ -130,11 +142,14 @@ specified in `diff-switches' are passed to the diff command." ,@switches ,@(mapcar #'shell-quote-argument (nconc - (when (or old-alt new-alt) - (list "-L" (if (stringp old) - old (prin1-to-string old)) - "-L" (if (stringp new) - new (prin1-to-string new)))) + (and (or old-alt new-alt) + (eq diff-use-labels t) + (list "--label" + (if (stringp old) old + (prin1-to-string old)) + "--label" + (if (stringp new) new + (prin1-to-string new)))) (list (or old-alt old) (or new-alt new))))) " ")) diff --git a/lisp/vc/ediff-diff.el b/lisp/vc/ediff-diff.el index 9ad1b39ac38..b4d986fb036 100644 --- a/lisp/vc/ediff-diff.el +++ b/lisp/vc/ediff-diff.el @@ -453,52 +453,30 @@ one optional arguments, diff-number to refine.") c-prev c-end) ;; else convert lines to points (ediff-with-current-buffer A-buffer - (let ((longlines-mode-val - (if (and (boundp 'longlines-mode) longlines-mode) 1 0))) - ;; we must disable and then restore longlines-mode - (if (eq longlines-mode-val 1) - (longlines-mode 0)) - (goto-char (or a-prev-pt shift-A (point-min))) - (forward-line (- a-begin a-prev)) - (setq a-begin-pt (point)) - (forward-line (- a-end a-begin)) - (setq a-end-pt (point) - a-prev a-end - a-prev-pt a-end-pt) - (if (eq longlines-mode-val 1) - (longlines-mode longlines-mode-val)) - )) + (goto-char (or a-prev-pt shift-A (point-min))) + (forward-line (- a-begin a-prev)) + (setq a-begin-pt (point)) + (forward-line (- a-end a-begin)) + (setq a-end-pt (point) + a-prev a-end + a-prev-pt a-end-pt)) (ediff-with-current-buffer B-buffer - (let ((longlines-mode-val - (if (and (boundp 'longlines-mode) longlines-mode) 1 0))) - (if (eq longlines-mode-val 1) - (longlines-mode 0)) - (goto-char (or b-prev-pt shift-B (point-min))) - (forward-line (- b-begin b-prev)) - (setq b-begin-pt (point)) - (forward-line (- b-end b-begin)) - (setq b-end-pt (point) - b-prev b-end - b-prev-pt b-end-pt) - (if (eq longlines-mode-val 1) - (longlines-mode longlines-mode-val)) - )) + (goto-char (or b-prev-pt shift-B (point-min))) + (forward-line (- b-begin b-prev)) + (setq b-begin-pt (point)) + (forward-line (- b-end b-begin)) + (setq b-end-pt (point) + b-prev b-end + b-prev-pt b-end-pt)) (if (ediff-buffer-live-p C-buffer) (ediff-with-current-buffer C-buffer - (let ((longlines-mode-val - (if (and (boundp 'longlines-mode) longlines-mode) 1 0))) - (if (eq longlines-mode-val 1) - (longlines-mode 0)) - (goto-char (or c-prev-pt (point-min))) - (forward-line (- c-begin c-prev)) - (setq c-begin-pt (point)) - (forward-line (- c-end c-begin)) - (setq c-end-pt (point) - c-prev c-end - c-prev-pt c-end-pt) - (if (eq longlines-mode-val 1) - (longlines-mode longlines-mode-val)) - ))) + (goto-char (or c-prev-pt (point-min))) + (forward-line (- c-begin c-prev)) + (setq c-begin-pt (point)) + (forward-line (- c-end c-begin)) + (setq c-end-pt (point) + c-prev c-end + c-prev-pt c-end-pt))) (setq diff-list (nconc diff-list @@ -1085,65 +1063,36 @@ delimiter regions")) c-prev c-end) ;; else convert lines to points (ediff-with-current-buffer A-buffer - (let ((longlines-mode-val - (if (and (boundp 'longlines-mode) longlines-mode) 1 0))) - ;; we must disable and then restore longlines-mode - (if (eq longlines-mode-val 1) - (longlines-mode 0)) - (goto-char (or a-prev-pt shift-A (point-min))) - (forward-line (- a-begin a-prev)) - (setq a-begin-pt (point)) - (forward-line (- a-end a-begin)) - (setq a-end-pt (point) - a-prev a-end - a-prev-pt a-end-pt) - (if (eq longlines-mode-val 1) - (longlines-mode longlines-mode-val)) - )) + (goto-char (or a-prev-pt shift-A (point-min))) + (forward-line (- a-begin a-prev)) + (setq a-begin-pt (point)) + (forward-line (- a-end a-begin)) + (setq a-end-pt (point) + a-prev a-end + a-prev-pt a-end-pt)) (ediff-with-current-buffer B-buffer - (let ((longlines-mode-val - (if (and (boundp 'longlines-mode) longlines-mode) 1 0))) - (if (eq longlines-mode-val 1) - (longlines-mode 0)) - (goto-char (or b-prev-pt shift-B (point-min))) - (forward-line (- b-begin b-prev)) - (setq b-begin-pt (point)) - (forward-line (- b-end b-begin)) - (setq b-end-pt (point) - b-prev b-end - b-prev-pt b-end-pt) - (if (eq longlines-mode-val 1) - (longlines-mode longlines-mode-val)) - )) + (goto-char (or b-prev-pt shift-B (point-min))) + (forward-line (- b-begin b-prev)) + (setq b-begin-pt (point)) + (forward-line (- b-end b-begin)) + (setq b-end-pt (point) + b-prev b-end + b-prev-pt b-end-pt)) (ediff-with-current-buffer C-buffer - (let ((longlines-mode-val - (if (and (boundp 'longlines-mode) longlines-mode) 1 0))) - (if (eq longlines-mode-val 1) - (longlines-mode 0)) - (goto-char (or c-prev-pt shift-C (point-min))) - (forward-line (- c-begin c-prev)) - (setq c-begin-pt (point)) - (forward-line (- c-end c-begin)) - (setq c-end-pt (point) - c-prev c-end - c-prev-pt c-end-pt) - (if (eq longlines-mode-val 1) - (longlines-mode longlines-mode-val)) - )) + (goto-char (or c-prev-pt shift-C (point-min))) + (forward-line (- c-begin c-prev)) + (setq c-begin-pt (point)) + (forward-line (- c-end c-begin)) + (setq c-end-pt (point) + c-prev c-end + c-prev-pt c-end-pt)) (if (ediff-buffer-live-p anc-buffer) (ediff-with-current-buffer anc-buffer - (let ((longlines-mode-val - (if (and (boundp 'longlines-mode) longlines-mode) 1 0))) - (if (eq longlines-mode-val 1) - (longlines-mode 0)) - (forward-line (- c-or-anc-begin anc-prev)) - (setq anc-begin-pt (point)) - (forward-line (- c-or-anc-end c-or-anc-begin)) - (setq anc-end-pt (point) - anc-prev c-or-anc-end) - (if (eq longlines-mode-val 1) - (longlines-mode longlines-mode-val)) - ))) + (forward-line (- c-or-anc-begin anc-prev)) + (setq anc-begin-pt (point)) + (forward-line (- c-or-anc-end c-or-anc-begin)) + (setq anc-end-pt (point) + anc-prev c-or-anc-end))) (setq diff-list (nconc diff-list diff --git a/lisp/vc/ediff-ptch.el b/lisp/vc/ediff-ptch.el index eccd17e5afe..64f4ee4a6ac 100644 --- a/lisp/vc/ediff-ptch.el +++ b/lisp/vc/ediff-ptch.el @@ -190,15 +190,15 @@ program." ;; We usually come up with two candidates and ediff-file-name-sans-prefix ;; resolves this later. ;; -;; The marker `marker1' delimits the beginning of the corresponding patch and -;; `marker2' does it for the end. +;; The marker `mark1' delimits the beginning of the corresponding patch and +;; `mark2' does it for the end. ;; The result of ediff-map-patch-buffer is a list, which is then assigned ;; to ediff-patch-map. ;; The function returns the number of elements in the list ediff-patch-map (defun ediff-map-patch-buffer (buf) (ediff-with-current-buffer buf (let ((count 0) - (mark1 (move-marker (make-marker) (point-min))) + (mark1 (point-min-marker)) (mark1-end (point-min)) (possible-file-names '("/dev/null" . "/dev/null")) mark2-end mark2 filenames diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el index c72e8e2af18..81146c0c931 100644 --- a/lisp/vc/ediff-util.el +++ b/lisp/vc/ediff-util.el @@ -143,6 +143,7 @@ to invocation.") 'ediff-previous-difference nil)) ;; must come after C-h, or else C-h wipes out backspace's binding in XEmacs (define-key ediff-mode-map [backspace] 'ediff-previous-difference) + (define-key ediff-mode-map [?\S-\ ] 'ediff-previous-difference) (define-key ediff-mode-map "n" 'ediff-next-difference) (define-key ediff-mode-map " " 'ediff-next-difference) (define-key ediff-mode-map "j" 'ediff-jump-to-difference) @@ -786,7 +787,12 @@ Reestablish the default three-window display." (frame-live-p ediff-control-frame) (not ediff-use-long-help-message) (not (ediff-frame-iconified-p ediff-control-frame))) - (raise-frame ediff-control-frame)) + (if (fboundp 'select-frame-set-input-focus) + (select-frame-set-input-focus ediff-control-frame) + (raise-frame ediff-control-frame) + (select-frame ediff-control-frame) + (if (fboundp 'focus-frame) + (focus-frame ediff-control-frame)))) ;; Redisplay whatever buffers are showing, if there is a selected difference (let ((control-frame ediff-control-frame) @@ -3378,10 +3384,18 @@ Without an argument, it saves customized diff argument, if available (set-window-buffer wind cloned-buff) cloned-buff)) -(defun ediff-clone-buffer-for-current-diff-comparison (buff buf-type reg-name) - (let ((cloned-buff (ediff-make-cloned-buffer buff reg-name)) - (reg-start (ediff-get-diff-posn buf-type 'beg)) - (reg-end (ediff-get-diff-posn buf-type 'end))) +(defun ediff-buffer-type (buffer) + (cond ((eq buffer ediff-buffer-A) 'A) + ((eq buffer ediff-buffer-B) 'B) + ((eq buffer ediff-buffer-C) 'C) + ((eq buffer ediff-ancestor-buffer) 'Ancestor) + (t nil))) + +(defun ediff-clone-buffer-for-current-diff-comparison (buff reg-name) + (let* ((cloned-buff (ediff-make-cloned-buffer buff reg-name)) + (buf-type (ediff-buffer-type buff)) + (reg-start (ediff-get-diff-posn buf-type 'beg)) + (reg-end (ediff-get-diff-posn buf-type 'end))) (ediff-with-current-buffer cloned-buff ;; set region to be the current diff region (goto-char reg-start) @@ -3466,7 +3480,7 @@ Without an argument, it saves customized diff argument, if available (defun ediff-inferior-compare-regions () "Compare regions in an active Ediff session. -Like ediff-regions-linewise but is called from under an active Ediff session on +Like `ediff-regions-linewise' but is called from under an active Ediff session on the files that belong to that session. After quitting the session invoked via this function, type C-l to the parent @@ -3555,7 +3569,7 @@ Ediff Control Panel to restore highlighting." (setq bufA (if use-current-diff-p (ediff-clone-buffer-for-current-diff-comparison - bufA 'A "-Region.A-") + bufA "-Region.A-") (ediff-clone-buffer-for-region-comparison bufA "-Region.A-"))) (ediff-with-current-buffer bufA (setq begA (region-beginning) @@ -3570,7 +3584,7 @@ Ediff Control Panel to restore highlighting." (setq bufB (if use-current-diff-p (ediff-clone-buffer-for-current-diff-comparison - bufB 'B "-Region.B-") + bufB "-Region.B-") (ediff-clone-buffer-for-region-comparison bufB "-Region.B-"))) (ediff-with-current-buffer bufB (setq begB (region-beginning) @@ -4010,7 +4024,7 @@ Mail anyway? (y or n) ") (set-buffer ctl-buf)) (setq buffer-name (buffer-name)) (require 'reporter) - (reporter-submit-bug-report "kifer@cs.stonybrook.edu" + (reporter-submit-bug-report "kifer@cs.stonybrook.edu, bug-gnu-emacs@gnu.org" (ediff-version) varlist nil diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index f8e753772e4..dfc7eee81a6 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el @@ -953,13 +953,14 @@ line of MSG." (while (re-search-forward (concat "^" (car header) ":" log-edit-header-contents-regexp) nil t) - (if (eq t (cdr header)) - (setq summary (match-string 1)) - (if (functionp (cdr header)) - (setq res (nconc res (funcall (cdr header) (match-string 1)))) - (push (match-string 1) res) - (push (or (cdr header) (car header)) res))) - (replace-match "" t t))) + (let ((txt (match-string 1))) + (replace-match "" t t) + (if (eq t (cdr header)) + (setq summary txt) + (if (functionp (cdr header)) + (setq res (nconc res (funcall (cdr header) txt))) + (push txt res) + (push (or (cdr header) (car header)) res)))))) ;; Remove header separator if the header is empty. (widen) (goto-char (point-min)) diff --git a/lisp/vc/pcvs.el b/lisp/vc/pcvs.el index 52dc7edfa2d..208b93d9670 100644 --- a/lisp/vc/pcvs.el +++ b/lisp/vc/pcvs.el @@ -856,7 +856,8 @@ the problem." (defun cvs-cleanup-collection (c rm-handled rm-dirs rm-msgs) "Remove undesired entries. C is the collection -RM-HANDLED if non-nil means remove handled entries. +RM-HANDLED if non-nil means remove handled entries (if file is currently + visited, only remove if value is `all'). RM-DIRS behaves like `cvs-auto-remove-directories'. RM-MSGS if non-nil means remove messages." (let (last-fi first-dir (rerun t)) @@ -870,16 +871,17 @@ RM-MSGS if non-nil means remove messages." (subtype (cvs-fileinfo->subtype fi)) (keep (pcase type - ;; remove temp messages and keep the others + ;; Remove temp messages and keep the others. (`MESSAGE (not (or rm-msgs (eq subtype 'TEMP)))) - ;; remove entries + ;; Remove dead entries. (`DEAD nil) - ;; handled also? + ;; Handled also? (`UP-TO-DATE - (if (find-buffer-visiting (cvs-fileinfo->full-name fi)) - t - (not rm-handled))) - ;; keep the rest + (not + (if (find-buffer-visiting (cvs-fileinfo->full-name fi)) + (eq rm-handled 'all) + rm-handled))) + ;; Keep the rest. (_ (not (run-hook-with-args-until-success 'cvs-cleanup-functions fi)))))) @@ -2121,7 +2123,7 @@ if you are convinced that the process that created the lock is dead." Empty directories are removed." (interactive) (cvs-cleanup-collection cvs-cookies - t (or cvs-auto-remove-directories 'handled) t)) + 'all (or cvs-auto-remove-directories 'handled) t)) (defun-cvs-mode cvs-mode-acknowledge () diff --git a/lisp/vc/vc-arch.el b/lisp/vc/vc-arch.el index 3dbaae52b37..52609457ebc 100644 --- a/lisp/vc/vc-arch.el +++ b/lisp/vc/vc-arch.el @@ -101,7 +101,7 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches." ;;;###autoload (defun vc-arch-registered (file) ;;;###autoload (if (vc-find-root file "{arch}/=tagging-method") ;;;###autoload (progn -;;;###autoload (load "vc-arch") +;;;###autoload (load "vc-arch" nil t) ;;;###autoload (vc-arch-registered file)))) (defun vc-arch-add-tagline () diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el index f436d300089..4a08403c93e 100644 --- a/lisp/vc/vc-bzr.el +++ b/lisp/vc/vc-bzr.el @@ -291,7 +291,7 @@ in the repository root directory of FILE." ;;;###autoload (defun vc-bzr-registered (file) ;;;###autoload (if (vc-find-root file vc-bzr-admin-checkout-format-file) ;;;###autoload (progn -;;;###autoload (load "vc-bzr") +;;;###autoload (load "vc-bzr" nil t) ;;;###autoload (vc-bzr-registered file)))) (defun vc-bzr-registered (file) @@ -620,15 +620,24 @@ or a superior directory.") (declare-function log-edit-extract-headers "log-edit" (headers string)) +(defun vc-bzr--sanitize-header (arg) + ;; Newlines in --fixes (and probably other fields as well) trigger a nasty + ;; Bazaar bug; see https://bugs.launchpad.net/bzr/+bug/1094180. + (lambda (str) (list arg + (replace-regexp-in-string "\\`[ \t]+\\|[ \t]+\\'" + "" (replace-regexp-in-string + "\n[ \t]?" " " str))))) + (defun vc-bzr-checkin (files rev comment) "Check FILES in to bzr with log message COMMENT. REV non-nil gets an error." (if rev (error "Can't check in a specific revision with bzr")) - (apply 'vc-bzr-command "commit" nil 0 - files (cons "-m" (log-edit-extract-headers '(("Author" . "--author") - ("Date" . "--commit-time") - ("Fixes" . "--fixes")) - comment)))) + (apply 'vc-bzr-command "commit" nil 0 files + (cons "-m" (log-edit-extract-headers + `(("Author" . ,(vc-bzr--sanitize-header "--author")) + ("Date" . ,(vc-bzr--sanitize-header "--commit-time")) + ("Fixes" . ,(vc-bzr--sanitize-header "--fixes"))) + comment)))) (defun vc-bzr-find-revision (file rev buffer) "Fetch revision REV of file FILE and put it into BUFFER." @@ -644,7 +653,7 @@ REV non-nil gets an error." (defun vc-bzr-revert (file &optional contents-done) (unless contents-done - (with-temp-buffer (vc-bzr-command "revert" t 0 file)))) + (with-temp-buffer (vc-bzr-command "revert" t 0 file "--no-backup")))) (defvar log-view-message-re) (defvar log-view-file-re) @@ -685,7 +694,10 @@ REV non-nil gets an error." ("^ *timestamp: \\(.*\\)" (1 'change-log-date-face))))))) (defun vc-bzr-print-log (files buffer &optional shortlog start-revision limit) - "Get bzr change log for FILES into specified BUFFER." + "Print commit log associated with FILES into specified BUFFER. +If SHORTLOG is non-nil, use --line 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) @@ -698,8 +710,33 @@ REV non-nil gets an error." (apply 'vc-bzr-command "log" buffer 'async files (append (when shortlog '("--line")) - (when start-revision (list (format "-r..%s" start-revision))) + ;; The extra complications here when start-revision and limit + ;; are set are due to bzr log's --forward argument, which + ;; could be enabled via an alias in bazaar.conf. + ;; Svn, for example, does not have this problem, because + ;; it doesn't have --forward. Instead, you can use + ;; svn --log -r HEAD:0 or -r 0:HEAD as you prefer. + ;; Bzr, however, insists in -r X..Y that X come before Y. + (if start-revision + (list (format + (if (and limit (= limit 1)) + ;; This means we don't have to use --no-aliases. + ;; Is -c any different to -r in this case? + "-r%s" + "-r..%s") start-revision))) (when limit (list "-l" (format "%s" limit))) + ;; There is no sensible way to combine --limit and --forward, + ;; and it breaks the meaning of START-REVISION as the + ;; _newest_ revision. See bug#14168. + ;; Eg bzr log --forward -r ..100 --limit 50 prints + ;; revisions 1-50 rather than 50-100. There + ;; seems no way in general to get bzr to print revisions + ;; 50-100 in --forward order in that case. + ;; FIXME There may be other alias stuff we want to keep. + ;; Is there a way to just suppress --forward? + ;; As of 2013/4 the only caller uses limit = 1, so it does + ;; not matter much. + (and start-revision limit (> limit 1) '("--no-aliases")) (if (stringp vc-bzr-log-switches) (list vc-bzr-log-switches) vc-bzr-log-switches))))) diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el index d90596baca0..7a8f8107509 100644 --- a/lisp/vc/vc-cvs.el +++ b/lisp/vc/vc-cvs.el @@ -198,7 +198,7 @@ See also variable `vc-cvs-sticky-date-format-string'." ;;;###autoload "Return non-nil if file F is registered with CVS." ;;;###autoload (when (file-readable-p (expand-file-name ;;;###autoload "CVS/Entries" (file-name-directory f))) -;;;###autoload (load "vc-cvs") +;;;###autoload (load "vc-cvs" nil t) ;;;###autoload (vc-cvs-registered f))) (defun vc-cvs-registered (file) @@ -503,7 +503,8 @@ Will fail unless you have administrative privileges on the repo." (declare-function vc-rcs-print-log-cleanup "vc-rcs" ()) (defun vc-cvs-print-log (files buffer &optional _shortlog _start-revision limit) - "Get change logs associated with FILES." + "Print commit log associated with FILES into specified BUFFER. +Remaining arguments are ignored." (require 'vc-rcs) ;; It's just the catenation of the individual logs. (vc-cvs-command @@ -562,14 +563,13 @@ Will fail unless you have administrative privileges on the repo." (defconst vc-cvs-annotate-first-line-re "^[0-9]") -(defun vc-cvs-annotate-process-filter (process string) +(defun vc-cvs-annotate-process-filter (filter process string) (setq string (concat (process-get process 'output) string)) (if (not (string-match vc-cvs-annotate-first-line-re string)) ;; Still waiting for the first real line. (process-put process 'output string) - (let ((vc-filter (process-get process 'vc-filter))) - (set-process-filter process vc-filter) - (funcall vc-filter process (substring string (match-beginning 0)))))) + (remove-function (process-filter process) #'vc-cvs-annotate-process-filter) + (funcall filter process (substring string (match-beginning 0))))) (defun vc-cvs-annotate-command (file buffer &optional revision) "Execute \"cvs annotate\" on FILE, inserting the contents in BUFFER. @@ -583,9 +583,8 @@ Optional arg REVISION is a revision to annotate from." (let ((proc (get-buffer-process buffer))) (if proc ;; If running asynchronously, use a process filter. - (progn - (process-put proc 'vc-filter (process-filter proc)) - (set-process-filter proc 'vc-cvs-annotate-process-filter)) + (add-function :around (process-filter proc) + #'vc-cvs-annotate-process-filter) (with-current-buffer buffer (goto-char (point-min)) (re-search-forward vc-cvs-annotate-first-line-re) diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el index e3b9941fe18..d10e3934680 100644 --- a/lisp/vc/vc-dir.el +++ b/lisp/vc/vc-dir.el @@ -930,6 +930,8 @@ If it is a file, return the corresponding cons for the file itself." (defvar use-vc-backend) ;; dynamically bound +;; Autoload cookie needed by desktop.el. +;;;###autoload (define-derived-mode vc-dir-mode special-mode "VC dir" "Major mode for VC directory buffers. Marking/Unmarking key bindings and actions: @@ -967,6 +969,8 @@ the *vc-dir* buffer. \\{vc-dir-mode-map}" (set (make-local-variable 'vc-dir-backend) use-vc-backend) + (set (make-local-variable 'desktop-save-buffer) + 'vc-dir-desktop-buffer-misc-data) (setq buffer-read-only t) (when (boundp 'tool-bar-map) (set (make-local-variable 'tool-bar-map) vc-dir-tool-bar-map)) @@ -1288,6 +1292,31 @@ These are the commands available for use in the file status buffer: "Default absence of extra information returned for a file." nil) + +;;; Support for desktop.el (adapted from what dired.el does). + +(declare-function desktop-file-name "desktop" (filename dirname)) + +(defun vc-dir-desktop-buffer-misc-data (dirname) + "Auxiliary information to be saved in desktop file." + (cons (desktop-file-name default-directory dirname) vc-dir-backend)) + +(defun vc-dir-restore-desktop-buffer (_filename _buffername misc-data) + "Restore a `vc-dir' buffer specified in a desktop file." + (let ((dir (car misc-data)) + (backend (cdr misc-data))) + (if (file-directory-p dir) + (progn + (vc-dir dir backend) + (current-buffer)) + (message "Desktop: Directory %s no longer exists." dir) + (when desktop-missing-file-warning (sit-for 1)) + nil))) + +(add-to-list 'desktop-buffer-mode-handlers + '(vc-dir-mode . vc-dir-restore-desktop-buffer)) + + (provide 'vc-dir) ;;; vc-dir.el ends here diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el index b03619e03d9..309cf50404c 100644 --- a/lisp/vc/vc-dispatcher.el +++ b/lisp/vc/vc-dispatcher.el @@ -1,4 +1,4 @@ -;;; vc-dispatcher.el -- generic command-dispatcher facility. +;;; vc-dispatcher.el -- generic command-dispatcher facility. -*- lexical-binding: t -*- ;; Copyright (C) 2008-2013 Free Software Foundation, Inc. @@ -182,32 +182,29 @@ Another is that undo information is not kept." (defvar vc-sentinel-movepoint) ;Dynamically scoped. -(defun vc-process-sentinel (p s) - (let ((previous (process-get p 'vc-previous-sentinel)) - (buf (process-buffer p))) +(defun vc--process-sentinel (p code) + (let ((buf (process-buffer p))) ;; Impatient users sometime kill "slow" buffers; check liveness ;; to avoid "error in process sentinel: Selecting deleted buffer". (when (buffer-live-p buf) - (when previous (funcall previous p s)) (with-current-buffer buf (setq mode-line-process (let ((status (process-status p))) ;; Leave mode-line uncluttered, normally. (unless (eq 'exit status) (format " (%s)" status)))) - (let (vc-sentinel-movepoint) + (let (vc-sentinel-movepoint + (m (process-mark p))) ;; Normally, we want async code such as sentinels to not move point. (save-excursion - (goto-char (process-mark p)) - (let ((cmds (process-get p 'vc-sentinel-commands))) - (process-put p 'vc-sentinel-commands nil) - (dolist (cmd cmds) + (goto-char m) ;; Each sentinel may move point and the next one should be run ;; at that new point. We could get the same result by having ;; each sentinel read&set process-mark, but since `cmd' needs ;; to work both for async and sync processes, this would be ;; difficult to achieve. - (vc-exec-after cmd)))) + (vc-exec-after code) + (move-marker m (point))) ;; But sometimes the sentinels really want to move point. (when vc-sentinel-movepoint (let ((win (get-buffer-window (current-buffer) 0))) @@ -226,7 +223,9 @@ Another is that undo information is not kept." (defun vc-exec-after (code) "Eval CODE when the current buffer's process is done. If the current buffer has no process, just evaluate CODE. -Else, add CODE to the process' sentinel." +Else, add CODE to the process' sentinel. +CODE can be either a function of no arguments, or an expression +to evaluate." (let ((proc (get-buffer-process (current-buffer)))) (cond ;; If there's no background process, just execute the code. @@ -237,20 +236,14 @@ Else, add CODE to the process' sentinel." ((or (null proc) (eq (process-status proc) 'exit)) ;; Make sure we've read the process's output before going further. (when proc (accept-process-output proc)) - (eval code)) + (if (functionp code) (funcall code) (eval code))) ;; If a process is running, add CODE to the sentinel ((eq (process-status proc) 'run) (vc-set-mode-line-busy-indicator) - (let ((previous (process-sentinel proc))) - (unless (eq previous 'vc-process-sentinel) - (process-put proc 'vc-previous-sentinel previous)) - (set-process-sentinel proc 'vc-process-sentinel)) - (process-put proc 'vc-sentinel-commands - ;; We keep the code fragments in the order given - ;; so that vc-diff-finish's message shows up in - ;; the presence of non-nil vc-command-messages. - (append (process-get proc 'vc-sentinel-commands) - (list code)))) + (letrec ((fun (lambda (p _msg) + (remove-function (process-sentinel p) fun) + (vc--process-sentinel p code)))) + (add-function :after (process-sentinel proc) fun))) (t (error "Unexpected process state")))) nil) @@ -329,7 +322,9 @@ case, and the process object in the asynchronous case." command squeezed)))) (when vc-command-messages (message "Running %s in background..." full-command)) - ;;(set-process-sentinel proc (lambda (p msg) (delete-process p))) + ;; Get rid of the default message insertion, in case we don't + ;; set a sentinel explicitly. + (set-process-sentinel proc #'ignore) (set-process-filter proc 'vc-process-filter) (setq status proc) (when vc-command-messages @@ -386,6 +381,8 @@ Display the buffer in some window, but don't select it." (set-window-start window new-window-start)) buffer)) +(defvar compilation-error-regexp-alist) + (defun vc-compilation-mode (backend) "Setup `compilation-mode' after with the appropriate `compilation-error-regexp-alist'." (let* ((error-regexp-alist @@ -477,7 +474,7 @@ Used by `vc-restore-buffer-context' to later restore the context." (vc-position-context (mark-marker)))) ;; Make the right thing happen in transient-mark-mode. (mark-active nil)) - (list point-context mark-context nil))) + (list point-context mark-context))) (defun vc-restore-buffer-context (context) "Restore point/mark, and reparse any affected compilation buffers. @@ -516,6 +513,8 @@ ARG and NO-CONFIRM are passed on to `revert-buffer'." (make-variable-buffer-local 'vc-mode-line-hook) (put 'vc-mode-line-hook 'permanent-local t) +(defvar view-old-buffer-read-only) + (defun vc-resynch-window (file &optional keep noquery reset-vc-info) "If FILE is in the current buffer, either revert or unvisit it. The choice between revert (to see expanded keywords) and unvisit diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index fb39f1baec7..06474cb4604 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -168,7 +168,7 @@ matching the resulting Git log output, and KEYWORDS is a list of ;;;###autoload "Return non-nil if FILE is registered with git." ;;;###autoload (if (vc-find-root file ".git") ; Short cut. ;;;###autoload (progn -;;;###autoload (load "vc-git") +;;;###autoload (load "vc-git" nil t) ;;;###autoload (vc-git-registered file)))) (defun vc-git-registered (file) @@ -732,9 +732,11 @@ This prompts for a branch to merge from." ;;; HISTORY FUNCTIONS (defun vc-git-print-log (files buffer &optional shortlog start-revision limit) - "Get change log associated with FILES. -Note that using SHORTLOG requires at least Git version 1.5.6, -for the --graph option." + "Print commit log associated with FILES into specified BUFFER. +If SHORTLOG is non-nil, use a short format based on `vc-git-root-log-format'. +\(This requires at least Git version 1.5.6, for the --graph option.) +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." (let ((coding-system-for-read vc-git-commits-coding-system)) ;; `vc-do-command' creates the buffer, but we need it before running ;; the command. @@ -1148,7 +1150,7 @@ This command shares argument histories with \\[rgrep] and \\[grep]." The difference to vc-do-command is that this function always invokes `vc-git-program'." (apply 'vc-do-command (or buffer "*vc*") okstatus vc-git-program - file-or-list flags)) + file-or-list (cons "--no-pager" flags))) (defun vc-git--empty-db-p () "Check if the git db is empty (no commit done yet)." diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index 18667117714..feec015e52a 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -93,7 +93,7 @@ ;; - 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 @@ -152,7 +152,7 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches." (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 @@ -176,7 +176,7 @@ highlighting the Log View buffer." ;;;###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 @@ -246,7 +246,10 @@ highlighting the Log View buffer." :group 'vc-hg) (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) @@ -257,7 +260,7 @@ highlighting the Log View 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))))) @@ -357,7 +360,7 @@ Optional arg REVISION is a revision to annotate from." ;;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) @@ -384,7 +387,7 @@ Optional arg REVISION is a revision to annotate from." (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))))) @@ -464,6 +467,35 @@ REV is the revision to check out into WORKFILE." (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))) diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index dd87fb6de79..5c8a4515b7e 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -703,19 +703,21 @@ Before doing that, check if there are any old backups and get rid of them." ;; the state to 'edited and redisplay the mode line. (let* ((file buffer-file-name) (backend (vc-backend file))) - (and backend - (or (and (equal (vc-file-getprop file 'vc-checkout-time) - (nth 5 (file-attributes file))) - ;; File has been saved in the same second in which - ;; it was checked out. Clear the checkout-time - ;; to avoid confusion. - (vc-file-setprop file 'vc-checkout-time nil)) - t) - (eq (vc-checkout-model backend (list file)) 'implicit) - (vc-state-refresh file backend) - (vc-mode-line file backend)) - ;; Try to avoid unnecessary work, a *vc-dir* buffer is - ;; present if this is true. + (cond + ((null backend)) + ((eq (vc-checkout-model backend (list file)) 'implicit) + ;; If the file was saved in the same second in which it was + ;; checked out, clear the checkout-time to avoid confusion. + (if (equal (vc-file-getprop file 'vc-checkout-time) + (nth 5 (file-attributes file))) + (vc-file-setprop file 'vc-checkout-time nil)) + (if (vc-state-refresh file backend) + (vc-mode-line file backend))) + ;; If we saved an unlocked file on a locking based VCS, that + ;; file is not longer up-to-date. + ((eq (vc-file-getprop file 'vc-state) 'up-to-date) + (vc-file-setprop file 'vc-state nil))) + ;; Resynch *vc-dir* buffers, if any are present. (when vc-dir-buffers (vc-dir-resynch-file file)))) @@ -856,13 +858,23 @@ current, and kill the buffer that visits the link." (set (make-local-variable 'backup-inhibited) t)) ;; Let the backend setup any buffer-local things he needs. (vc-call-backend backend 'find-file-hook)) - ((let ((link-type (and (not (equal buffer-file-name buffer-file-truename)) - (vc-backend buffer-file-truename)))) + ((let* ((truename (and buffer-file-truename + (expand-file-name buffer-file-truename))) + (link-type (and truename + (not (equal buffer-file-name truename)) + (vc-backend truename)))) (cond ((not link-type) nil) ;Nothing to do. ((eq vc-follow-symlinks nil) (message "Warning: symbolic link to %s-controlled source file" link-type)) ((or (not (eq vc-follow-symlinks 'ask)) + ;; Assume we cannot ask, default to yes. + noninteractive + ;; Copied from server-start. Seems like there should + ;; be a better way to ask "can we get user input?"... + (and (daemonp) + (null (cdr (frame-list))) + (eq (selected-frame) terminal-frame)) ;; If we already visited this file by following ;; the link, don't ask again if we try to visit ;; it again. GUD does that, and repeated questions @@ -973,6 +985,10 @@ current, and kill the buffer that visits the link." ")) (bindings--define-key map [undo] '(menu-item "Undo Last Check-In" vc-rollback + :enable (let ((backend (if buffer-file-name + (vc-backend buffer-file-name)))) + (or (not backend) + (vc-find-backend-function backend 'rollback))) :help "Remove the most recent changeset committed to the repository")) (bindings--define-key map [vc-revert] '(menu-item "Revert to Base Version" vc-revert diff --git a/lisp/vc/vc-mtn.el b/lisp/vc/vc-mtn.el index f2569e2145d..fbfd89561b7 100644 --- a/lisp/vc/vc-mtn.el +++ b/lisp/vc/vc-mtn.el @@ -72,7 +72,7 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches." ;;;###autoload (defun vc-mtn-registered (file) ;;;###autoload (if (vc-find-root file vc-mtn-admin-format) ;;;###autoload (progn -;;;###autoload (load "vc-mtn") +;;;###autoload (load "vc-mtn" nil t) ;;;###autoload (vc-mtn-registered file)))) (defun vc-mtn-revision-granularity () 'repository) @@ -202,6 +202,10 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches." ;; ) (defun vc-mtn-print-log (files buffer &optional _shortlog start-revision limit) + "Print commit logs associated with FILES into specified BUFFER. +_SHORTLOG is ignored. +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." (apply 'vc-mtn-command buffer 0 files "log" (append (when start-revision (list "--from" (format "%s" start-revision))) diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el index 40d8acb7e07..0a2fc804e6d 100644 --- a/lisp/vc/vc-rcs.el +++ b/lisp/vc/vc-rcs.el @@ -567,10 +567,14 @@ directory the operation is applied to all registered files beneath it." (when (looking-at "[\b\t\n\v\f\r ]+") (delete-char (- (match-end 0) (match-beginning 0)))))) -(defun vc-rcs-print-log (files buffer &optional shortlog start-revision-ignored limit) - "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))) +(defun vc-rcs-print-log (files buffer &optional shortlog + start-revision-ignored limit) + "Print commit log associated with FILES into specified BUFFER. +Remaining arguments are ignored. +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))) (with-current-buffer (or buffer "*vc*") (vc-rcs-print-log-cleanup)) (when limit 'limit-unsupported)) diff --git a/lisp/vc/vc-sccs.el b/lisp/vc/vc-sccs.el index bfbe42222e9..d3cf650ddf9 100644 --- a/lisp/vc/vc-sccs.el +++ b/lisp/vc/vc-sccs.el @@ -350,7 +350,8 @@ revert all subfiles." ;;; (defun vc-sccs-print-log (files buffer &optional shortlog start-revision-ignored limit) - "Get change log associated with FILES." + "Print commit log associated with FILES into specified BUFFER. +Remaining arguments are ignored." (setq files (vc-expand-dirs files)) (vc-sccs-do-command buffer 0 "prs" (mapcar 'vc-name files)) (when limit 'limit-unsupported)) diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el index 2899a5e8737..a94bf0d6117 100644 --- a/lisp/vc/vc-svn.el +++ b/lisp/vc/vc-svn.el @@ -50,14 +50,21 @@ :type 'string :group 'vc-svn) -(defcustom vc-svn-global-switches nil - "Global switches to pass to any SVN command." +;; Might be nice if svn defaulted to non-interactive if stdin not tty. +;; http://svn.haxx.se/dev/archive-2008-05/0762.shtml +;; http://svn.haxx.se/dev/archive-2009-04/0094.shtml +;; Maybe newer ones do? +(defcustom vc-svn-global-switches (unless (eq system-type 'darwin) ; bug#13513 + '("--non-interactive")) + "Global switches to pass to any SVN command. +The option \"--non-interactive\" is often needed to prevent SVN +hanging while prompting for authorization." :type '(choice (const :tag "None" nil) (string :tag "Argument String") (repeat :tag "Argument List" :value ("") string)) - :version "22.1" + :version "24.4" :group 'vc-svn) (defcustom vc-svn-register-switches nil @@ -123,7 +130,7 @@ If you want to force an empty list of arguments, use t." ;;;###autoload "_svn") ;;;###autoload (t ".svn")))) ;;;###autoload (when (vc-find-root f admin-dir) -;;;###autoload (load "vc-svn") +;;;###autoload (load "vc-svn" nil t) ;;;###autoload (vc-svn-registered f)))) (defun vc-svn-registered (file) @@ -155,9 +162,24 @@ If you want to force an empty list of arguments, use t." (vc-svn-command t 0 file "status" (if localp "-v" "-u")) (vc-svn-parse-status file)))) +;; NB this does not handle svn properties, which can be changed +;; without changing the file timestamp. +;; Note that unlike vc-cvs-state-heuristic, this is not called from +;; vc-svn-state. AFAICS, it is only called from vc-state-refresh via +;; vc-after-save (bug#7850). Therefore the fact that it ignores +;; properties is irrelevant. If you want to make vc-svn-state call +;; this, it should be extended to handle svn properties. (defun vc-svn-state-heuristic (file) "SVN-specific state heuristic." - (vc-svn-state file 'local)) + ;; If the file has not changed since checkout, consider it `up-to-date'. + ;; Otherwise consider it `edited'. Copied from vc-cvs-state-heuristic. + (let ((checkout-time (vc-file-getprop file 'vc-checkout-time)) + (lastmod (nth 5 (file-attributes file)))) + (cond + ((equal checkout-time lastmod) 'up-to-date) + ((string= (vc-working-revision file) "0") 'added) + ((null checkout-time) 'unregistered) + (t 'edited)))) ;; FIXME it would be better not to have the "remote" argument, ;; but to distinguish the two output formats based on content. @@ -472,7 +494,10 @@ or svn+ssh://." (set (make-local-variable 'log-view-per-file-logs) nil)) (defun vc-svn-print-log (files buffer &optional shortlog start-revision limit) - "Get change log(s) associated with FILES." + "Print commit log associated with FILES into specified BUFFER. +SHORTLOG is ignored. +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." (save-current-buffer (vc-setup-buffer buffer) (let ((inhibit-read-only t)) @@ -490,7 +515,7 @@ or svn+ssh://." (append (list (if start-revision - (format "-r%s" start-revision) + (format "-r%s:1" start-revision) ;; By default Subversion only shows the log up to the ;; working revision, whereas we also want the log of the ;; subsequent commits. At least that's what the @@ -585,19 +610,11 @@ NAME is assumed to be a URL." (defun vc-svn-command (buffer okstatus file-or-list &rest flags) "A wrapper around `vc-do-command' for use in vc-svn.el. The difference to vc-do-command is that this function always invokes `svn', -and that it passes \"--non-interactive\" and `vc-svn-global-switches' to -it before FLAGS." - ;; Might be nice if svn defaulted to non-interactive if stdin not tty. - ;; http://svn.haxx.se/dev/archive-2008-05/0762.shtml - ;; http://svn.haxx.se/dev/archive-2009-04/0094.shtml - ;; Maybe newer ones do? - (or (member "--non-interactive" - (setq flags (if (stringp vc-svn-global-switches) - (cons vc-svn-global-switches flags) - (append vc-svn-global-switches flags)))) - (setq flags (cons "--non-interactive" flags))) +and that it passes `vc-svn-global-switches' to it before FLAGS." (apply 'vc-do-command (or buffer "*vc*") okstatus vc-svn-program file-or-list - flags)) + (if (stringp vc-svn-global-switches) + (cons vc-svn-global-switches flags) + (append vc-svn-global-switches flags)))) (defun vc-svn-repository-hostname (dirname) (with-temp-buffer diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 35c15f1721d..5e1d27c0ea3 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -356,9 +356,11 @@ ;; If LIMIT is true insert only insert LIMIT log entries. If the ;; backend does not support limiting the number of entries to show ;; it should return `limit-unsupported'. -;; If START-REVISION is given, then show the log starting from the -;; revision. At this point START-REVISION is only required to work -;; in conjunction with LIMIT = 1. +;; If START-REVISION is given, then show the log starting from that +;; revision ("starting" in the sense of it being the _newest_ +;; revision shown, rather than the working revision, which is normally +;; the case). Not all backends support this. At present, this is +;; only ever used with LIMIT = 1 (by vc-annotate-show-log-revision-at-line). ;; ;; * log-outgoing (backend remote-location) ;; @@ -659,6 +661,10 @@ (eval-when-compile (require 'dired)) +(declare-function dired-get-filename "dired" (&optional localp noerror)) +(declare-function dired-move-to-filename "dired" (&optional err eol)) +(declare-function dired-marker-regexp "dired" ()) + (unless (assoc 'vc-parent-buffer minor-mode-alist) (setq minor-mode-alist (cons '(vc-parent-buffer vc-parent-buffer-name) @@ -1072,7 +1078,16 @@ For old-style locking-based version control systems, like RCS: ;; among all the `files'. (model (nth 4 vc-fileset))) - ;; Do the right thing + ;; If a buffer has unsaved changes, a checkout would discard those + ;; changes, so treat the buffer as having unlocked changes. + (when (and (not (eq model 'implicit)) (eq state 'up-to-date)) + (dolist (file files) + (let ((buffer (get-file-buffer file))) + (and buffer + (buffer-modified-p buffer) + (setq state 'unlocked-changes))))) + + ;; Do the right thing. (cond ((eq state 'missing) (error "Fileset files are missing, so cannot be operated on")) @@ -1271,12 +1286,10 @@ first backend that could register the file is used." ;; many VCS allow that as well. (dolist (fname files) (let ((bname (get-file-buffer fname))) - (unless fname (setq fname buffer-file-name)) - (when (vc-backend fname) - (if (vc-registered fname) - (error "This file is already registered") - (unless (y-or-n-p "Previous master file has vanished. Make a new one? ") - (error "Aborted")))) + (unless fname + (setq fname buffer-file-name)) + (when (vc-call-backend backend 'registered fname) + (error "This file is already registered")) ;; Watch out for new buffers of size 0: the corresponding file ;; does not exist yet, even though buffer-modified-p is nil. (when bname @@ -2073,6 +2086,11 @@ Not all VC backends support short logs!") (defvar log-view-vc-fileset) (defun vc-print-log-setup-buttons (working-revision is-start-revision limit pl-return) + "Insert at the end of the current buffer buttons to show more log entries. +In the new log, leave point at WORKING-REVISION (if non-nil). +LIMIT is the number of entries currently shown. +Does nothing if IS-START-REVISION is non-nil, or if LIMIT is nil, +or if PL-RETURN is 'limit-unsupported." (when (and limit (not (eq 'limit-unsupported pl-return)) (not is-start-revision)) (goto-char (point-max)) @@ -2093,6 +2111,14 @@ Not all VC backends support short logs!") (defun vc-print-log-internal (backend files working-revision &optional is-start-revision limit) + "For specified BACKEND and FILES, show the VC log. +Leave point at WORKING-REVISION, if it is non-nil. +If IS-START-REVISION is non-nil, start the log from WORKING-REVISION +\(not all backends support this); i.e., show only WORKING-REVISION and +earlier revisions. Show up to LIMIT entries (non-nil means unlimited)." + ;; As of 2013/04 the only thing that passes IS-START-REVISION non-nil + ;; is vc-annotate-show-log-revision-at-line, which sets LIMIT = 1. + ;; 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. @@ -2178,7 +2204,7 @@ WORKING-REVISION and LIMIT." (interactive (cond (current-prefix-arg - (let ((rev (read-from-minibuffer "Log from revision (default: last revision): " nil + (let ((rev (read-from-minibuffer "Leave point at revision (default: last revision): " nil nil nil nil)) (lim (string-to-number (read-from-minibuffer @@ -2556,8 +2582,12 @@ backend to NEW-BACKEND, and unregister FILE from the current backend. ;;;###autoload (defun vc-delete-file (file) - "Delete file and mark it as such in the version control system." - (interactive "fVC delete file: ") + "Delete file and mark it as such in the version control system. +If called interactively, read FILE, defaulting to the current +buffer's file name if it's under version control." + (interactive (list (read-file-name "VC delete file: " nil + (when (vc-backend buffer-file-name) + buffer-file-name) t))) (setq file (expand-file-name file)) (let ((buf (get-file-buffer file)) (backend (vc-backend file))) @@ -2595,8 +2625,13 @@ backend to NEW-BACKEND, and unregister FILE from the current backend. ;;;###autoload (defun vc-rename-file (old new) - "Rename file OLD to NEW in both work area and repository." - (interactive "fVC rename file: \nFRename to: ") + "Rename file OLD to NEW in both work area and repository. +If called interactively, read OLD and NEW, defaulting OLD to the +current buffer's file name if it's under version control." + (interactive (list (read-file-name "VC rename file: " nil + (when (vc-backend buffer-file-name) + buffer-file-name) t) + (read-file-name "Rename to: "))) ;; in CL I would have said (setq new (merge-pathnames new old)) (let ((old-base (file-name-nondirectory old))) (when (and (not (string= "" old-base)) @@ -2645,14 +2680,11 @@ log entries should be gathered." (cond ((consp current-prefix-arg) ;C-u (list buffer-file-name)) (current-prefix-arg ;Numeric argument. - (let ((files nil) - (buffers (buffer-list)) - file) - (while buffers - (setq file (buffer-file-name (car buffers))) - (and file (vc-backend file) - (setq files (cons file files))) - (setq buffers (cdr buffers))) + (let ((files nil)) + (dolist (buffer (buffer-list)) + (let ((file (buffer-file-name buffer))) + (and file (vc-backend file) + (setq files (cons file files))))) files)) (t ;; Don't supply any filenames to backend; this means |