Minor declare-function improvement
[emacs.git] / lisp / vc / vc-svn.el
Commit [+]AuthorDateLineData
9c750eba Stefan Monnier2013-09-04 17:09:42 -04001;;; vc-svn.el --- non-resident support for Subversion version-control -*- lexical-binding:t -*-
1fd3454a Stefan Monnier2003-05-05 15:42:27 +00002
7e09ef09 Paul Eggert2015-01-01 14:26:41 -08003;; Copyright (C) 2003-2015 Free Software Foundation, Inc.
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +00004
5;; Author: FSF (see vc.el for full credits)
6;; Maintainer: Stefan Monnier <monnier@gnu.org>
bd78fa1d Chong Yidong2010-08-29 12:17:13 -04007;; Package: vc
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +00008
9;; This file is part of GNU Emacs.
10
eb3fa2cf Glenn Morris2008-05-06 08:06:51 +000011;; GNU Emacs is free software: you can redistribute it and/or modify
ab882ed2 Glenn Morris2014-12-01 16:32:04 -050012;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
Glenn Morris2008-05-06 08:06:51 +000013;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +000015
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
eb3fa2cf Glenn Morris2008-05-06 08:06:51 +000022;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +000023
24;;; Commentary:
25
f9914e54
ER
Eric S. Raymond2007-10-09 16:54:40 +000026;; Sync'd with Subversion's vc-svn.el as of revision 5801. but this version
27;; has been extensively modified since to handle filesets.
1fd3454a Stefan Monnier2003-05-05 15:42:27 +000028
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +000029;;; Code:
30
31(eval-when-compile
32 (require 'vc))
33
8228a275
MH
Mark A. Hershberger2010-02-05 14:20:17 -050034;; Clear up the cache to force vc-call to check again and discover
35;; new functions when we reload this file.
36(put 'SVN 'vc-functions nil)
37
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +000038;;;
39;;; Customization options
40;;;
41
67b0de11
CY
Chong Yidong2012-02-25 12:29:09 +080042(defgroup vc-svn nil
43 "VC Subversion (svn) backend."
44 :version "24.1"
45 :group 'vc)
46
f9d5dc48
GM
Glenn Morris2008-11-22 03:27:18 +000047;; FIXME there is also svnadmin.
48(defcustom vc-svn-program "svn"
49 "Name of the SVN executable."
50 :type 'string
67b0de11 Chong Yidong2012-02-25 12:29:09 +080051 :group 'vc-svn)
f9d5dc48 Glenn Morris2008-11-22 03:27:18 +000052
31db8c31
GM
Glenn Morris2013-02-10 17:07:05 -080053;; Might be nice if svn defaulted to non-interactive if stdin not tty.
54;; http://svn.haxx.se/dev/archive-2008-05/0762.shtml
55;; http://svn.haxx.se/dev/archive-2009-04/0094.shtml
56;; Maybe newer ones do?
57(defcustom vc-svn-global-switches (unless (eq system-type 'darwin) ; bug#13513
58 '("--non-interactive"))
59 "Global switches to pass to any SVN command.
60The option \"--non-interactive\" is often needed to prevent SVN
61hanging while prompting for authorization."
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +000062 :type '(choice (const :tag "None" nil)
63 (string :tag "Argument String")
64 (repeat :tag "Argument List"
65 :value ("")
66 string))
31db8c31 Glenn Morris2013-02-10 17:07:05 -080067 :version "24.4"
67b0de11 Chong Yidong2012-02-25 12:29:09 +080068 :group 'vc-svn)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +000069
70(defcustom vc-svn-register-switches nil
c8d6b4bc Glenn Morris2008-12-04 07:03:53 +000071 "Switches for registering a file into SVN.
1fd3454a Stefan Monnier2003-05-05 15:42:27 +000072A string or list of strings passed to the checkin program by
c8d6b4bc
GM
Glenn Morris2008-12-04 07:03:53 +000073\\[vc-register]. If nil, use the value of `vc-register-switches'.
74If t, use no switches."
75 :type '(choice (const :tag "Unspecified" nil)
76 (const :tag "None" t)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +000077 (string :tag "Argument String")
c8d6b4bc Glenn Morris2008-12-04 07:03:53 +000078 (repeat :tag "Argument List" :value ("") string))
bf247b6e Kim F. Storm2005-02-09 15:50:47 +000079 :version "22.1"
67b0de11 Chong Yidong2012-02-25 12:29:09 +080080 :group 'vc-svn)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +000081
8462aca5
SM
Stefan Monnier2003-07-23 15:34:14 +000082(defcustom vc-svn-diff-switches
83 t ;`svn' doesn't support common args like -c or -b.
84 "String or list of strings specifying extra switches for svn diff under VC.
9751169a Glenn Morris2008-11-30 01:58:06 +000085If nil, use the value of `vc-diff-switches' (or `diff-switches'),
ed68f651
SS
Sam Steingold2011-01-25 11:01:53 -050086together with \"-x --diff-cmd=\"`diff-command' (since 'svn diff'
87does not support the default \"-c\" value of `diff-switches').
88If you want to force an empty list of arguments, use t."
8462aca5
SM
Stefan Monnier2003-07-23 15:34:14 +000089 :type '(choice (const :tag "Unspecified" nil)
90 (const :tag "None" t)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +000091 (string :tag "Argument String")
92 (repeat :tag "Argument List"
93 :value ("")
94 string))
bf247b6e Kim F. Storm2005-02-09 15:50:47 +000095 :version "22.1"
67b0de11 Chong Yidong2012-02-25 12:29:09 +080096 :group 'vc-svn)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +000097
b5a0603e
OF
Oscar Fuentes2015-02-26 15:46:12 +010098(defcustom vc-svn-annotate-switches nil
99 "String or list of strings specifying switches for svn annotate under VC.
100If nil, use the value of `vc-annotate-switches'. If t, use no
101switches."
102 :type '(choice (const :tag "Unspecified" nil)
103 (const :tag "None" t)
104 (string :tag "Argument String")
105 (repeat :tag "Argument List" :value ("") string))
106 :version "25.1"
107 :group 'vc-svn)
108
67141a37 Glenn Morris2010-10-03 14:05:47 -0700109(defcustom vc-svn-header '("\$Id\$")
f9d5dc48 Glenn Morris2008-11-22 03:27:18 +0000110 "Header keywords to be inserted by `vc-insert-headers'."
67141a37 Glenn Morris2010-10-03 14:05:47 -0700111 :version "24.1" ; no longer consult the obsolete vc-header-alist
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000112 :type '(repeat string)
67b0de11 Chong Yidong2012-02-25 12:29:09 +0800113 :group 'vc-svn)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000114
fc2fb30c
SM
Stefan Monnier2007-02-19 19:42:10 +0000115;; We want to autoload it for use by the autoloaded version of
116;; vc-svn-registered, but we want the value to be compiled at startup, not
117;; at dump time.
118;; ;;;###autoload
119(defconst vc-svn-admin-directory
120 (cond ((and (memq system-type '(cygwin windows-nt ms-dos))
ace2fad9
CY
Chong Yidong2006-11-09 03:34:17 +0000121 (getenv "SVN_ASP_DOT_NET_HACK"))
122 "_svn")
123 (t ".svn"))
124 "The name of the \".svn\" subdirectory or its equivalent.")
125
8cdd17b4
ER
Eric S. Raymond2007-07-18 16:32:40 +0000126;;; Properties of the backend
127
70e2f6c7 Eric S. Raymond2008-05-02 17:47:25 +0000128(defun vc-svn-revision-granularity () 'repository)
9c750eba Stefan Monnier2013-09-04 17:09:42 -0400129(defun vc-svn-checkout-model (_files) 'implicit)
70e2f6c7 Eric S. Raymond2008-05-02 17:47:25 +0000130
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000131;;;
132;;; State-querying functions
133;;;
134
ace2fad9
CY
Chong Yidong2006-11-09 03:34:17 +0000135;;; vc-svn-admin-directory is generally not defined when the
136;;; autoloaded function is called.
137
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000138;;;###autoload (defun vc-svn-registered (f)
ace2fad9 Chong Yidong2006-11-09 03:34:17 +0000139;;;###autoload (let ((admin-dir (cond ((and (eq system-type 'windows-nt)
fc2fb30c
SM
Stefan Monnier2007-02-19 19:42:10 +0000140;;;###autoload (getenv "SVN_ASP_DOT_NET_HACK"))
141;;;###autoload "_svn")
142;;;###autoload (t ".svn"))))
b5a53795 Karl Pflästerer2011-02-11 20:12:53 -0500143;;;###autoload (when (vc-find-root f admin-dir)
af314ba0 Christopher Schmidt2013-02-01 18:19:24 +0100144;;;###autoload (load "vc-svn" nil t)
ace2fad9 Chong Yidong2006-11-09 03:34:17 +0000145;;;###autoload (vc-svn-registered f))))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000146
147(defun vc-svn-registered (file)
148 "Check if FILE is SVN registered."
7d043d59 Michael Albinus2014-12-05 21:36:47 +0100149 (setq file (expand-file-name file))
b5a53795 Karl Pflästerer2011-02-11 20:12:53 -0500150 (when (vc-svn-root file)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000151 (with-temp-buffer
152 (cd (file-name-directory file))
04473f67
MA
Michael Albinus2009-08-25 09:05:07 +0000153 (let* (process-file-side-effects
154 (status
df4da7f4
SM
Stefan Monnier2005-12-13 22:25:24 +0000155 (condition-case nil
156 ;; Ignore all errors.
157 (vc-svn-command t t file "status" "-v")
158 ;; Some problem happened. E.g. We can't find an `svn'
159 ;; executable. We used to only catch `file-error' but when
160 ;; the process is run on a remote host via Tramp, the error
161 ;; is only reported via the exit status which is turned into
162 ;; an `error' by vc-do-command.
163 (error nil))))
164 (when (eq 0 status)
b5e791bd
DN
Dan Nicolaescu2008-01-20 19:56:43 +0000165 (let ((parsed (vc-svn-parse-status file)))
166 (and parsed (not (memq parsed '(ignored unregistered))))))))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000167
b3298507 Karl Fogel2014-12-03 14:23:26 -0600168(defun vc-svn-state (file)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000169 "SVN-specific version of `vc-state'."
04473f67 Michael Albinus2009-08-25 09:05:07 +0000170 (let (process-file-side-effects)
04473f67
MA
Michael Albinus2009-08-25 09:05:07 +0000171 (with-temp-buffer
172 (cd (file-name-directory file))
b3298507 Karl Fogel2014-12-03 14:23:26 -0600173 (vc-svn-command t 0 file "status" "-v")
04473f67 Michael Albinus2009-08-25 09:05:07 +0000174 (vc-svn-parse-status file))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000175
a80a6b03
GM
Glenn Morris2008-10-04 20:24:24 +0000176;; FIXME it would be better not to have the "remote" argument,
177;; but to distinguish the two output formats based on content.
255d2a5a Dmitry Gutov2015-01-16 06:24:09 +0300178;; FIXME: the local format isn't used by the (sole) caller anymore.
a80a6b03 Glenn Morris2008-10-04 20:24:24 +0000179(defun vc-svn-after-dir-status (callback &optional remote)
c222c25f Dan Nicolaescu2008-01-19 16:32:23 +0000180 (let ((state-map '((?A . added)
b2ee56c9 Stefan Monnier2008-04-11 15:59:22 +0000181 (?C . conflict)
b2ee56c9
SM
Stefan Monnier2008-04-11 15:59:22 +0000182 (?I . ignored)
183 (?M . edited)
e6c01f09 Stefan Monnier2009-05-05 04:17:27 +0000184 (?D . removed)
b2ee56c9
SM
Stefan Monnier2008-04-11 15:59:22 +0000185 (?R . removed)
186 (?? . unregistered)
187 ;; This is what vc-svn-parse-status does.
188 (?~ . edited)))
5dd4f3f7
GM
Glenn Morris2011-01-18 19:49:00 -0800189 (re (if remote "^\\(.\\)\\(.\\).....? \\([ *]\\) +\\(?:[-0-9]+\\)? \\(.*\\)$"
190 ;; Subexp 3 is a dummy in this case, so the numbers match.
f0db3488 Stefan Monnier2014-10-02 20:42:28 -0400191 "^\\(.\\)\\(.\\)...\\(.\\).? \\(.*\\)$"))
c222c25f
DN
Dan Nicolaescu2008-01-19 16:32:23 +0000192 result)
193 (goto-char (point-min))
a80a6b03 Glenn Morris2008-10-04 20:24:24 +0000194 (while (re-search-forward re nil t)
c222c25f Dan Nicolaescu2008-01-19 16:32:23 +0000195 (let ((state (cdr (assq (aref (match-string 1) 0) state-map)))
5dd4f3f7 Glenn Morris2011-01-18 19:49:00 -0800196 (propstat (cdr (assq (aref (match-string 2) 0) state-map)))
614b85f8
VJ
Vagn Johansen2011-03-02 23:27:52 -0800197 (filename (if (memq system-type '(windows-nt ms-dos))
198 (replace-regexp-in-string "\\\\" "/" (match-string 4))
199 (match-string 4))))
dbfb414e
GM
Glenn Morris2011-01-19 23:17:22 -0800200 (and (memq propstat '(conflict edited))
201 (not (eq state 'conflict)) ; conflict always wins
202 (setq state propstat))
5dd4f3f7 Glenn Morris2011-01-18 19:49:00 -0800203 (and remote (string-equal (match-string 3) "*")
a80a6b03
GM
Glenn Morris2008-10-04 20:24:24 +0000204 ;; FIXME are there other possible combinations?
205 (cond ((eq state 'edited) (setq state 'needs-merge))
206 ((not state) (setq state 'needs-update))))
524a655d Dan Nicolaescu2009-04-15 00:32:47 +0000207 (when (and state (not (string= "." filename)))
1b3f2d4e Dan Nicolaescu2008-03-31 15:36:56 +0000208 (setq result (cons (list filename state) result)))))
b2ee56c9 Stefan Monnier2008-04-11 15:59:22 +0000209 (funcall callback result)))
c222c25f Dan Nicolaescu2008-01-19 16:32:23 +0000210
b1a765b3
ER
Eric S. Raymond2014-12-02 10:10:55 -0500211;; dir-status-files called from vc-dir, which loads vc,
212;; which loads vc-dispatcher.
e658d75c
GM
Glenn Morris2013-05-28 00:01:59 -0700213(declare-function vc-exec-after "vc-dispatcher" (code))
214
b1a765b3
ER
Eric S. Raymond2014-12-02 10:10:55 -0500215(autoload 'vc-expand-dirs "vc")
216
af1040b3 Dmitry Gutov2014-12-18 15:47:11 +0200217(defun vc-svn-dir-status-files (_dir files callback)
c222c25f
DN
Dan Nicolaescu2008-01-19 16:32:23 +0000218 "Run 'svn status' for DIR and update BUFFER via CALLBACK.
219CALLBACK is called as (CALLBACK RESULT BUFFER), where
220RESULT is a list of conses (FILE . STATE) for directory DIR."
687ae680 Dmitry Gutov2014-12-18 15:51:34 +0200221 ;; FIXME shouldn't this rather default to all the files in dir?
af1040b3 Dmitry Gutov2014-12-18 15:47:11 +0200222 (apply #'vc-svn-command (current-buffer) 'async nil "status" "-u" files)
255d2a5a Dmitry Gutov2015-01-16 06:24:09 +0300223 (vc-run-delayed (vc-svn-after-dir-status callback t)))
f8e89f19 Dan Nicolaescu2008-01-18 23:45:04 +0000224
be94d713 Glenn Morris2013-09-11 23:53:57 -0700225(defun vc-svn-dir-extra-headers (_dir)
2ec0d864 Eric S. Raymond2008-05-16 18:15:26 +0000226 "Generate extra status headers for a Subversion working copy."
04473f67
MA
Michael Albinus2009-08-25 09:05:07 +0000227 (let (process-file-side-effects)
228 (vc-svn-command "*vc*" 0 nil "info"))
2ec0d864 Eric S. Raymond2008-05-16 18:15:26 +0000229 (let ((repo
def61be2 Juanma Barranquero2008-06-16 08:55:56 +0000230 (save-excursion
2ec0d864
ER
Eric S. Raymond2008-05-16 18:15:26 +0000231 (and (progn
232 (set-buffer "*vc*")
233 (goto-char (point-min))
234 (re-search-forward "Repository Root: *\\(.*\\)" nil t))
235 (match-string 1)))))
236 (concat
237 (cond (repo
238 (concat
239 (propertize "Repository : " 'face 'font-lock-type-face)
240 (propertize repo 'face 'font-lock-variable-name-face)))
241 (t "")))))
242
ac3f4c6f
ER
Eric S. Raymond2007-10-10 18:52:45 +0000243(defun vc-svn-working-revision (file)
244 "SVN-specific version of `vc-working-revision'."
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000245 ;; There is no need to consult RCS headers under SVN, because we
246 ;; get the workfile version for free when we recognize that a file
247 ;; is registered in SVN.
248 (vc-svn-registered file)
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000249 (vc-file-getprop file 'vc-working-revision))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000250
5cc7cb96
SM
Stefan Monnier2003-07-04 22:21:45 +0000251;; vc-svn-mode-line-string doesn't exist because the default implementation
252;; works just fine.
253
9c750eba Stefan Monnier2013-09-04 17:09:42 -0400254(defun vc-svn-previous-revision (_file rev)
cbbd2cd3
TTN
Thien-Thi Nguyen2006-02-06 15:58:38 +0000255 (let ((newrev (1- (string-to-number rev))))
256 (when (< 0 newrev)
257 (number-to-string newrev))))
258
5b5afd50 Eric S. Raymond2007-10-10 19:39:23 +0000259(defun vc-svn-next-revision (file rev)
cbbd2cd3 Thien-Thi Nguyen2006-02-06 15:58:38 +0000260 (let ((newrev (1+ (string-to-number rev))))
5b5afd50 Eric S. Raymond2007-10-10 19:39:23 +0000261 ;; The "working revision" is an uneasy conceptual fit under Subversion;
cbbd2cd3
TTN
Thien-Thi Nguyen2006-02-06 15:58:38 +0000262 ;; we use it as the upper bound until a better idea comes along. If the
263 ;; workfile version W coincides with the tree's latest revision R, then
264 ;; this check prevents a "no such revision: R+1" error. Otherwise, it
265 ;; inhibits showing of W+1 through R, which could be considered anywhere
266 ;; from gracious to impolite.
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000267 (unless (< (string-to-number (vc-file-getprop file 'vc-working-revision))
cbbd2cd3
TTN
Thien-Thi Nguyen2006-02-06 15:58:38 +0000268 newrev)
269 (number-to-string newrev))))
270
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000271
272;;;
273;;; State-changing functions
274;;;
275
8cdd17b4
ER
Eric S. Raymond2007-07-18 16:32:40 +0000276(defun vc-svn-create-repo ()
277 "Create a new SVN repository."
2888a97e Eric S. Raymond2008-05-10 13:27:16 +0000278 (vc-do-command "*vc*" 0 "svnadmin" '("create" "SVN"))
14afa541
GM
Glenn Morris2013-10-09 14:49:32 -0400279 ;; Expand default-directory because svn gets confused by eg
280 ;; file://~/path/to/file. (Bug#15446).
9a4de110 Glenn Morris2011-11-09 21:36:48 -0500281 (vc-svn-command "*vc*" 0 "." "checkout"
14afa541 Glenn Morris2013-10-09 14:49:32 -0400282 (concat "file://" (expand-file-name default-directory) "SVN")))
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000283
e658d75c
GM
Glenn Morris2013-05-28 00:01:59 -0700284(autoload 'vc-switches "vc")
285
9e9e3432 Eric S. Raymond2014-12-01 07:08:40 -0500286(defun vc-svn-register (files &optional _comment)
8cdd17b4
ER
Eric S. Raymond2007-07-18 16:32:40 +0000287 "Register FILES into the SVN version-control system.
288The COMMENT argument is ignored This does an add but not a commit.
c8d6b4bc
GM
Glenn Morris2008-12-04 07:03:53 +0000289Passes either `vc-svn-register-switches' or `vc-register-switches'
290to the SVN command."
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000291 (apply 'vc-svn-command nil 0 files "add" (vc-switches 'SVN 'register)))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000292
b5a53795
KP
Karl Pflästerer2011-02-11 20:12:53 -0500293(defun vc-svn-root (file)
294 (vc-find-root file vc-svn-admin-directory))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000295
b5a53795
KP
Karl Pflästerer2011-02-11 20:12:53 -0500296(defalias 'vc-svn-responsible-p 'vc-svn-root)
297
f83109f0 Eric S. Raymond2014-11-20 02:37:06 -0500298(defun vc-svn-checkin (files comment &optional _extra-args-ignored)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000299 "SVN-specific version of `vc-backend-checkin'."
5129f10c Karl Fogel2004-06-04 04:37:10 +0000300 (let ((status (apply
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000301 'vc-svn-command nil 1 files "ci"
5129f10c Karl Fogel2004-06-04 04:37:10 +0000302 (nconc (list "-m" comment) (vc-switches 'SVN 'checkin)))))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000303 (set-buffer "*vc*")
304 (goto-char (point-min))
305 (unless (equal status 0)
306 ;; Check checkin problem.
307 (cond
fd140743 Stefan Monnier2003-05-08 18:31:21 +0000308 ((search-forward "Transaction is out of date" nil t)
8cdd17b4
ER
Eric S. Raymond2007-07-18 16:32:40 +0000309 (mapc (lambda (file) (vc-file-setprop file 'vc-state 'needs-merge))
310 files)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000311 (error (substitute-command-keys
312 (concat "Up-to-date check failed: "
313 "type \\[vc-next-action] to merge in changes"))))
314 (t
315 (pop-to-buffer (current-buffer))
316 (goto-char (point-min))
317 (shrink-window-if-larger-than-buffer)
318 (error "Check-in failed"))))
319 ;; Update file properties
320 ;; (vc-file-setprop
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000321 ;; file 'vc-working-revision
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000322 ;; (vc-parse-buffer "^\\(new\\|initial\\) revision: \\([0-9.]+\\)" 2))
323 ))
324
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000325(defun vc-svn-find-revision (file rev buffer)
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000326 "SVN-specific retrieval of a specified version into a buffer."
04473f67
MA
Michael Albinus2009-08-25 09:05:07 +0000327 (let (process-file-side-effects)
328 (apply 'vc-svn-command
329 buffer 0 file
330 "cat"
331 (and rev (not (string= rev ""))
332 (concat "-r" rev))
333 (vc-switches 'SVN 'checkout))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000334
c799337f Dmitry Gutov2014-10-03 17:15:05 +0400335(defun vc-svn-ignore (file &optional directory remove)
ab419665 Xue Fuqiao2013-08-04 10:55:45 +0800336 "Ignore FILE under Subversion.
63191d9f Xue Fuqiao2013-09-04 08:31:13 +0800337FILE is a file wildcard, relative to the root directory of DIRECTORY."
c799337f
DG
Dmitry Gutov2014-10-03 17:15:05 +0400338 (let* ((ignores (vc-svn-ignore-completion-table directory))
339 (file (file-relative-name file directory))
340 (ignores (if remove
341 (delete file ignores)
342 (push file ignores))))
343 (vc-svn-command nil 0 nil nil "propset" "svn:ignore"
344 (mapconcat #'identity ignores "\n")
345 (expand-file-name directory))))
346
347(defun vc-svn-ignore-completion-table (directory)
348 "Return the list of ignored files in DIRECTORY."
349 (with-temp-buffer
350 (vc-svn-command t t nil "propget" "svn:ignore" (expand-file-name directory))
351 (split-string (buffer-string))))
ab419665 Xue Fuqiao2013-08-04 10:55:45 +0800352
34ca0f4c
XF
Xue Fuqiao2013-10-05 07:47:00 +0800353(defun vc-svn-find-admin-dir (file)
354 "Return the administrative directory of FILE."
355 (expand-file-name vc-svn-admin-directory (vc-svn-root file)))
356
e7e9dbcc Eric S. Raymond2014-11-20 03:52:24 -0500357(defun vc-svn-checkout (file &optional rev)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000358 (message "Checking out %s..." file)
359 (with-current-buffer (or (get-file-buffer file) (current-buffer))
e7e9dbcc Eric S. Raymond2014-11-20 03:52:24 -0500360 (vc-svn-update file rev (vc-switches 'SVN 'checkout)))
77bf3f54 Dan Nicolaescu2009-06-23 06:35:40 +0000361 (vc-mode-line file 'SVN)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000362 (message "Checking out %s...done" file))
363
e7e9dbcc Eric S. Raymond2014-11-20 03:52:24 -0500364(defun vc-svn-update (file rev switches)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000365 (if (and (file-exists-p file) (not rev))
fc2fb30c
SM
Stefan Monnier2007-02-19 19:42:10 +0000366 ;; If no revision was specified, there's nothing to do.
367 nil
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000368 ;; Check out a particular version (or recreate the file).
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000369 (vc-file-setprop file 'vc-working-revision nil)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000370 (apply 'vc-svn-command nil 0 file
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000371 "update"
5cc7cb96
SM
Stefan Monnier2003-07-04 22:21:45 +0000372 (cond
373 ((null rev) "-rBASE")
374 ((or (eq rev t) (equal rev "")) nil)
375 (t (concat "-r" rev)))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000376 switches)))
377
3bdc13e4
SM
Stefan Monnier2003-05-14 19:38:39 +0000378(defun vc-svn-delete-file (file)
379 (vc-svn-command nil 0 file "remove"))
380
2766aaaf
SM
Stefan Monnier2003-05-09 14:13:40 +0000381(defun vc-svn-rename-file (old new)
382 (vc-svn-command nil 0 new "move" (file-relative-name old)))
383
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000384(defun vc-svn-revert (file &optional contents-done)
385 "Revert FILE to the version it was based on."
386 (unless contents-done
fc2fb30c Stefan Monnier2007-02-19 19:42:10 +0000387 (vc-svn-command nil 0 file "revert")))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000388
d17bae90
ER
Eric S. Raymond2014-12-01 11:41:45 -0500389(defun vc-svn-merge-file (file)
390 "Accept a file merge request, prompting for revisions."
391 (let* ((first-revision
392 (vc-read-revision
393 (concat "Merge " file
394 " from SVN revision "
395 "(default news on current branch): ")
396 (list file)
397 'SVN))
398 second-revision
399 status)
400 (cond
401 ((string= first-revision "")
402 (setq status (vc-svn-merge-news file)))
403 (t
404 (setq second-revision
405 (vc-read-revision
406 "Second SVN revision: "
407 (list file) 'SVN nil
408 first-revision))
409 (setq status (vc-svn-merge file first-revision second-revision))))
410 status))
411
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000412(defun vc-svn-merge (file first-version &optional second-version)
413 "Merge changes into current working copy of FILE.
414The changes are between FIRST-VERSION and SECOND-VERSION."
415 (vc-svn-command nil 0 file
c217cb04 Stefan Monnier2003-05-05 16:13:04 +0000416 "merge"
02610d0e Stefan Monnier2003-05-05 16:13:39 +0000417 "-r" (if second-version
c217cb04
SM
Stefan Monnier2003-05-05 16:13:04 +0000418 (concat first-version ":" second-version)
419 first-version))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000420 (vc-file-setprop file 'vc-state 'edited)
421 (with-current-buffer (get-buffer "*vc*")
422 (goto-char (point-min))
c217cb04
SM
Stefan Monnier2003-05-05 16:13:04 +0000423 (if (looking-at "C ")
424 1 ; signal conflict
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000425 0))) ; signal success
426
427(defun vc-svn-merge-news (file)
428 "Merge in any new changes made to FILE."
429 (message "Merging changes into %s..." file)
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000430 ;; (vc-file-setprop file 'vc-working-revision nil)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000431 (vc-file-setprop file 'vc-checkout-time 0)
9a4de110 Glenn Morris2011-11-09 21:36:48 -0500432 (vc-svn-command nil 0 file "update")
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000433 ;; Analyze the merge result reported by SVN, and set
434 ;; file properties accordingly.
435 (with-current-buffer (get-buffer "*vc*")
436 (goto-char (point-min))
5b5afd50 Eric S. Raymond2007-10-10 19:39:23 +0000437 ;; get new working revision
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000438 (if (re-search-forward
1468d754 Stefan Monnier2003-05-05 16:06:10 +0000439 "^\\(Updated to\\|At\\) revision \\([0-9]+\\)" nil t)
ac3f4c6f
ER
Eric S. Raymond2007-10-10 18:52:45 +0000440 (vc-file-setprop file 'vc-working-revision (match-string 2))
441 (vc-file-setprop file 'vc-working-revision nil))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000442 ;; get file status
1468d754 Stefan Monnier2003-05-05 16:06:10 +0000443 (goto-char (point-min))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000444 (prog1
1468d754 Stefan Monnier2003-05-05 16:06:10 +0000445 (if (looking-at "At revision")
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000446 0 ;; there were no news; indicate success
447 (if (re-search-forward
459b1fe4
SM
Stefan Monnier2007-02-07 23:02:12 +0000448 ;; Newer SVN clients have 3 columns of chars (one for the
449 ;; file's contents, then second for its properties, and the
450 ;; third for lock-grabbing info), before the 2 spaces.
451 ;; We also used to match the filename in column 0 without any
452 ;; meta-info before it, but I believe this can never happen.
453 (concat "^\\(\\([ACGDU]\\)\\(.[B ]\\)? \\)"
c2d07557 Chong Yidong2012-11-17 15:06:57 +0800454 (regexp-quote (file-relative-name file)))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000455 nil t)
456 (cond
457 ;; Merge successful, we are in sync with repository now
459b1fe4 Stefan Monnier2007-02-07 23:02:12 +0000458 ((string= (match-string 2) "U")
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000459 (vc-file-setprop file 'vc-state 'up-to-date)
460 (vc-file-setprop file 'vc-checkout-time
461 (nth 5 (file-attributes file)))
462 0);; indicate success to the caller
463 ;; Merge successful, but our own changes are still in the file
459b1fe4 Stefan Monnier2007-02-07 23:02:12 +0000464 ((string= (match-string 2) "G")
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000465 (vc-file-setprop file 'vc-state 'edited)
466 0);; indicate success to the caller
467 ;; Conflicts detected!
468 (t
469 (vc-file-setprop file 'vc-state 'edited)
470 1);; signal the error to the caller
471 )
472 (pop-to-buffer "*vc*")
473 (error "Couldn't analyze svn update result")))
474 (message "Merging changes into %s...done" file))))
475
9c750eba Stefan Monnier2013-09-04 17:09:42 -0400476(defun vc-svn-modify-change-comment (_files rev comment)
42a0a135
ER
Eric S. Raymond2008-01-02 00:42:37 +0000477 "Modify the change comments for a specified REV.
478You must have ssh access to the repository host, and the directory Emacs
e09deae9 Chong Yidong2008-12-03 03:25:15 +0000479uses locally for temp files must also be writable by you on that host.
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000480This is only supported if the repository access method is either file://
481or svn+ssh://."
482 (let (tempfile host remotefile directory fileurl-p)
42a0a135 Eric S. Raymond2008-01-02 00:42:37 +0000483 (with-temp-buffer
9a4de110 Glenn Morris2011-11-09 21:36:48 -0500484 (vc-svn-command (current-buffer) 0 nil "info")
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000485 (goto-char (point-min))
486 (unless (re-search-forward "Repository Root: \\(file://\\(/.*\\)\\)\\|\\(svn\\+ssh://\\([^/]+\\)\\(/.*\\)\\)" nil t)
487 (error "Repository information is unavailable"))
488 (if (match-string 1)
489 (progn
490 (setq fileurl-p t)
491 (setq directory (match-string 2)))
492 (setq host (match-string 4))
493 (setq directory (match-string 5))
494 (setq remotefile (concat host ":" tempfile))))
495 (with-temp-file (setq tempfile (make-temp-file user-mail-address))
496 (insert comment))
497 (if fileurl-p
498 ;; Repository Root is a local file.
499 (progn
500 (unless (vc-do-command
2888a97e Eric S. Raymond2008-05-10 13:27:16 +0000501 "*vc*" 0 "svnadmin" nil
def61be2 Juanma Barranquero2008-06-16 08:55:56 +0000502 "setlog" "--bypass-hooks" directory
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000503 "-r" rev (format "%s" tempfile))
504 (error "Log edit failed"))
505 (delete-file tempfile))
506
507 ;; Remote repository, using svn+ssh.
2888a97e Eric S. Raymond2008-05-10 13:27:16 +0000508 (unless (vc-do-command "*vc*" 0 "scp" nil "-q" tempfile remotefile)
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000509 (error "Copy of comment to %s failed" remotefile))
510 (unless (vc-do-command
2888a97e Eric S. Raymond2008-05-10 13:27:16 +0000511 "*vc*" 0 "ssh" nil "-q" host
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000512 (format "svnadmin setlog --bypass-hooks %s -r %s %s; rm %s"
513 directory rev tempfile tempfile))
514 (error "Log edit failed")))))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000515
516;;;
517;;; History functions
518;;;
519
def61be2
JB
Juanma Barranquero2008-06-16 08:55:56 +0000520(defvar log-view-per-file-logs)
521
6653c6b7
DN
Dan Nicolaescu2008-06-15 14:58:24 +0000522(define-derived-mode vc-svn-log-view-mode log-view-mode "SVN-Log-View"
523 (require 'add-log)
524 (set (make-local-variable 'log-view-per-file-logs) nil))
525
e658d75c
GM
Glenn Morris2013-05-28 00:01:59 -0700526(autoload 'vc-setup-buffer "vc-dispatcher")
527
9c750eba Stefan Monnier2013-09-04 17:09:42 -0400528(defun vc-svn-print-log (files buffer &optional _shortlog start-revision limit)
bb7cdf58
GM
Glenn Morris2013-04-24 00:52:00 -0700529 "Print commit log associated with FILES into specified BUFFER.
530SHORTLOG is ignored.
531If START-REVISION is non-nil, it is the newest revision to show.
532If LIMIT is non-nil, show no more than this many entries."
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000533 (save-current-buffer
b349012b Juanma Barranquero2004-04-20 16:49:26 +0000534 (vc-setup-buffer buffer)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000535 (let ((inhibit-read-only t))
536 (goto-char (point-min))
13b56025
ER
Eric S. Raymond2007-12-27 03:10:52 +0000537 (if files
538 (dolist (file files)
539 (insert "Working file: " file "\n")
6616006b
DN
Dan Nicolaescu2009-11-15 20:28:58 +0000540 (apply
541 'vc-svn-command
13b56025
ER
Eric S. Raymond2007-12-27 03:10:52 +0000542 buffer
543 'async
13b56025
ER
Eric S. Raymond2007-12-27 03:10:52 +0000544 (list file)
545 "log"
662c5698
DN
Dan Nicolaescu2009-12-07 09:02:11 +0000546 (append
547 (list
548 (if start-revision
90b4237a Glenn Morris2013-04-24 00:59:29 -0700549 (format "-r%s:1" start-revision)
662c5698
DN
Dan Nicolaescu2009-12-07 09:02:11 +0000550 ;; By default Subversion only shows the log up to the
551 ;; working revision, whereas we also want the log of the
552 ;; subsequent commits. At least that's what the
553 ;; vc-cvs.el code does.
554 "-rHEAD:0"))
1db3226b Glenn Morris2010-01-14 19:54:36 -0800555 (when limit (list "--limit" (format "%s" limit))))))
13b56025 Eric S. Raymond2007-12-27 03:10:52 +0000556 ;; Dump log for the entire directory.
662c5698
DN
Dan Nicolaescu2009-12-07 09:02:11 +0000557 (apply 'vc-svn-command buffer 0 nil "log"
558 (append
559 (list
560 (if start-revision (format "-r%s" start-revision) "-rHEAD:0"))
1db3226b Glenn Morris2010-01-14 19:54:36 -0800561 (when limit (list "--limit" (format "%s" limit)))))))))
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000562
01b97f9d Dmitry Gutov2014-12-14 12:49:08 +0200563(defun vc-svn-diff (files &optional oldvers newvers buffer async)
5b5afd50 Eric S. Raymond2007-10-10 19:39:23 +0000564 "Get a difference report using SVN between two revisions of fileset FILES."
22b5692c
NR
Nick Roberts2009-02-04 10:49:04 +0000565 (and oldvers
566 (not newvers)
567 files
568 (catch 'no
569 (dolist (f files)
570 (or (equal oldvers (vc-working-revision f))
571 (throw 'no nil)))
572 t)
573 ;; Use nil rather than the current revision because svn handles
574 ;; it better (i.e. locally). Note that if _any_ of the files
575 ;; has a different revision, we fetch the lot, which is
576 ;; obviously sub-optimal.
577 (setq oldvers nil))
3c07d7f0 Eric S. Raymond2014-12-13 06:15:33 -0500578 (setq async (and async (or oldvers newvers))) ; Svn diffs those locally.
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000579 (let* ((switches
f9d1f3be
SM
Stefan Monnier2004-08-23 18:23:52 +0000580 (if vc-svn-diff-switches
581 (vc-switches 'SVN 'diff)
ed68f651 Sam Steingold2011-01-25 11:01:53 -0500582 (list (concat "--diff-cmd=" diff-command) "-x"
3c07d7f0 Eric S. Raymond2014-12-13 06:15:33 -0500583 (mapconcat 'identity (vc-switches nil 'diff) " ")))))
b349012b Juanma Barranquero2004-04-20 16:49:26 +0000584 (apply 'vc-svn-command buffer
2766aaaf Stefan Monnier2003-05-09 14:13:40 +0000585 (if async 'async 0)
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000586 files "diff"
2766aaaf Stefan Monnier2003-05-09 14:13:40 +0000587 (append
f9d1f3be Stefan Monnier2004-08-23 18:23:52 +0000588 switches
2766aaaf
SM
Stefan Monnier2003-05-09 14:13:40 +0000589 (when oldvers
590 (list "-r" (if newvers (concat oldvers ":" newvers)
591 oldvers)))))
fd140743
SM
Stefan Monnier2003-05-08 18:31:21 +0000592 (if async 1 ; async diff => pessimistic assumption
593 ;; For some reason `svn diff' does not return a useful
594 ;; status w.r.t whether the diff was empty or not.
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000595 (buffer-size (get-buffer buffer)))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000596
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000597;;;
370fded4 Eric S. Raymond2008-05-15 17:38:50 +0000598;;; Tag system
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000599;;;
600
370fded4 Eric S. Raymond2008-05-15 17:38:50 +0000601(defun vc-svn-create-tag (dir name branchp)
5b5afd50 Eric S. Raymond2007-10-10 19:39:23 +0000602 "Assign to DIR's current revision a given NAME.
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000603If BRANCHP is non-nil, the name is created as a branch (and the current
5cc7cb96
SM
Stefan Monnier2003-07-04 22:21:45 +0000604workspace is immediately moved to that new branch).
605NAME is assumed to be a URL."
606 (vc-svn-command nil 0 dir "copy" name)
370fded4 Eric S. Raymond2008-05-15 17:38:50 +0000607 (when branchp (vc-svn-retrieve-tag dir name nil)))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000608
aa30fa6f Glenn Morris2013-09-11 23:55:15 -0700609(defun vc-svn-retrieve-tag (dir name _update)
370fded4
ER
Eric S. Raymond2008-05-15 17:38:50 +0000610 "Retrieve a tag at and below DIR.
611NAME is the name of the tag; if it is empty, do a `svn update'.
5cc7cb96
SM
Stefan Monnier2003-07-04 22:21:45 +0000612If UPDATE is non-nil, then update (resynch) any affected buffers.
613NAME is assumed to be a URL."
614 (vc-svn-command nil 0 dir "switch" name)
615 ;; FIXME: parse the output and obey `update'.
616 )
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000617
618;;;
619;;; Miscellaneous
620;;;
621
622;; Subversion makes backups for us, so don't bother.
77bf3f54
DN
Dan Nicolaescu2009-06-23 06:35:40 +0000623;; (defun vc-svn-make-version-backups-p (file)
624;; "Return non-nil if version backups should be made for FILE."
2a81c5d9 Eric S. Raymond2014-12-01 10:11:42 -0500625;; nil)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000626
627(defun vc-svn-check-headers ()
628 "Check if the current file has any headers in it."
629 (save-excursion
630 (goto-char (point-min))
631 (re-search-forward "\\$[A-Za-z\300-\326\330-\366\370-\377]+\
632\\(: [\t -#%-\176\240-\377]*\\)?\\$" nil t)))
633
634
635;;;
636;;; Internal functions
637;;;
638
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000639(defun vc-svn-command (buffer okstatus file-or-list &rest flags)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000640 "A wrapper around `vc-do-command' for use in vc-svn.el.
641The difference to vc-do-command is that this function always invokes `svn',
31db8c31 Glenn Morris2013-02-10 17:07:05 -0800642and that it passes `vc-svn-global-switches' to it before FLAGS."
9a4de110 Glenn Morris2011-11-09 21:36:48 -0500643 (apply 'vc-do-command (or buffer "*vc*") okstatus vc-svn-program file-or-list
31db8c31
GM
Glenn Morris2013-02-10 17:07:05 -0800644 (if (stringp vc-svn-global-switches)
645 (cons vc-svn-global-switches flags)
646 (append vc-svn-global-switches flags))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000647
1c67a814
SM
Stefan Monnier2007-09-28 18:45:43 +0000648(defun vc-svn-resolve-when-done ()
649 "Call \"svn resolved\" if the conflict markers have been removed."
650 (save-excursion
651 (goto-char (point-min))
54648b5c
DN
Dan Nicolaescu2008-01-15 04:37:20 +0000652 (unless (re-search-forward "^<<<<<<< " nil t)
653 (vc-svn-command nil 0 buffer-file-name "resolved")
654 ;; Remove the hook so that it is not called multiple times.
655 (remove-hook 'after-save-hook 'vc-svn-resolve-when-done t))))
1c67a814
SM
Stefan Monnier2007-09-28 18:45:43 +0000656
657;; Inspired by vc-arch-find-file-hook.
658(defun vc-svn-find-file-hook ()
659 (when (eq ?C (vc-file-getprop buffer-file-name 'vc-svn-status))
660 ;; If the file is marked as "conflicted", then we should try and call
661 ;; "svn resolved" when applicable.
662 (if (save-excursion
663 (goto-char (point-min))
664 (re-search-forward "^<<<<<<< " nil t))
665 ;; There are conflict markers.
666 (progn
28e4e2b4 Dan Nicolaescu2008-01-16 06:22:59 +0000667 (smerge-start-session)
1c67a814
SM
Stefan Monnier2007-09-28 18:45:43 +0000668 (add-hook 'after-save-hook 'vc-svn-resolve-when-done nil t))
669 ;; There are no conflict markers. This is problematic: maybe it means
670 ;; the conflict has been resolved and we should immediately call "svn
671 ;; resolved", or it means that the file's type does not allow Svn to
672 ;; use conflict markers in which case we don't really know what to do.
673 ;; So let's just punt for now.
674 nil)
675 (message "There are unresolved conflicts in this file")))
676
bc8c1bb4 Stefan Monnier2006-10-20 07:56:20 +0000677(defun vc-svn-parse-status (&optional filename)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000678 "Parse output of \"svn status\" command in the current buffer.
a6ae021f
GM
Glenn Morris2013-09-11 23:21:33 -0700679Set file properties accordingly. If FILENAME is non-nil, return its status."
680 (let (multifile file status propstat)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000681 (goto-char (point-min))
682 (while (re-search-forward
484c1b1f Eric S. Raymond2007-12-29 13:20:49 +0000683 ;; Ignore the files with status X.
245cacf1 Dan Nicolaescu2008-08-06 16:49:23 +0000684 "^\\(?:\\?\\|[ ACDGIMR!~][ MC][ L][ +][ S]..\\([ *]\\) +\\([-0-9]+\\) +\\([0-9?]+\\) +\\([^ ]+\\)\\) +" nil t)
c45b3be3
SM
Stefan Monnier2007-01-14 14:49:28 +0000685 ;; If the username contains spaces, the output format is ambiguous,
686 ;; so don't trust the output's filename unless we have to.
a6ae021f Glenn Morris2013-09-11 23:21:33 -0700687 (setq file (or (unless multifile filename)
c45b3be3 Stefan Monnier2007-01-14 14:49:28 +0000688 (expand-file-name
a6ae021f
GM
Glenn Morris2013-09-11 23:21:33 -0700689 (buffer-substring (point) (line-end-position))))
690 ;; If we are parsing the result of running status on a directory,
691 ;; there could be multiple files in the output.
692 ;; We assume that filename, if supplied, applies to the first
693 ;; listed file (ie, the directory). Bug#15322.
694 multifile t
695 status (char-after (line-beginning-position))
5dd4f3f7
GM
Glenn Morris2011-01-18 19:49:00 -0800696 ;; Status of the item's properties ([ MC]).
697 propstat (char-after (1+ (line-beginning-position))))
484c1b1f Eric S. Raymond2007-12-29 13:20:49 +0000698 (if (eq status ??)
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000699 (vc-file-setprop file 'vc-state 'unregistered)
fd140743
SM
Stefan Monnier2003-05-08 18:31:21 +0000700 ;; Use the last-modified revision, so that searching in vc-print-log
701 ;; output works.
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000702 (vc-file-setprop file 'vc-working-revision (match-string 3))
1c67a814 Stefan Monnier2007-09-28 18:45:43 +0000703 ;; Remember Svn's own status.
4f07b9f2
ER
Eric S. Raymond2008-01-01 18:40:42 +0000704 (vc-file-setprop file 'vc-svn-status status)
705 (vc-file-setprop
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000706 file 'vc-state
707 (cond
5dd4f3f7 Glenn Morris2011-01-18 19:49:00 -0800708 ((and (eq status ?\ ) (eq propstat ?\ ))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000709 (if (eq (char-after (match-beginning 1)) ?*)
3702367b Eric S. Raymond2008-05-01 19:13:16 +0000710 'needs-update
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000711 (vc-file-setprop file 'vc-checkout-time
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000712 (nth 5 (file-attributes file)))
713 'up-to-date))
714 ((eq status ?A)
fd140743 Stefan Monnier2003-05-08 18:31:21 +0000715 ;; If the file was actually copied, (match-string 2) is "-".
4f07b9f2
ER
Eric S. Raymond2008-01-01 18:40:42 +0000716 (vc-file-setprop file 'vc-working-revision "0")
717 (vc-file-setprop file 'vc-checkout-time 0)
484c1b1f Eric S. Raymond2007-12-29 13:20:49 +0000718 'added)
5dd4f3f7
GM
Glenn Morris2011-01-18 19:49:00 -0800719 ;; Conflict in contents or properties.
720 ((or (eq status ?C) (eq propstat ?C))
7fbb4797 Dan Nicolaescu2008-04-10 07:32:25 +0000721 (vc-file-setprop file 'vc-state 'conflict))
5dd4f3f7
GM
Glenn Morris2011-01-18 19:49:00 -0800722 ;; Modified contents or properties.
723 ((or (eq status ?M) (eq propstat ?M))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000724 (if (eq (char-after (match-beginning 1)) ?*)
725 'needs-merge
726 'edited))
722f037f Eric S. Raymond2007-12-28 18:16:55 +0000727 ((eq status ?I)
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000728 (vc-file-setprop file 'vc-state 'ignored))
e6c01f09 Stefan Monnier2009-05-05 04:17:27 +0000729 ((memq status '(?D ?R))
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000730 (vc-file-setprop file 'vc-state 'removed))
bc8c1bb4 Stefan Monnier2006-10-20 07:56:20 +0000731 (t 'edited)))))
245cacf1 Dan Nicolaescu2008-08-06 16:49:23 +0000732 (when filename (vc-file-getprop filename 'vc-state))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000733
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000734(defun vc-svn-valid-symbolic-tag-name-p (tag)
735 "Return non-nil if TAG is a valid symbolic tag name."
736 ;; According to the SVN manual, a valid symbolic tag must start with
737 ;; an uppercase or lowercase letter and can contain uppercase and
738 ;; lowercase letters, digits, `-', and `_'.
739 (and (string-match "^[a-zA-Z]" tag)
740 (not (string-match "[^a-z0-9A-Z-_]" tag))))
741
5b5afd50
ER
Eric S. Raymond2007-10-10 19:39:23 +0000742(defun vc-svn-valid-revision-number-p (tag)
743 "Return non-nil if TAG is a valid revision number."
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000744 (and (string-match "^[0-9]" tag)
745 (not (string-match "[^0-9]" tag))))
746
17a5a301
SM
Stefan Monnier2004-12-13 06:30:40 +0000747;; Support for `svn annotate'
748
749(defun vc-svn-annotate-command (file buf &optional rev)
b5a0603e
OF
Oscar Fuentes2015-02-26 15:46:12 +0100750 (apply #'vc-svn-command buf 'async file "annotate"
751 (append (vc-switches 'svn 'annotate)
752 (if rev (list (concat "-r" rev))))))
17a5a301
SM
Stefan Monnier2004-12-13 06:30:40 +0000753
754(defun vc-svn-annotate-time-of-rev (rev)
da6062e6 Paul Eggert2011-11-14 23:55:13 -0800755 ;; Arbitrarily assume 10 commits per day.
17a5a301
SM
Stefan Monnier2004-12-13 06:30:40 +0000756 (/ (string-to-number rev) 10.0))
757
e53ac718
DN
Dan Nicolaescu2008-06-25 02:45:50 +0000758(defvar vc-annotate-parent-rev)
759
17a5a301
SM
Stefan Monnier2004-12-13 06:30:40 +0000760(defun vc-svn-annotate-current-time ()
761 (vc-svn-annotate-time-of-rev vc-annotate-parent-rev))
762
763(defconst vc-svn-annotate-re "[ \t]*\\([0-9]+\\)[ \t]+[^\t ]+ ")
764
765(defun vc-svn-annotate-time ()
766 (when (looking-at vc-svn-annotate-re)
767 (goto-char (match-end 0))
768 (vc-svn-annotate-time-of-rev (match-string 1))))
769
770(defun vc-svn-annotate-extract-revision-at-line ()
771 (save-excursion
772 (beginning-of-line)
773 (if (looking-at vc-svn-annotate-re) (match-string 1))))
774
8228a275
MH
Mark A. Hershberger2010-02-05 14:20:17 -0500775(defun vc-svn-revision-table (files)
776 (let ((vc-svn-revisions '()))
777 (with-current-buffer "*vc*"
778 (vc-svn-command nil 0 files "log" "-q")
779 (goto-char (point-min))
780 (forward-line)
781 (let ((start (point-min))
782 (loglines (buffer-substring-no-properties (point-min)
783 (point-max))))
784 (while (string-match "^r\\([0-9]+\\) " loglines)
785 (push (match-string 1 loglines) vc-svn-revisions)
786 (setq start (+ start (match-end 0)))
787 (setq loglines (buffer-substring-no-properties start (point-max)))))
788 vc-svn-revisions)))
789
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000790(provide 'vc-svn)
791
792;;; vc-svn.el ends here