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