Syntactic structure
-------------------

The Subversion protocol is specified in terms of the following
syntactic elements, specified using ABNF [RFC 2234]:

  item   = word / number / string / list
  word   = ALPHA *(ALPHA / DIGIT / "-") space
  number = 1*DIGIT space
  string = number ":" *OCTET space
         ; number gives the byte count of the *OCTET portion
  list   = "(" space *item ")" space
  space  = 1*(SP / LF)

Here is an example item showing each of the syntactic elements:

  ( word 22 6:string ( sublist ) )

All items end with mandatory whitespace.  (In the above example, a
newline provides the terminating whitespace for the outer list.)  It
is possible to parse an item without knowing its type in advance.

Lists are not constrained to contain items of the same type.  Lists
can be used for tuples, optional tuples, or arrays.  A tuple is a list
expected containing a fixed number of items, generally of differing
types.  An optional value is a list containing either zero or a fixed
number of items.  An array is a list containing zero or more items of
the same type.

Words are used for enumerated protocol values, while strings are used
for text or binary data of interest to the Subversion client or
server.  Words are case-sensitive.

For convenience, this specification will define prototypes for data
items using a syntax like:

  example: ( literal [ rev:number ] ( data:string ... ) )

A simple word such as "literal", with no colon, denotes a literal
word.  A choice of words may be given in braces with "|" separating
the choices.  "name:type" specifies a parameter with the given type.
A type is "word", "number", "string", "list", or the name of another
prototype.  Brackets denote an optional tuple.  Parentheses denote a
tuple, unless the parentheses contain ellipses, in which case the
parentheses denote an array containing zero or more elements matching
the prototype preceding the ellipses.

For extensibility, implementations must treat a list as matching a
prototype's tuple even if the list contains extra elements.  The extra
elements must be ignored.

In some cases, a prototype may need to match two different kinds of
data items.  This case will be written using "|" to separate the
alternatives; for example:

  example: ( first-kind rev:number )
         | second-kind

Connection establishment and protocol setup
-------------------------------------------

By default, the client connects to the server on port XXX.

Upon receiving a connection, the server sends a greeting, using an
item matching the prototype:

  greeting: ( minver:number maxver:number
              ( mech:word ... ) ( cap:word ... ) )

minver and maxver give the minimum and maximum Subversion protocol
versions supported by the server.  The mech values give a list of SASL
[RFC 2222] mechanisms supported by the server.  The cap values give a
list of server capabilities; no capabilities are currently defined.

If the client does not support a protocol version within the specified
range, or does not support any of the specified SASL mechanisms, it
closes the connection.  Otherwise, the client responds to the greeting
with an item matching the prototype:

  response: ( version:number mech:word [ mecharg:string ] ( cap:word ... ) )

version gives the protocol version selected by the client, mech gives
the SASL authentication mechanism, and mecharg gives the initial
response for the authentication exchange.  mecharg must be omitted if
the selected mechanism does not begin with an initial client response.
(Calling this an "initial response" is confusing, but technically
correct; SASL talks in terms of server challenges and client
responses, even when the mechanism begins with information from the
client or ends with information from the server.)  The cap values give
a list of client capabilities; no capabilities are currently defined.

Upon receiving the client's response to the greeting, the server sends
a series of challenges.  Each challenge is a tuple matching the
prototype:

  challenge: ( step ( token:string ) )
           | ( failure ( message:string ) )
           | ( success [ token:string ] )

If the first word of the challenge is "step", then the token is
interpreted by the authentication mechanism, and the response token
transmitted to the server as a string.  The server then proceeds with
another challenge.  If the client wishes to abort the authentication
exchange, it may do so by closing the connection.

If the first word of the challenge is "success", the authentication is
successful.  If a token is provided, it should be interpreted by the
authentication mechanism, but there is no response.

If the first word of the challenge is "failure", the authentication
exchange is unsuccessful.  After sending a failure notification, the
server must close the connection, as no further action is possible.

RFC 2222 requires that a protocol profile define a service name for
the sake of the GSSAPI mechanism.  The service name for this protocol
is "svn".

Upon receiving a success notification from the server, the security
layer (if any) goes into effect, starting with the next message from
the client.  The client passes its URL to the server in a tuple
matching the prototype:

  url: ( client-url:string )

The server decomposes the client url into repository path and root fs
path, and sends back either a successful command response with no
parameters or an error response as appropriate.  (See section 3.)  The
client may now begin sending commands from the main command set.

3. Commands

Commands and command responses match the prototypes:

  command: ( command-name:word params:list )
  command-response: ( success params:list )
                  | ( failure ( err:error ... ) )
  error: ( apr-err:number message:string file:string line:number )

The interpretation of parameters in a command and its response depend
on the command.

Initially, the client initiates commands from the main command set,
and the server responds.  Some commands in the main command set can
temporarily change the set of commands which may be issued, or change
the flow of control so that the server issues commands and the client
responds.

