protocol revision 299742
1This file documents version 2 of the svn protocol.
2
31. Syntactic structure
4----------------------
5
6The Subversion protocol is specified in terms of the following
7syntactic elements, specified using ABNF [RFC 2234]:
8
9  item   = word / number / string / list
10  word   = ALPHA *(ALPHA / DIGIT / "-") space
11  number = 1*DIGIT space
12  string = 1*DIGIT ":" *OCTET space
13         ; digits give the byte count of the *OCTET portion
14  list   = "(" space *item ")" space
15  space  = 1*(SP / LF)
16
17Here is an example item showing each of the syntactic elements:
18
19  ( word 22 6:string ( sublist ) )
20
21All items end with mandatory whitespace.  (In the above example, a
22newline provides the terminating whitespace for the outer list.)  It
23is possible to parse an item without knowing its type in advance.
24
25Lists are not constrained to contain items of the same type.  Lists
26can be used for tuples, optional tuples, or arrays.  A tuple is a list
27expected to contain a fixed number of items, generally of differing
28types.  An optional tuple is a list containing either zero or a fixed
29number of items (thus "optional" here does not refer to the list's
30presence or absence, but to the presence or absence of its contents).
31An array is a list containing zero or more items of the same type.
32
33Words are used for enumerated protocol values, while strings are used
34for text or binary data of interest to the Subversion client or
35server.  Words are case-sensitive.
36
37For convenience, this specification will define prototypes for data
38items using a syntax like:
39
40  example: ( literal ( data:string ... ) )
41
42A simple word such as "literal", with no colon, denotes a literal
43word.  A choice of words may be given with "|" separating the choices.
44"name:type" specifies a parameter with the given type.
45
46A type is "word", "number", "string", "list", or the name of another
47prototype.  Parentheses denote a tuple, unless the parentheses contain
48ellipses, in which case the parentheses denote an array containing
49zero or more elements matching the prototype preceding the ellipses.
50
51If a tuple has an optional part after the fixed part, a '?' marks
52places where the tuple is allowed to end.  The following tuple could
53contain one, three, or four or more items:
54
55  example: ( fixed:string ? opt1:number opt2:string ? opt3:number )
56
57Brackets denote an optional tuple; they are equivalent to parentheses
58and a leading '?'.  For example, this:
59
60  example: ( literal (? rev:number ) ( data:string ... ) )
61
62can be written more compactly like this:
63
64  example: ( literal [ rev:number ] ( data:string ... ) )
65
66For extensibility, implementations must treat a list as matching a
67prototype's tuple even if the list contains extra elements.  The extra
68elements must be ignored.
69
70In some cases, a prototype may need to match two different kinds of
71data items.  This case will be written using "|" to separate the
72alternatives; for example:
73
74  example: ( first-kind rev:number )
75         | second-kind
76
77The "command response" prototype is used in several contexts of this
78specification to indicate the success or failure of an operation.  It
79is defined as follows:
80
81  command-response: ( success params:list )
82                  | ( failure ( err:error ... ) )
83  error: ( apr-err:number message:string file:string line:number )
84
85The interpretation of parameters in a successful command response is
86context-dependent.
87
88URLs and repository paths are represented as strings.  They should be in
89canonical form when sent over the protocol.  However, as a matter of input
90validation, an implementation should always canonicalize received paths if it
91needs them in canonicalized form.
92
932. Connection establishment and protocol setup
94----------------------------------------------
95
96By default, the client connects to the server on port 3690.
97
98Upon receiving a connection, the server sends a greeting, using a
99command response whose parameters match the prototype:
100
101  greeting: ( minver:number maxver:number mechs:list ( cap:word ... ) )
102
103minver and maxver give the minimum and maximum Subversion protocol
104versions supported by the server.  mechs is present for historical
105reasons, and is ignored by the client.  The cap values give a list of
106server capabilities (see section 2.1).
107
108If the client does not support a protocol version within the specified
109range, it closes the connection.  Otherwise, the client responds to
110the greeting with an item matching the prototype:
111
112  response: ( version:number ( cap:word ... ) url:string
113              ? ra-client:string ( ? client:string ) )
114
115version gives the protocol version selected by the client.  The cap
116values give a list of client capabilities (see section 2.1).  url
117gives the URL the client is accessing.  ra-client is a string
118identifying the RA implementation, e.g. "SVN/1.6.0" or "SVNKit 1.1.4".
119client is the string returned by svn_ra_callbacks2_t.get_client_string;
120that callback may not be implemented, so this is optional.
121
122Upon receiving the client's response to the greeting, the server sends
123an authentication request, which is a command response whose arguments
124match the prototype:
125
126  auth-request: ( ( mech:word ... ) realm:string )
127
128The mech values give a list of SASL mechanisms supported by the
129server.  The realm string is similar to an HTTP authentication realm
130as defined in [RFC 2617]; it allows the server to indicate which of
131several protection spaces the server wishes to authenticate in.  If
132the mechanism list is empty, then no authentication is required and no
133further action takes place as part of the authentication challenge;
134otherwise, the client responds with a tuple matching the prototype:
135
136  auth-response: ( mech:word [ token:string ] )
137
138mech specifies the SASL mechanism and token, if present, gives the
139"initial response" of the authentication exchange.  The client may
140specify an empty mechanism to decline authentication; otherwise, upon
141receiving the client's auth-response, the server sends a series of
142challenges, each a tuple matching the prototype:
143
144  challenge: ( step ( token:string ) )
145           | ( failure ( message:string ) )
146           | ( success [ token:string ] )
147
148If the first word of the challenge is "step", then the token is
149interpreted by the authentication mechanism, and the response token
150transmitted to the server as a string.  The server then proceeds with
151another challenge.  If the client wishes to abort the authentication
152exchange, it may do so by closing the connection.
153
154If the first word of the challenge is "success", the authentication is
155successful.  If a token is provided, it should be interpreted by the
156authentication mechanism, but there is no response.
157
158If the first word of the challenge is "failure", the authentication
159exchange is unsuccessful.  The client may then give up, or make
160another auth-response and restart the authentication process.
161
162RFC 2222 requires that a protocol profile define a service name for
163the sake of the GSSAPI mechanism.  The service name for this protocol
164is "svn".
165
166After a successful authentication exchange, the server sends a command
167response whose parameters match the prototype:
168
169  repos-info: ( uuid:string repos-url:string ( cap:word ... ) )
170
171uuid gives the universal unique identifier of the repository,
172repos-url gives the URL of the repository's root directory, and the
173cap values list the repository capabilities (that is, capabilities
174that require both server and repository support before the server can
175claim them as capabilities, e.g., SVN_RA_SVN_CAP_MERGEINFO).
176
177The client can now begin sending commands from the main command set.
178
1792.1 Capabilities
180
181The following capabilities are currently defined (S indicates a server
182capability and C indicates a client capability):
183
184[CS] edit-pipeline     Every released version of Subversion since 1.0
185                       announces the edit-pipeline capability; starting
186                       in Subversion 1.5, both client and server
187                       *require* the other side to announce edit-pipeline.
188[CS] svndiff1          If both the client and server support svndiff version
189                       1, this will be used as the on-the-wire format for 
190                       svndiff instead of svndiff version 0.
191[CS] absent-entries    If the remote end announces support for this capability,
192                       it will accept the absent-dir and absent-file editor
193                       commands.
194[S]  commit-revprops   If the server presents this capability, it supports the 
195                       rev-props parameter of the commit command.
196                       See section 3.1.1.
197[S]  mergeinfo         If the server presents this capability, it supports the 
198                       get-mergeinfo command.  See section 3.1.1.
199[S]  depth             If the server presents this capability, it understands
200                       requested operational depth (see section 3.1.1) and
201                       per-path ambient depth (see section 3.1.3).
202[S]  atomic-revprops   If the server presents this capability, it
203                       supports the change-rev-prop2 command.
204                       See section 3.1.1.
205[S]  inherited-props   If the server presents this capability, it supports the
206                       retrieval of inherited properties via the get-dir and
207                       get-file commands and also supports the get-iprops
208                       command (see section 3.1.1).
209
2103. Commands
211-----------
212
213Commands match the prototypes:
214
215  command: ( command-name:word params:list )
216
217The interpretation of command parameters is different from command to
218command.
219
220Initially, the client initiates commands from the main command set,
221and the server responds.  Some commands in the main command set can
222temporarily change the set of commands which may be issued, or change
223the flow of control so that the server issues commands and the client
224responds.
225
226Here are some miscellaneous prototypes used by the command sets:
227
228  proplist:  ( ( name:string value:string ) ... )
229  iproplist: ( ( name:string proplist ) ... )
230  propdelta: ( ( name:string [ value:string ] ) ... )
231  node-kind: none|file|dir|unknown
232  bool:      true|false
233  lockdesc:  ( path:string token:string owner:string [ comment:string ]
234               created:string [ expires:string ] )
235
2363.1. Command Sets
237
238There are three command sets: the main command set, the editor command
239set, and the report command set.  Initially, the protocol begins in
240the main command set with the client sending commands; some commands
241can change the command set and possibly the direction of control.
242
2433.1.1. Main Command Set
244
245The main command set corresponds to the svn_ra interfaces.  After each
246main command is issued by the client, the server sends an auth-request
247as described in section 2.  (If no new authentication is required, the
248auth-request contains an empty mechanism list, and the server proceeds
249immediately to sending the command response.)  Some commands include a
250second place for auth-request point as noted below.
251
252  reparent
253    params:   ( url:string )
254    response: ( )
255
256  get-latest-rev
257    params:   ( )
258    response: ( rev:number )
259
260  get-dated-rev
261    params:   ( date:string )
262    response: ( rev:number )
263
264  change-rev-prop
265    params:   ( rev:number name:string ? value:string )
266    response: ( )
267    If value is not specified, the rev-prop is removed.
268    (Originally the value was required; for minimum impact, it was
269     changed to be optional without creating an optional tuple for
270     that one parameter as we normally do.)
271
272  change-rev-prop2
273    params:   ( rev:number name:string [ value:string ]
274                ( dont-care:bool ? previous-value:string ) )
275    response: ( )
276    If value is not specified, the rev-prop is removed.  If dont-care is false,
277    then the rev-prop is changed only if it is currently set as previous-value
278    indicates.  (If dont-care is false and previous-value is unspecified, then
279    the revision property must be previously unset.)  If dont-care is true,
280    then previous-value must not be specified.
281
282  rev-proplist
283    params:   ( rev:number )
284    response: ( props:proplist )
285
286  rev-prop
287    params:   ( rev:number name:string )
288    response: ( [ value:string ] )
289
290  commit
291    params:   ( logmsg:string ? ( ( lock-path:string lock-token:string ) ... )
292                keep-locks:bool ? rev-props:proplist )
293    response: ( )
294    Upon receiving response, client switches to editor command set.
295    Upon successful completion of edit, server sends auth-request.
296    After auth exchange completes, server sends commit-info.
297    If rev-props is present, logmsg is ignored.  Only the svn:log entry in
298    rev-props (if any) will be used.
299    commit-info: ( new-rev:number date:string author:string
300                   ? ( post-commit-err:string ) )
301    NOTE: when revving this, make 'logmsg' optional, or delete that parameter
302          and have the log message specified in 'rev-props'.
303
304  get-file
305    params:   ( path:string [ rev:number ] want-props:bool want-contents:bool
306                ? want-iprops:bool )
307    response: ( [ checksum:string ] rev:number props:proplist
308                [ inherited-props:iproplist ] )
309    If want-contents is specified, then after sending response, server
310     sends file contents as a series of strings, terminated by the empty
311     string, followed by a second empty command response to indicate
312     whether an error occurred during the sending of the file.
313    NOTE: the standard client doesn't send want-iprops as true, it uses
314     get-iprops, but does send want-iprops as false to workaround a server
315     bug in 1.8.0-1.8.8.
316
317  get-dir
318    params:   ( path:string [ rev:number ] want-props:bool want-contents:bool
319                ? ( field:dirent-field ... ) ? want-iprops:bool )
320    response: ( rev:number props:proplist ( entry:dirent ... )
321                [ inherited-props:iproplist ] )]
322    dirent:   ( name:string kind:node-kind size:number has-props:bool
323                created-rev:number [ created-date:string ]
324                [ last-author:string ] )
325    dirent-field: kind | size | has-props | created-rev | time | last-author
326                  | word
327    NOTE: the standard client doesn't send want-iprops as true, it uses
328     get-iprops, but does send want-iprops as false to workaround a server
329     bug in 1.8.0-1.8.8.
330
331  check-path
332    params:   ( path:string [ rev:number ] )
333    response: ( kind:node-kind )
334    If path is non-existent, 'svn_node_none' kind is returned.
335
336  stat
337    params:   ( path:string [ rev:number ] )
338    response: ( ? entry:dirent )
339    dirent:   ( name:string kind:node-kind size:number has-props:bool
340                created-rev:number [ created-date:string ]
341                [ last-author:string ] )
342    New in svn 1.2.  If path is non-existent, an empty response is returned.
343
344  get-mergeinfo
345    params:   ( ( path:string ... ) [ rev:number ] inherit:word 
346                descendants:bool)
347    response: ( ( ( path:string merge-info:string ) ... ) )
348    New in svn 1.5.  If no paths are specified, an empty response is
349    returned.  If rev is not specified, the youngest revision is used.
350
351  update
352    params:   ( [ rev:number ] target:string recurse:bool
353                ? depth:word send_copyfrom_args:bool ? ignore_ancestry:bool )
354    Client switches to report command set.
355    Upon finish-report, server sends auth-request.
356    After auth exchange completes, server switches to editor command set.
357    After edit completes, server sends response.
358    response: ( )
359
360  switch
361    params:   ( [ rev:number ] target:string recurse:bool url:string
362                ? depth:word ? send_copyfrom_args:bool ignore_ancestry:bool )
363    Client switches to report command set.
364    Upon finish-report, server sends auth-request.
365    After auth exchange completes, server switches to editor command set.
366    After edit completes, server sends response.
367    response: ( )
368
369  status
370    params:   ( target:string recurse:bool ? [ rev:number ] ? depth:word )
371    Client switches to report command set.
372    Upon finish-report, server sends auth-request.
373    After auth exchange completes, server switches to editor command set.
374    After edit completes, server sends response.
375    response: ( )
376
377  diff
378    params:   ( [ rev:number ] target:string recurse:bool ignore-ancestry:bool
379                url:string ? text-deltas:bool ? depth:word )
380    Client switches to report command set.
381    Upon finish-report, server sends auth-request.
382    After auth exchange completes, server switches to editor command set.
383    After edit completes, server sends response.
384    response: ( )
385
386  log
387    params:   ( ( target-path:string ... ) [ start-rev:number ]
388                [ end-rev:number ] changed-paths:bool strict-node:bool
389                ? limit:number
390                ? include-merged-revisions:bool
391                all-revprops | revprops ( revprop:string ... ) )
392    Before sending response, server sends log entries, ending with "done".
393    If a client does not want to specify a limit, it should send 0 as the
394    limit parameter.  rev-props excludes author, date, and log; they are
395    sent separately for backwards-compatibility.
396    log-entry: ( ( change:changed-path-entry ... ) rev:number
397                 [ author:string ] [ date:string ] [ message:string ]
398                 ? has-children:bool invalid-revnum:bool
399                 revprop-count:number rev-props:proplist
400                 ? subtractive-merge:bool )
401             | done
402    changed-path-entry: ( path:string A|D|R|M
403                          ? ( ? copy-path:string copy-rev:number )
404                          ? ( ? node-kind:string ? text-mods:bool prop-mods:bool ) )
405    response: ( )
406
407  get-locations
408    params:   ( path:string peg-rev:number ( rev:number ... ) )
409    Before sending response, server sends location entries, ending with "done".
410    location-entry: ( rev:number abs-path:number ) | done
411    response: ( )
412
413  get-location-segments
414    params:   ( path:string [ start-rev:number ] [ end-rev:number ] )
415    Before sending response, server sends location entries, ending with "done".
416    location-entry: ( range-start:number range-end:number [ abs-path:string ] ) | done
417    response: ( )
418
419  get-file-revs
420    params:   ( path:string [ start-rev:number ] [ end-rev:number ]
421                ? include-merged-revisions:bool )
422    Before sending response, server sends file-rev entries, ending with "done".
423    file-rev: ( path:string rev:number rev-props:proplist
424                file-props:propdelta ? merged-revision:bool )
425              | done
426    After each file-rev, the file delta is sent as one or more strings,
427    terminated by the empty string.  If there is no delta, server just sends
428    the terminator.
429    response: ( )
430
431  lock
432    params:    ( path:string [ comment:string ] steal-lock:bool
433                 [ current-rev:number ] )
434    response:  ( lock:lockdesc )
435
436  lock-many
437    params:    ( [ comment:string ] steal-lock:bool ( ( path:string
438                 [ current-rev:number ] ) ... ) )
439    Before sending response, server sends lock cmd status and descriptions,
440    ending with "done".
441    lock-info: ( success ( lock:lockdesc ) ) | ( failure ( err:error ) )
442                | done
443    response: ( )
444
445  unlock
446    params:    ( path:string [ token:string ] break-lock:bool )
447    response:  ( )
448
449  unlock-many
450    params:    ( break-lock:bool ( ( path:string [ token:string ] ) ... ) )
451    Before sending response, server sends unlocked paths, ending with "done".
452    pre-response: ( success ( path:string ) ) | ( failure ( err:error ) )
453                  | done
454    response:  ( )
455
456  get-lock
457    params:    ( path:string )
458    response:  ( [ lock:lockdesc ] )
459
460  get-locks
461    params:    ( path:string ? [ depth:word ] )
462    response   ( ( lock:lockdesc ... ) )
463
464  replay
465    params:    ( revision:number low-water-mark:number send-deltas:bool )
466    After auth exchange completes, server switches to editor command set.
467    After edit completes, server sends response.
468    response   ( )
469
470  replay-range
471    params:    ( start-rev:number end-rev:number low-water-mark:number 
472                 send-deltas:bool )
473    After auth exchange completes, server sends each revision
474    from start-rev to end-rev, alternating between sending 'revprops' 
475    entries and sending the revision in the editor command set.
476    After all revisions are complete, server sends response.
477    revprops:  ( revprops:word props:proplist )
478      (revprops here is the literal word "revprops".)
479    response   ( )
480
481  get-deleted-rev
482    params:   ( path:string peg-rev:number end-rev:number )
483    response: ( deleted-rev:number )
484
485  get-iprops
486    params:   ( path:string [ rev:number ] )
487    response: ( inherited-props:iproplist )
488    New in svn 1.8.  If rev is not specified, the youngest revision is used.
489
4903.1.2. Editor Command Set
491
492An edit operation produces only one response, at close-edit or
493abort-edit time.  However, the consumer may write an error response at
494any time during the edit in order to terminate the edit operation
495early; the driver must notice that input is waiting on the connection,
496read the error, and send an abort-edit operation.  After an error is
497returned, the consumer must read and discard editing operations until
498the abort-edit.  In order to prevent TCP deadlock, the consumer must
499use non-blocking I/O to send an early error response; if writing
500blocks, the consumer must read and discard edit operations until
501writing unblocks or it reads an abort-edit.
502
503  target-rev
504    params:   ( rev:number )
505
506  open-root
507    params:   ( [ rev:number ] root-token:string )
508
509  delete-entry
510    params:   ( path:string rev:number dir-token:string )
511
512  add-dir
513    params:   ( path:string parent-token:string child-token:string
514                [ copy-path:string copy-rev:number ] )
515
516  open-dir
517    params:   ( path:string parent-token:string child-token:string rev:number )
518
519  change-dir-prop
520    params:   ( dir-token:string name:string [ value:string ] )
521
522  close-dir
523    params:   ( dir-token:string )
524
525  absent-dir
526    params:   ( path:string parent-token:string )
527
528  add-file
529    params:   ( path:string dir-token:string file-token:string
530                [ copy-path:string copy-rev:number ] )
531
532  open-file
533    params:   ( path:string dir-token:string file-token:string rev:number )
534
535  apply-textdelta
536    params:   ( file-token:string [ base-checksum:string ] )
537
538  textdelta-chunk
539    params: ( file-token:string chunk:string )
540
541  textdelta-end
542    params: ( file-token:string )
543
544  change-file-prop
545    params:   ( file-token:string name:string [ value:string ] )
546
547  close-file
548    params:   ( file-token:string [ text-checksum:string ] )
549
550  absent-file
551    params:   ( path:string parent-token:string )
552
553  close-edit
554    params:   ( )
555    response: ( )
556
557  abort-edit
558    params:   ( )
559    response: ( )
560
561  finish-replay
562    params:   ( )
563    Only delivered from server to client, at the end of a replay.
564
5653.1.3. Report Command Set
566
567To reduce round-trip delays, report commands do not return responses.
568Any errors resulting from a report call will be returned to the client
569by the command which invoked the report (following an abort-edit
570call).  Errors resulting from an abort-report call are ignored.
571
572  set-path:
573    params: ( path:string rev:number start-empty:bool
574              ? [ lock-token:string ] ? depth:word )
575
576  delete-path:
577    params: ( path:string )
578
579  link-path:
580    params: ( path:string url:string rev:number start-empty:bool 
581              ? [ lock-token:string ] ? depth:word )
582
583  finish-report:
584    params: ( )
585
586  abort-report
587    params: ( )
588
5894. Extensibility
590----------------
591
592This protocol may be extended in three ways, in decreasing order of
593desirability:
594
595  * Items may be added to any tuple.  An old implementation will
596    ignore the extra items.
597
598  * Named extensions may be expressed at connection initiation time
599    by the client or server.
600
601  * The protocol version may be bumped.  Clients and servers can then
602    choose to any range of protocol versions.
603
6044.1. Limitations
605
606The current implementation limits the length of a word to 31 characters.
607Longer words, such as capability names, will be cause an error on the
608receiver side.
609
6104.2. Extending existing commands
611
612Extending an existing command is normally done by indicating that its
613tuple is allowed to end where it currently ends, for backwards
614compatibility, and then tacking on a new, possibly optional, item.
615
616For example, diff was extended to include a new mandatory text-deltas
617parameter like this:
618
619  /* OLD */ diff:
620    params:   ( [ rev:number ] target:string recurse:bool ignore-ancestry:bool
621                url:string )
622  /* NEW */ diff:
623    params:   ( [ rev:number ] target:string recurse:bool ignore-ancestry:bool
624                url:string ? text-deltas:bool )
625
626The "?" says that the tuple is allowed to end here, because an old
627client or server wouldn't know to send the new item.
628
629For optional parameters, a slightly different approach must be used.
630set-path was extended to include lock-tokens like this:
631
632  /* OLD */ set-path:
633    params: ( path:string rev:number start-empty:bool )
634
635  /* NEW */ set-path:
636    params: ( path:string rev:number start-empty:bool ? [ lock-token:string ] )
637
638The new item appears in brackets because, even in the new protocol,
639the lock-token is still optional.  However, if there's no lock-token
640to send, an empty tuple must still be transmitted so that future
641extensions to this command remain possible.
642