* lisp/net/tramp-cache.el (tramp-set-file-property): Fix code typo.
[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"
f8006664
FP
Fabrice Popineau2015-07-07 18:06:53 +0300282 (let ((defdir (expand-file-name default-directory))
283 (svn-prog (executable-find "svn")))
284 (when (and (fboundp 'w32-application-type)
285 (eq (w32-application-type svn-prog) 'msys))
286 (setq defdir
287 (replace-regexp-in-string "^\\(.\\):/" "/\\1/"
288 defdir)))
7baae811
EZ
Eli Zaretskii2015-06-27 14:27:23 +0300289 (concat (if (and (stringp defdir)
290 (eq (aref defdir 0) ?/))
291 "file://"
292 ;; MS-Windows files d:/foo/bar need to
293 ;; begin with 3 leading slashes.
294 "file:///")
295 defdir
296 "SVN"))))
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000297
e658d75c
GM
Glenn Morris2013-05-28 00:01:59 -0700298(autoload 'vc-switches "vc")
299
9e9e3432 Eric S. Raymond2014-12-01 07:08:40 -0500300(defun vc-svn-register (files &optional _comment)
8cdd17b4
ER
Eric S. Raymond2007-07-18 16:32:40 +0000301 "Register FILES into the SVN version-control system.
302The COMMENT argument is ignored This does an add but not a commit.
c8d6b4bc
GM
Glenn Morris2008-12-04 07:03:53 +0000303Passes either `vc-svn-register-switches' or `vc-register-switches'
304to the SVN command."
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000305 (apply 'vc-svn-command nil 0 files "add" (vc-switches 'SVN 'register)))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000306
b5a53795
KP
Karl Pflästerer2011-02-11 20:12:53 -0500307(defun vc-svn-root (file)
308 (vc-find-root file vc-svn-admin-directory))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000309
b5a53795
KP
Karl Pflästerer2011-02-11 20:12:53 -0500310(defalias 'vc-svn-responsible-p 'vc-svn-root)
311
f83109f0 Eric S. Raymond2014-11-20 02:37:06 -0500312(defun vc-svn-checkin (files comment &optional _extra-args-ignored)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000313 "SVN-specific version of `vc-backend-checkin'."
5129f10c Karl Fogel2004-06-04 04:37:10 +0000314 (let ((status (apply
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000315 'vc-svn-command nil 1 files "ci"
5129f10c Karl Fogel2004-06-04 04:37:10 +0000316 (nconc (list "-m" comment) (vc-switches 'SVN 'checkin)))))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000317 (set-buffer "*vc*")
318 (goto-char (point-min))
319 (unless (equal status 0)
320 ;; Check checkin problem.
321 (cond
fd140743 Stefan Monnier2003-05-08 18:31:21 +0000322 ((search-forward "Transaction is out of date" nil t)
8cdd17b4
ER
Eric S. Raymond2007-07-18 16:32:40 +0000323 (mapc (lambda (file) (vc-file-setprop file 'vc-state 'needs-merge))
324 files)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000325 (error (substitute-command-keys
326 (concat "Up-to-date check failed: "
327 "type \\[vc-next-action] to merge in changes"))))
328 (t
329 (pop-to-buffer (current-buffer))
330 (goto-char (point-min))
331 (shrink-window-if-larger-than-buffer)
332 (error "Check-in failed"))))
333 ;; Update file properties
334 ;; (vc-file-setprop
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000335 ;; file 'vc-working-revision
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000336 ;; (vc-parse-buffer "^\\(new\\|initial\\) revision: \\([0-9.]+\\)" 2))
337 ))
338
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000339(defun vc-svn-find-revision (file rev buffer)
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000340 "SVN-specific retrieval of a specified version into a buffer."
04473f67
MA
Michael Albinus2009-08-25 09:05:07 +0000341 (let (process-file-side-effects)
342 (apply 'vc-svn-command
343 buffer 0 file
344 "cat"
345 (and rev (not (string= rev ""))
346 (concat "-r" rev))
347 (vc-switches 'SVN 'checkout))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000348
c799337f Dmitry Gutov2014-10-03 17:15:05 +0400349(defun vc-svn-ignore (file &optional directory remove)
ab419665 Xue Fuqiao2013-08-04 10:55:45 +0800350 "Ignore FILE under Subversion.
63191d9f Xue Fuqiao2013-09-04 08:31:13 +0800351FILE is a file wildcard, relative to the root directory of DIRECTORY."
c799337f
DG
Dmitry Gutov2014-10-03 17:15:05 +0400352 (let* ((ignores (vc-svn-ignore-completion-table directory))
353 (file (file-relative-name file directory))
354 (ignores (if remove
355 (delete file ignores)
356 (push file ignores))))
357 (vc-svn-command nil 0 nil nil "propset" "svn:ignore"
358 (mapconcat #'identity ignores "\n")
359 (expand-file-name directory))))
360
361(defun vc-svn-ignore-completion-table (directory)
362 "Return the list of ignored files in DIRECTORY."
363 (with-temp-buffer
364 (vc-svn-command t t nil "propget" "svn:ignore" (expand-file-name directory))
365 (split-string (buffer-string))))
ab419665 Xue Fuqiao2013-08-04 10:55:45 +0800366
34ca0f4c
XF
Xue Fuqiao2013-10-05 07:47:00 +0800367(defun vc-svn-find-admin-dir (file)
368 "Return the administrative directory of FILE."
369 (expand-file-name vc-svn-admin-directory (vc-svn-root file)))
370
e7e9dbcc Eric S. Raymond2014-11-20 03:52:24 -0500371(defun vc-svn-checkout (file &optional rev)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000372 (message "Checking out %s..." file)
373 (with-current-buffer (or (get-file-buffer file) (current-buffer))
e7e9dbcc Eric S. Raymond2014-11-20 03:52:24 -0500374 (vc-svn-update file rev (vc-switches 'SVN 'checkout)))
77bf3f54 Dan Nicolaescu2009-06-23 06:35:40 +0000375 (vc-mode-line file 'SVN)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000376 (message "Checking out %s...done" file))
377
e7e9dbcc Eric S. Raymond2014-11-20 03:52:24 -0500378(defun vc-svn-update (file rev switches)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000379 (if (and (file-exists-p file) (not rev))
fc2fb30c
SM
Stefan Monnier2007-02-19 19:42:10 +0000380 ;; If no revision was specified, there's nothing to do.
381 nil
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000382 ;; Check out a particular version (or recreate the file).
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000383 (vc-file-setprop file 'vc-working-revision nil)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000384 (apply 'vc-svn-command nil 0 file
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000385 "update"
5cc7cb96
SM
Stefan Monnier2003-07-04 22:21:45 +0000386 (cond
387 ((null rev) "-rBASE")
388 ((or (eq rev t) (equal rev "")) nil)
389 (t (concat "-r" rev)))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000390 switches)))
391
3bdc13e4
SM
Stefan Monnier2003-05-14 19:38:39 +0000392(defun vc-svn-delete-file (file)
393 (vc-svn-command nil 0 file "remove"))
394
2766aaaf
SM
Stefan Monnier2003-05-09 14:13:40 +0000395(defun vc-svn-rename-file (old new)
396 (vc-svn-command nil 0 new "move" (file-relative-name old)))
397
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000398(defun vc-svn-revert (file &optional contents-done)
399 "Revert FILE to the version it was based on."
400 (unless contents-done
fc2fb30c Stefan Monnier2007-02-19 19:42:10 +0000401 (vc-svn-command nil 0 file "revert")))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000402
d17bae90
ER
Eric S. Raymond2014-12-01 11:41:45 -0500403(defun vc-svn-merge-file (file)
404 "Accept a file merge request, prompting for revisions."
405 (let* ((first-revision
406 (vc-read-revision
407 (concat "Merge " file
408 " from SVN revision "
409 "(default news on current branch): ")
410 (list file)
411 'SVN))
412 second-revision
413 status)
414 (cond
415 ((string= first-revision "")
416 (setq status (vc-svn-merge-news file)))
417 (t
418 (setq second-revision
419 (vc-read-revision
420 "Second SVN revision: "
421 (list file) 'SVN nil
422 first-revision))
423 (setq status (vc-svn-merge file first-revision second-revision))))
424 status))
425
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000426(defun vc-svn-merge (file first-version &optional second-version)
427 "Merge changes into current working copy of FILE.
428The changes are between FIRST-VERSION and SECOND-VERSION."
429 (vc-svn-command nil 0 file
c217cb04 Stefan Monnier2003-05-05 16:13:04 +0000430 "merge"
02610d0e Stefan Monnier2003-05-05 16:13:39 +0000431 "-r" (if second-version
c217cb04
SM
Stefan Monnier2003-05-05 16:13:04 +0000432 (concat first-version ":" second-version)
433 first-version))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000434 (vc-file-setprop file 'vc-state 'edited)
435 (with-current-buffer (get-buffer "*vc*")
436 (goto-char (point-min))
c217cb04
SM
Stefan Monnier2003-05-05 16:13:04 +0000437 (if (looking-at "C ")
438 1 ; signal conflict
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000439 0))) ; signal success
440
441(defun vc-svn-merge-news (file)
442 "Merge in any new changes made to FILE."
443 (message "Merging changes into %s..." file)
ac3f4c6f Eric S. Raymond2007-10-10 18:52:45 +0000444 ;; (vc-file-setprop file 'vc-working-revision nil)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000445 (vc-file-setprop file 'vc-checkout-time 0)
9a4de110 Glenn Morris2011-11-09 21:36:48 -0500446 (vc-svn-command nil 0 file "update")
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000447 ;; Analyze the merge result reported by SVN, and set
448 ;; file properties accordingly.
449 (with-current-buffer (get-buffer "*vc*")
450 (goto-char (point-min))
5b5afd50 Eric S. Raymond2007-10-10 19:39:23 +0000451 ;; get new working revision
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000452 (if (re-search-forward
1468d754 Stefan Monnier2003-05-05 16:06:10 +0000453 "^\\(Updated to\\|At\\) revision \\([0-9]+\\)" nil t)
ac3f4c6f
ER
Eric S. Raymond2007-10-10 18:52:45 +0000454 (vc-file-setprop file 'vc-working-revision (match-string 2))
455 (vc-file-setprop file 'vc-working-revision nil))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000456 ;; get file status
1468d754 Stefan Monnier2003-05-05 16:06:10 +0000457 (goto-char (point-min))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000458 (prog1
1468d754 Stefan Monnier2003-05-05 16:06:10 +0000459 (if (looking-at "At revision")
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000460 0 ;; there were no news; indicate success
461 (if (re-search-forward
459b1fe4
SM
Stefan Monnier2007-02-07 23:02:12 +0000462 ;; Newer SVN clients have 3 columns of chars (one for the
463 ;; file's contents, then second for its properties, and the
464 ;; third for lock-grabbing info), before the 2 spaces.
465 ;; We also used to match the filename in column 0 without any
466 ;; meta-info before it, but I believe this can never happen.
467 (concat "^\\(\\([ACGDU]\\)\\(.[B ]\\)? \\)"
c2d07557 Chong Yidong2012-11-17 15:06:57 +0800468 (regexp-quote (file-relative-name file)))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000469 nil t)
470 (cond
471 ;; Merge successful, we are in sync with repository now
459b1fe4 Stefan Monnier2007-02-07 23:02:12 +0000472 ((string= (match-string 2) "U")
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000473 (vc-file-setprop file 'vc-state 'up-to-date)
474 (vc-file-setprop file 'vc-checkout-time
475 (nth 5 (file-attributes file)))
476 0);; indicate success to the caller
477 ;; Merge successful, but our own changes are still in the file
459b1fe4 Stefan Monnier2007-02-07 23:02:12 +0000478 ((string= (match-string 2) "G")
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000479 (vc-file-setprop file 'vc-state 'edited)
480 0);; indicate success to the caller
481 ;; Conflicts detected!
482 (t
483 (vc-file-setprop file 'vc-state 'edited)
484 1);; signal the error to the caller
485 )
486 (pop-to-buffer "*vc*")
487 (error "Couldn't analyze svn update result")))
488 (message "Merging changes into %s...done" file))))
489
9c750eba Stefan Monnier2013-09-04 17:09:42 -0400490(defun vc-svn-modify-change-comment (_files rev comment)
42a0a135
ER
Eric S. Raymond2008-01-02 00:42:37 +0000491 "Modify the change comments for a specified REV.
492You must have ssh access to the repository host, and the directory Emacs
e09deae9 Chong Yidong2008-12-03 03:25:15 +0000493uses locally for temp files must also be writable by you on that host.
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000494This is only supported if the repository access method is either file://
495or svn+ssh://."
496 (let (tempfile host remotefile directory fileurl-p)
42a0a135 Eric S. Raymond2008-01-02 00:42:37 +0000497 (with-temp-buffer
9a4de110 Glenn Morris2011-11-09 21:36:48 -0500498 (vc-svn-command (current-buffer) 0 nil "info")
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000499 (goto-char (point-min))
500 (unless (re-search-forward "Repository Root: \\(file://\\(/.*\\)\\)\\|\\(svn\\+ssh://\\([^/]+\\)\\(/.*\\)\\)" nil t)
501 (error "Repository information is unavailable"))
502 (if (match-string 1)
503 (progn
504 (setq fileurl-p t)
505 (setq directory (match-string 2)))
506 (setq host (match-string 4))
507 (setq directory (match-string 5))
508 (setq remotefile (concat host ":" tempfile))))
509 (with-temp-file (setq tempfile (make-temp-file user-mail-address))
510 (insert comment))
511 (if fileurl-p
512 ;; Repository Root is a local file.
513 (progn
514 (unless (vc-do-command
2888a97e Eric S. Raymond2008-05-10 13:27:16 +0000515 "*vc*" 0 "svnadmin" nil
def61be2 Juanma Barranquero2008-06-16 08:55:56 +0000516 "setlog" "--bypass-hooks" directory
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000517 "-r" rev (format "%s" tempfile))
518 (error "Log edit failed"))
519 (delete-file tempfile))
520
521 ;; Remote repository, using svn+ssh.
2888a97e Eric S. Raymond2008-05-10 13:27:16 +0000522 (unless (vc-do-command "*vc*" 0 "scp" nil "-q" tempfile remotefile)
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000523 (error "Copy of comment to %s failed" remotefile))
524 (unless (vc-do-command
2888a97e Eric S. Raymond2008-05-10 13:27:16 +0000525 "*vc*" 0 "ssh" nil "-q" host
fd064451
DN
Dan Nicolaescu2008-04-09 03:38:39 +0000526 (format "svnadmin setlog --bypass-hooks %s -r %s %s; rm %s"
527 directory rev tempfile tempfile))
528 (error "Log edit failed")))))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000529
530;;;
531;;; History functions
532;;;
533
def61be2
JB
Juanma Barranquero2008-06-16 08:55:56 +0000534(defvar log-view-per-file-logs)
535
6653c6b7
DN
Dan Nicolaescu2008-06-15 14:58:24 +0000536(define-derived-mode vc-svn-log-view-mode log-view-mode "SVN-Log-View"
537 (require 'add-log)
538 (set (make-local-variable 'log-view-per-file-logs) nil))
539
e658d75c
GM
Glenn Morris2013-05-28 00:01:59 -0700540(autoload 'vc-setup-buffer "vc-dispatcher")
541
9c750eba Stefan Monnier2013-09-04 17:09:42 -0400542(defun vc-svn-print-log (files buffer &optional _shortlog start-revision limit)
bb7cdf58
GM
Glenn Morris2013-04-24 00:52:00 -0700543 "Print commit log associated with FILES into specified BUFFER.
544SHORTLOG is ignored.
545If START-REVISION is non-nil, it is the newest revision to show.
546If LIMIT is non-nil, show no more than this many entries."
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000547 (save-current-buffer
b349012b Juanma Barranquero2004-04-20 16:49:26 +0000548 (vc-setup-buffer buffer)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000549 (let ((inhibit-read-only t))
550 (goto-char (point-min))
13b56025
ER
Eric S. Raymond2007-12-27 03:10:52 +0000551 (if files
552 (dolist (file files)
553 (insert "Working file: " file "\n")
6616006b
DN
Dan Nicolaescu2009-11-15 20:28:58 +0000554 (apply
555 'vc-svn-command
13b56025
ER
Eric S. Raymond2007-12-27 03:10:52 +0000556 buffer
557 'async
13b56025
ER
Eric S. Raymond2007-12-27 03:10:52 +0000558 (list file)
559 "log"
662c5698
DN
Dan Nicolaescu2009-12-07 09:02:11 +0000560 (append
561 (list
562 (if start-revision
90b4237a Glenn Morris2013-04-24 00:59:29 -0700563 (format "-r%s:1" start-revision)
662c5698
DN
Dan Nicolaescu2009-12-07 09:02:11 +0000564 ;; By default Subversion only shows the log up to the
565 ;; working revision, whereas we also want the log of the
566 ;; subsequent commits. At least that's what the
567 ;; vc-cvs.el code does.
568 "-rHEAD:0"))
1db3226b Glenn Morris2010-01-14 19:54:36 -0800569 (when limit (list "--limit" (format "%s" limit))))))
13b56025 Eric S. Raymond2007-12-27 03:10:52 +0000570 ;; Dump log for the entire directory.
662c5698
DN
Dan Nicolaescu2009-12-07 09:02:11 +0000571 (apply 'vc-svn-command buffer 0 nil "log"
572 (append
573 (list
574 (if start-revision (format "-r%s" start-revision) "-rHEAD:0"))
1db3226b Glenn Morris2010-01-14 19:54:36 -0800575 (when limit (list "--limit" (format "%s" limit)))))))))
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000576
01b97f9d Dmitry Gutov2014-12-14 12:49:08 +0200577(defun vc-svn-diff (files &optional oldvers newvers buffer async)
5b5afd50 Eric S. Raymond2007-10-10 19:39:23 +0000578 "Get a difference report using SVN between two revisions of fileset FILES."
22b5692c
NR
Nick Roberts2009-02-04 10:49:04 +0000579 (and oldvers
580 (not newvers)
581 files
582 (catch 'no
583 (dolist (f files)
584 (or (equal oldvers (vc-working-revision f))
585 (throw 'no nil)))
586 t)
587 ;; Use nil rather than the current revision because svn handles
588 ;; it better (i.e. locally). Note that if _any_ of the files
589 ;; has a different revision, we fetch the lot, which is
590 ;; obviously sub-optimal.
591 (setq oldvers nil))
3c07d7f0 Eric S. Raymond2014-12-13 06:15:33 -0500592 (setq async (and async (or oldvers newvers))) ; Svn diffs those locally.
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000593 (let* ((switches
f9d1f3be
SM
Stefan Monnier2004-08-23 18:23:52 +0000594 (if vc-svn-diff-switches
595 (vc-switches 'SVN 'diff)
ed68f651 Sam Steingold2011-01-25 11:01:53 -0500596 (list (concat "--diff-cmd=" diff-command) "-x"
3c07d7f0 Eric S. Raymond2014-12-13 06:15:33 -0500597 (mapconcat 'identity (vc-switches nil 'diff) " ")))))
b349012b Juanma Barranquero2004-04-20 16:49:26 +0000598 (apply 'vc-svn-command buffer
2766aaaf Stefan Monnier2003-05-09 14:13:40 +0000599 (if async 'async 0)
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000600 files "diff"
2766aaaf Stefan Monnier2003-05-09 14:13:40 +0000601 (append
f9d1f3be Stefan Monnier2004-08-23 18:23:52 +0000602 switches
2766aaaf
SM
Stefan Monnier2003-05-09 14:13:40 +0000603 (when oldvers
604 (list "-r" (if newvers (concat oldvers ":" newvers)
605 oldvers)))))
fd140743
SM
Stefan Monnier2003-05-08 18:31:21 +0000606 (if async 1 ; async diff => pessimistic assumption
607 ;; For some reason `svn diff' does not return a useful
608 ;; status w.r.t whether the diff was empty or not.
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000609 (buffer-size (get-buffer buffer)))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000610
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000611;;;
370fded4 Eric S. Raymond2008-05-15 17:38:50 +0000612;;; Tag system
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000613;;;
614
370fded4 Eric S. Raymond2008-05-15 17:38:50 +0000615(defun vc-svn-create-tag (dir name branchp)
5b5afd50 Eric S. Raymond2007-10-10 19:39:23 +0000616 "Assign to DIR's current revision a given NAME.
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000617If BRANCHP is non-nil, the name is created as a branch (and the current
5cc7cb96
SM
Stefan Monnier2003-07-04 22:21:45 +0000618workspace is immediately moved to that new branch).
619NAME is assumed to be a URL."
620 (vc-svn-command nil 0 dir "copy" name)
370fded4 Eric S. Raymond2008-05-15 17:38:50 +0000621 (when branchp (vc-svn-retrieve-tag dir name nil)))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000622
aa30fa6f Glenn Morris2013-09-11 23:55:15 -0700623(defun vc-svn-retrieve-tag (dir name _update)
370fded4
ER
Eric S. Raymond2008-05-15 17:38:50 +0000624 "Retrieve a tag at and below DIR.
625NAME is the name of the tag; if it is empty, do a `svn update'.
5cc7cb96
SM
Stefan Monnier2003-07-04 22:21:45 +0000626If UPDATE is non-nil, then update (resynch) any affected buffers.
627NAME is assumed to be a URL."
628 (vc-svn-command nil 0 dir "switch" name)
629 ;; FIXME: parse the output and obey `update'.
630 )
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000631
632;;;
633;;; Miscellaneous
634;;;
635
636;; Subversion makes backups for us, so don't bother.
77bf3f54
DN
Dan Nicolaescu2009-06-23 06:35:40 +0000637;; (defun vc-svn-make-version-backups-p (file)
638;; "Return non-nil if version backups should be made for FILE."
2a81c5d9 Eric S. Raymond2014-12-01 10:11:42 -0500639;; nil)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000640
641(defun vc-svn-check-headers ()
642 "Check if the current file has any headers in it."
643 (save-excursion
644 (goto-char (point-min))
645 (re-search-forward "\\$[A-Za-z\300-\326\330-\366\370-\377]+\
646\\(: [\t -#%-\176\240-\377]*\\)?\\$" nil t)))
647
648
649;;;
650;;; Internal functions
651;;;
652
8cdd17b4 Eric S. Raymond2007-07-18 16:32:40 +0000653(defun vc-svn-command (buffer okstatus file-or-list &rest flags)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000654 "A wrapper around `vc-do-command' for use in vc-svn.el.
655The difference to vc-do-command is that this function always invokes `svn',
31db8c31 Glenn Morris2013-02-10 17:07:05 -0800656and that it passes `vc-svn-global-switches' to it before FLAGS."
9a4de110 Glenn Morris2011-11-09 21:36:48 -0500657 (apply 'vc-do-command (or buffer "*vc*") okstatus vc-svn-program file-or-list
31db8c31
GM
Glenn Morris2013-02-10 17:07:05 -0800658 (if (stringp vc-svn-global-switches)
659 (cons vc-svn-global-switches flags)
660 (append vc-svn-global-switches flags))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000661
1c67a814
SM
Stefan Monnier2007-09-28 18:45:43 +0000662(defun vc-svn-resolve-when-done ()
663 "Call \"svn resolved\" if the conflict markers have been removed."
664 (save-excursion
665 (goto-char (point-min))
54648b5c
DN
Dan Nicolaescu2008-01-15 04:37:20 +0000666 (unless (re-search-forward "^<<<<<<< " nil t)
667 (vc-svn-command nil 0 buffer-file-name "resolved")
668 ;; Remove the hook so that it is not called multiple times.
669 (remove-hook 'after-save-hook 'vc-svn-resolve-when-done t))))
1c67a814
SM
Stefan Monnier2007-09-28 18:45:43 +0000670
671;; Inspired by vc-arch-find-file-hook.
672(defun vc-svn-find-file-hook ()
673 (when (eq ?C (vc-file-getprop buffer-file-name 'vc-svn-status))
674 ;; If the file is marked as "conflicted", then we should try and call
675 ;; "svn resolved" when applicable.
676 (if (save-excursion
677 (goto-char (point-min))
678 (re-search-forward "^<<<<<<< " nil t))
679 ;; There are conflict markers.
680 (progn
28e4e2b4 Dan Nicolaescu2008-01-16 06:22:59 +0000681 (smerge-start-session)
1c67a814
SM
Stefan Monnier2007-09-28 18:45:43 +0000682 (add-hook 'after-save-hook 'vc-svn-resolve-when-done nil t))
683 ;; There are no conflict markers. This is problematic: maybe it means
684 ;; the conflict has been resolved and we should immediately call "svn
685 ;; resolved", or it means that the file's type does not allow Svn to
686 ;; use conflict markers in which case we don't really know what to do.
687 ;; So let's just punt for now.
688 nil)
689 (message "There are unresolved conflicts in this file")))
690
bc8c1bb4 Stefan Monnier2006-10-20 07:56:20 +0000691(defun vc-svn-parse-status (&optional filename)
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000692 "Parse output of \"svn status\" command in the current buffer.
a6ae021f
GM
Glenn Morris2013-09-11 23:21:33 -0700693Set file properties accordingly. If FILENAME is non-nil, return its status."
694 (let (multifile file status propstat)
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000695 (goto-char (point-min))
696 (while (re-search-forward
484c1b1f Eric S. Raymond2007-12-29 13:20:49 +0000697 ;; Ignore the files with status X.
245cacf1 Dan Nicolaescu2008-08-06 16:49:23 +0000698 "^\\(?:\\?\\|[ ACDGIMR!~][ MC][ L][ +][ S]..\\([ *]\\) +\\([-0-9]+\\) +\\([0-9?]+\\) +\\([^ ]+\\)\\) +" nil t)
c45b3be3
SM
Stefan Monnier2007-01-14 14:49:28 +0000699 ;; If the username contains spaces, the output format is ambiguous,
700 ;; so don't trust the output's filename unless we have to.
a6ae021f Glenn Morris2013-09-11 23:21:33 -0700701 (setq file (or (unless multifile filename)
c45b3be3 Stefan Monnier2007-01-14 14:49:28 +0000702 (expand-file-name
a6ae021f
GM
Glenn Morris2013-09-11 23:21:33 -0700703 (buffer-substring (point) (line-end-position))))
704 ;; If we are parsing the result of running status on a directory,
705 ;; there could be multiple files in the output.
706 ;; We assume that filename, if supplied, applies to the first
707 ;; listed file (ie, the directory). Bug#15322.
708 multifile t
709 status (char-after (line-beginning-position))
5dd4f3f7
GM
Glenn Morris2011-01-18 19:49:00 -0800710 ;; Status of the item's properties ([ MC]).
711 propstat (char-after (1+ (line-beginning-position))))
484c1b1f Eric S. Raymond2007-12-29 13:20:49 +0000712 (if (eq status ??)
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000713 (vc-file-setprop file 'vc-state 'unregistered)
fd140743
SM
Stefan Monnier2003-05-08 18:31:21 +0000714 ;; Use the last-modified revision, so that searching in vc-print-log
715 ;; output works.
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000716 (vc-file-setprop file 'vc-working-revision (match-string 3))
1c67a814 Stefan Monnier2007-09-28 18:45:43 +0000717 ;; Remember Svn's own status.
4f07b9f2
ER
Eric S. Raymond2008-01-01 18:40:42 +0000718 (vc-file-setprop file 'vc-svn-status status)
719 (vc-file-setprop
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000720 file 'vc-state
721 (cond
5dd4f3f7 Glenn Morris2011-01-18 19:49:00 -0800722 ((and (eq status ?\ ) (eq propstat ?\ ))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000723 (if (eq (char-after (match-beginning 1)) ?*)
3702367b Eric S. Raymond2008-05-01 19:13:16 +0000724 'needs-update
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000725 (vc-file-setprop file 'vc-checkout-time
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000726 (nth 5 (file-attributes file)))
727 'up-to-date))
728 ((eq status ?A)
fd140743 Stefan Monnier2003-05-08 18:31:21 +0000729 ;; If the file was actually copied, (match-string 2) is "-".
4f07b9f2
ER
Eric S. Raymond2008-01-01 18:40:42 +0000730 (vc-file-setprop file 'vc-working-revision "0")
731 (vc-file-setprop file 'vc-checkout-time 0)
484c1b1f Eric S. Raymond2007-12-29 13:20:49 +0000732 'added)
5dd4f3f7
GM
Glenn Morris2011-01-18 19:49:00 -0800733 ;; Conflict in contents or properties.
734 ((or (eq status ?C) (eq propstat ?C))
7fbb4797 Dan Nicolaescu2008-04-10 07:32:25 +0000735 (vc-file-setprop file 'vc-state 'conflict))
5dd4f3f7
GM
Glenn Morris2011-01-18 19:49:00 -0800736 ;; Modified contents or properties.
737 ((or (eq status ?M) (eq propstat ?M))
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000738 (if (eq (char-after (match-beginning 1)) ?*)
739 'needs-merge
740 'edited))
722f037f Eric S. Raymond2007-12-28 18:16:55 +0000741 ((eq status ?I)
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000742 (vc-file-setprop file 'vc-state 'ignored))
e6c01f09 Stefan Monnier2009-05-05 04:17:27 +0000743 ((memq status '(?D ?R))
4f07b9f2 Eric S. Raymond2008-01-01 18:40:42 +0000744 (vc-file-setprop file 'vc-state 'removed))
bc8c1bb4 Stefan Monnier2006-10-20 07:56:20 +0000745 (t 'edited)))))
245cacf1 Dan Nicolaescu2008-08-06 16:49:23 +0000746 (when filename (vc-file-getprop filename 'vc-state))))
1fd3454a Stefan Monnier2003-05-05 15:42:27 +0000747
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000748(defun vc-svn-valid-symbolic-tag-name-p (tag)
749 "Return non-nil if TAG is a valid symbolic tag name."
750 ;; According to the SVN manual, a valid symbolic tag must start with
751 ;; an uppercase or lowercase letter and can contain uppercase and
752 ;; lowercase letters, digits, `-', and `_'.
753 (and (string-match "^[a-zA-Z]" tag)
754 (not (string-match "[^a-z0-9A-Z-_]" tag))))
755
5b5afd50
ER
Eric S. Raymond2007-10-10 19:39:23 +0000756(defun vc-svn-valid-revision-number-p (tag)
757 "Return non-nil if TAG is a valid revision number."
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000758 (and (string-match "^[0-9]" tag)
759 (not (string-match "[^0-9]" tag))))
760
17a5a301
SM
Stefan Monnier2004-12-13 06:30:40 +0000761;; Support for `svn annotate'
762
763(defun vc-svn-annotate-command (file buf &optional rev)
b5a0603e
OF
Oscar Fuentes2015-02-26 15:46:12 +0100764 (apply #'vc-svn-command buf 'async file "annotate"
765 (append (vc-switches 'svn 'annotate)
766 (if rev (list (concat "-r" rev))))))
17a5a301
SM
Stefan Monnier2004-12-13 06:30:40 +0000767
768(defun vc-svn-annotate-time-of-rev (rev)
da6062e6 Paul Eggert2011-11-14 23:55:13 -0800769 ;; Arbitrarily assume 10 commits per day.
17a5a301
SM
Stefan Monnier2004-12-13 06:30:40 +0000770 (/ (string-to-number rev) 10.0))
771
e53ac718
DN
Dan Nicolaescu2008-06-25 02:45:50 +0000772(defvar vc-annotate-parent-rev)
773
17a5a301
SM
Stefan Monnier2004-12-13 06:30:40 +0000774(defun vc-svn-annotate-current-time ()
775 (vc-svn-annotate-time-of-rev vc-annotate-parent-rev))
776
777(defconst vc-svn-annotate-re "[ \t]*\\([0-9]+\\)[ \t]+[^\t ]+ ")
778
779(defun vc-svn-annotate-time ()
780 (when (looking-at vc-svn-annotate-re)
781 (goto-char (match-end 0))
782 (vc-svn-annotate-time-of-rev (match-string 1))))
783
784(defun vc-svn-annotate-extract-revision-at-line ()
785 (save-excursion
786 (beginning-of-line)
787 (if (looking-at vc-svn-annotate-re) (match-string 1))))
788
8228a275
MH
Mark A. Hershberger2010-02-05 14:20:17 -0500789(defun vc-svn-revision-table (files)
790 (let ((vc-svn-revisions '()))
791 (with-current-buffer "*vc*"
792 (vc-svn-command nil 0 files "log" "-q")
793 (goto-char (point-min))
794 (forward-line)
795 (let ((start (point-min))
796 (loglines (buffer-substring-no-properties (point-min)
797 (point-max))))
798 (while (string-match "^r\\([0-9]+\\) " loglines)
799 (push (match-string 1 loglines) vc-svn-revisions)
800 (setq start (+ start (match-end 0)))
801 (setq loglines (buffer-substring-no-properties start (point-max)))))
802 vc-svn-revisions)))
803
1fd3454a
SM
Stefan Monnier2003-05-05 15:42:27 +0000804(provide 'vc-svn)
805
806;;; vc-svn.el ends here