Here are some miscellaneous prototypes used by the command sets:

  proplist:  ( ( name:string value:string ) ... )
  node-kind: none|file|dir|unknown

3.1. Command Sets

There are three command sets: the main command set, the editor command
set, and the report command set.  Initially, the protocol begins in
the main command set with the client sending commands; some commands
can change the command set and possibly the direction of control.

3.1.1. Main Command Set

The main command set corresponds to the svn_ra interfaces.

  get-latest-rev
    params:   ( )
    response: ( rev:number )

  get-dated-rev
    params:   ( date:string )
    response: ( rev:number )

  change-rev-prop
    params:   ( rev:number name:string value:string )
    response: ( )

  rev-proplist
    params:   ( rev:number )
    response: ( props:proplist )

  rev-prop
    params:   ( rev:number name:string )
    response: ( [ value:string ] )

  commit
    params:   ( logmsg:string )
    response: ( )
    Upon receiving response, client switches to editor command set.
    Upon completion of edit, server sends commit-info.
    commit-info: ( new-rev:number date:string author:string )

  get-file
    params:   ( path:string [ rev:number ] )
    response: ( rev:number props:proplist )
    After sending response, server sends file contents as a series of
     strings, terminated by the empty string.

  get-dir
    params:   ( path:string [ rev:number ] )
    response: ( rev:number props:proplist ( entry:dirent ... ) )]
    dirent:   ( name:string kind:node-kind size:number [ has-props ]
                created-rev:number [ created-date:string ]
                [ last-author:string ] )

  checkout
    params:   ( [ rev:number ] [ recurse ] )
    response: ( )
    After sending response, server switches to editor command set.

  update
    params:   ( [ rev:number ] target:string [ recurse ] )
    response: ( )
    Upon receiving response, client switches to report command set.
    Upon completion of report, server switches to editor command set.

  switch
    params:   ( [ rev:number ] target:string [ recurse ] url:string )
    response: ( )
    Upon receiving response, client switches to report command set.
    Upon completion of report, server switches to editor command set.

  status
    params:   ( target:string [ recurse ] )
    response: ( )
    Upon receiving response, client switches to report command set.
    Upon completion of report, server switches to editor command set.

  diff
    params:   ( [ rev:number ] target:string [ recurse ] url:string )
    response: ( )
    Upon receiving response, client switches to report command set.
    Upon completion of report, server switches to editor command set.

  log
    params:   ( ( target-path:string ... ) [ start-rev:number ]
                [ end-rev:number ] [ changed-paths ] [ strict-node ] )
    response: ( )
    After sending response, server sends log entries
    log-entry: ( ( change:changed-path-entry ... ) rev:number
                 [ author:string ] [ date:string ] [ message:string ] )
    changed-path-entry: ( path:string A|D|R|M [ copy-path:string ]
                          [ copy-rev:number ] )

3.1.2. Editor Command Set

  target-rev
    params:   ( rev:number )
    response: ( )

  open-root
    params:   ( [ rev:number ] )
    response: ( dir-token: string )

  delete-entry
    params:   ( path:string rev:number dir-token:string )
    response: ( )

  add-dir
    params:   ( path:string dir-token:string
                [ copy-path:string copy-rev:number ] )
    response: ( dir-token: string )

  open-dir
    params:   ( path:string dir-token:string rev:number )
    response: ( dir-token: string )

  change-dir-prop
    params:   ( dir-token:string name:string value:string )
    response: ( )

  close-dir
    params:   ( dir-token:string )
    response: ( )

  add-file
    params:   ( path:string dir-token:string
                [ copy-path:string copy-rev:number ] )
    response: ( file-token:string )

  open-file
    params:   ( path:string dir-token:string rev:number )
    response: ( file-token:string )

  apply-textdelta:
    params:   ( file-token:string )
    response: ( )
    Upon receiving response, client sends svndiff data as strings,
     terminated by an empty string.

  change-file-prop:
    params:   ( file-token:string name:string value:string )
    response: ( )

  close-file:
    params:   ( file-token:string )
    response: ( )

  close-edit:
    params:   ( )
    response: ( )

  abort-edit:
    params:   ( )
    response: ( )

3.1.3. Report Command Set

  set-path:
    params: ( path:string rev:number )
    response: ( )

  delete-path:
    params: ( path:string )
    response: ( )

  link-path:
    params: ( path:string url:string rev:number )
    response: ( )

  finish-report:
    params: ( )
    response: ( )

  abort-report
    params: ( )
    response: ( )

4. Extensibility

This protocol may be extended in three ways, in decreasing order of
desirability:

  * Items may be added to any tuple.  An old implementation will
    ignore the extra items.

  * Named extensions may be expressed at connection initiation time
    by the clent or server.

  * The protocol version may be bumped.  Clients and servers can then
    choose to any range of protocol versions.

It is quite possible that the protocol version will never change.