webdav-protocol   [plain text]


This file documents Subversion's use of the WebDAV/DeltaV protocol.


IMPORTANT RFCs and LINKS
========================

  * RFC 2518  (WebDAV)

  * RFC 3253  (DeltaV)

  * Subversion's limited uses of DeltaV, as well as interoperability
    issues, are explained in the "WebDAV" appendix of the free
    Subversion book (at http://svnbook.red-bean.com)




HTTP METHODS USED, indexed by svn commands that access network
==============================================================


Read Commands  :  (OPTIONS, PROPFIND, GET, REPORT)
-------------

  Most commands have to resolve peg-revisions before starting:

  * -r X foo@Y      REPORT                        ('get-locations')

       ...if an old server doesn't support 'get-locations' report, the
       client traces history using the 'log-report' instead.

  And any command which has to convert a date to a revision:

  * -r {DATE}       REPORT                        ('dated-rev-report')


  The following group of commands all use the custom 'update-report'
  request, which is just a fancy way of driving svn_repos_dir_delta():

  * svn checkout / svn export / svn update:
   (do_update RA interface)

     ra_neon:       PROPFIND, REPORT              ('update-report' w/send-all)

     ra_serf:       PROPFIND, REPORT              ('update-report')
                    ... then many PROPFIND/GETs on many parallel connections

    svn update only                               ('merge-info-report')

  * svn switch:     OPTIONS, PROPFIND, REPORT     ('update-report',
                                                   'merge-info-report')

  * svn diff:       OPTIONS, PROPFIND, REPORT     ('update-report')
                    ... then many GETs

  * svn merge:      OPTIONS, PROPFIND, REPORT     ('update-report',
                                                   'merge-info-report')
                    ... then many GETs

  * svn status -u:  OPTIONS, PROPFIND, REPORT     ('update-report' and
                                                   'get-locks-report')

  * svn cp URL wc:  OPTIONS, PROPFIND, REPORT     ('update-report')
                    (this is just like checkout)


  And these guys are left over:

  * svn log:        OPTIONS, PROPFIND, REPORT     ('log-report')

  * svn blame:      OPTIONS, PROPFIND, REPORT     ('file-revs-report')
                    [older clients use GET
                     and different REPORT]        ('log-report')

  * svn ls:         PROPFIND

  * svn ls -v:      PROPFIND, REPORT              ('get-locks-report')

  * svn cat:        PROPFIND, GET

  * svn info URL:   PROPFIND

  * svn plist URL:  PROPFIND

  * svn pget URL:   PROPFIND
 



Write Commands  :  (MKACTIVITY, PROPPATCH, PUT, CHECKOUT, MKCOL, MOVE,
--------------      COPY, DELETE, LOCK, UNLOCK, MERGE)

  With the exception of LOCK/UNLOCK, every write command performs some
  sort of DeltaV commit operation.  In DeltaV, a commit always starts
  by creating a transaction (MKACTIVITY), applies a log message
  (PROPPATCH), does some other write methods, and then ends by
  committing the transaction (MERGE).  If the MERGE fails, the client
  may try to remove the transaction with a DELETE.

  * svn commit:
     ra_neon:       OPTIONS, PROPFIND, MKACTIVITY, 
                    {CHECKOUT, COPY, MOVE, DELETE, PROPPATCH, PUT, MKCOL},
                    MERGE (DELETE)

     ra_serf:       OPTIONS to acquire activity collection set
     (no major      MKACTIVITY to a unique UUID relative to activity set
      differences)  PROPFIND to get what we think our baseline is
                    CHECKOUT of baseline revision into activity
                    Setting log: PROPPATCH on root directory
                    Delete a file: CHECKOUT file / DELETE
                    Add a dir:  MKCOL
                    Add a file: CHECKOUT parent dirs / PUT raw-file
                    Edit a file: CHECKOUT file / PUT svndiff stream
                    End commit: MERGE activity, DELETE activity

  * svn import:     OPTIONS, PROPFIND, MKACTIVITY,
                    {PROPPATCH, PUT, MKCOL},
                    MERGE (DELETE)

  * svn lock:       PROPFIND, LOCK
  
  * svn unlock:     PROPFIND, UNLOCK

  * svn cp URL URL: OPTIONS, PROPFIND, MKACTIVITY, PROPPATCH,
                    COPY, MERGE.  (DELETE)

  * svn mv URL URL: OPTIONS, PROPFIND, MKACTIVITY, PROPPATCH,
                    COPY, DELETE, MERGE.  (DELETE)

  * svn rm URL:     OPTIONS, PROPFIND, MKACTIVITY, PROPPATCH, DELETE, MERGE.

  * svn mkdir URL:  OPTIONS, PROPFIND, MKACTIVITY, PROPPATCH, MKCOL, MERGE.

  * svn pset --revprop:  PROPPATCH

Remembering Our Location
========================

For a file in our WC, both ra_serf and ra_neon will store the checked-in href
(where the original text-base and properties can be found) in the
svn:wc:ra_dav:version-url wcprop.

Example property:
  svn:wc:ra_dav:version-url -> /repos/test/!svn/ver/2/httpd/configure

GET
===

ra_serf
-------

For a file that a WC already has when it wants to do an update, ra_serf will
send two extra headers:

  X-SVN-VR-Base: <checked-in href of locally-present file>
  Accept-Encoding: svndiff1;q=0.9,svndiff;q=0.8

The server may choose not to return svndiff content but return full-text.

(ra_neon has this same functionality, but is largely just dead code.)

Example
-------

Request:

  GET /repos/test/!svn/ver/3/httpd/configure HTTP/1.1
  X-SVN-VR-Base: /repos/test/!svn/ver/2/httpd/configure
  Accept-Encoding: svndiff1;q=0.9,svndiff;q=0.8

Response:

  HTTP/1.1 200 OK
  ETag: "3//httpd/configure"
  Vary: Accept-Encoding
  Content-Type: application/vnd.svn-svndiff
  
  ...svn-svndiff stream that can be passed to svn_txdelta_parse_svndiff...

Custom REPORTs
==============

We use a bunch of custom reports, here's a little info on what they look like.

update-report
-------------

Purpose: Present what we have in our WC to the server and let it tell us what
         has changed.  Has an optional 'send-all' attribute that will include
         the text-deltas in base64-encoding inline to the XML REPORT response.

Target URL: Base VCC URL
            Example: REPORT /repos/test/!svn/vcc/default

Note: ra_serf will not set the send-all attribute to the update-report.  It
      will instead take the returned D:checked-in href and do a pipelined
      PROPFIND / GET on that resource.

Note: If a client had a previous revision, it would not send the 'start-empty'
      attribute to entry.

Request:

  <S:update-report send-all="true" xmlns:S="svn:">
    <S:src-path>http://localhost:8080/repos/test/httpd/support</S:src-path>
    <S:target-revision>2</S:target-revision>
    <S:entry rev="2"  start-empty="true"></S:entry>
  </S:update-report>

Response:

<S:update-report xmlns:S="svn:" xmlns:V="..." xmlns:D="DAV:" send-all="true">
  <S:target-revision rev="2"/>
  <S:open-directory rev="2">
    <D:checked-in>
      <D:href>/repos/test/!svn/ver/2/httpd/support</D:href>
    </D:checked-in>
    <S:set-prop name="svn:entry:committed-rev">2</S:set-prop>
    ... more set props ...
    <S:add-file name="ab.c">
      <D:checked-in>
        <D:href>/repos/test/!svn/ver/2/httpd/support/ab.c</D:href>
      </D:checked-in>
      <S:set-prop name="svn:entry:committed-rev">2</S:set-prop>
      ... more set props for the file ...
      <S:txdelta>...base64-encoded file content...</S:txdelta>
    </S:add-file>
    <S:add-directory name="os" bc-url="/repos/test/!svn/bc/2/httpd/os">
      <D:checked-in>
        <D:href>/repos/test/!svn/ver/2/httpd/os</D:href>
      </D:checked-in>
      ...directory contents...
    </S:add-directory>
  </S:open-directory>
</S:update-report>

dated-rev-report
----------------

Purpose: Get the revision associated with a particular date.

Target URL: VCC URL for repos.

Request:

  <S:dated-rev-report xmlns:S="svn:" xmlns:D="DAV:">
    <D:creationdate>2005-12-07T13:06:26.034802Z</D:creationdate>
  </S:dated-rev-report>

Response:

  <S:dated-rev-report xmlns:S="svn:" xmlns:D="DAV:">
    <D:version-name>4747</D:version-name>
  </S:dated-rev-report>

get-locks-report
----------------

Purpose: Get the locks associated with a particular resource.

Target URL: URL of item we're getting the locks for

Request:

  <S:get-locks-report xmlns:S="svn">
  </S:get-locks-report>

Response:

  <S:get-locks-report xmlns:S="svn">
    <S:lock>
      <S:path>/foo/bar/baz</S:path>
      <S:token>opaquelocktoken:706689a6-8cef-0310-9809-fb7545cbd44e</S:token>
      <S:owner>fred</S:owner>
      <S:comment encoding="base64">ET39IGCB93LL4M</S:comment>
      <S:creationdate>2005-02-07T14:17:08Z</S:creationdate>
      <S:expirationdate>2005-02-08T14:17:08Z</S:expirationdate>
    </S:lock>
  </S:get-locks-report>

get-locations
-------------

Purpose: Get the location of a path appearing in a particular revision.

Target URL: Current baseline collection for a directory plus relative paths.
            Example: REPORT /repos/test/!svn/bc/5/httpd

Request:
 
  <S:get-locations xmlns:S="svn:">
    <S:path></S:path>
    <S:peg-revision>5</S:peg-revision>
    <S:location-revision>1</S:location-revision>
  </S:get-locations>

Response:

  <?xml version="1.0" encoding="utf-8"?>
  <S:get-locations-report xmlns:S="svn:" xmlns:D="DAV:">
    <S:location rev="1" path="/httpd"/>
  </S:get-locations-report>

log-report
----------

Purpose: Retrieve the log for a portion of the repository.

Target URL: Current baseline collection for a directory plus relative paths.
            Example: REPORT /repos/test/!svn/bc/5/httpd/support

Request:

  <S:log-report xmlns:S="svn:">
    <S:start-revision>2</S:start-revision>
    <S:end-revision>2</S:end-revision>
    <S:limit>1</S:limit> (optional)
    <S:discover-changed-paths/> (optional)
    <S:strict-node-history/> (optional)
    <S:include-merged-revisions/> (optional)
    <S:revprop>REVPROP</S:revprop>... | <S:all-revprops/> | <S:no-revprops/>
      ('revprop', 'all-revprops', and 'no-revprops' are all optional)
    <S:path></S:path>... (optional)
  </S:log-report>

Response:

  <?xml version="1.0" encoding="utf-8"?>
  <S:log-report xmlns:S="svn:" xmlns:D="DAV:">
    <S:log-item>
      <D:version-name>2</D:version-name>
      <S:creator-displayname>bob</S:creator-displayname>
      <S:date>2006-02-27T18:44:26.149336Z</S:date>
      <D:comment>Add doo-hickey</D:comment>
      <S:revprop name="REVPROP">value</S:revprop>... (optional)
      <S:has-children/> (optional)
      <S:added-path( copyfrom-path="PATH" copyfrom-rev="REVNUM">PATH</S:added-path>... (optional)
      <S:replaced-path( copyfrom-path="PATH" copyfrom-rev="REVNUM">PATH</S:replaced-path>... (optional)
      <S:deleted-path>PATH</S:deleted-path>... (optional)
      <S:modified-path>PATH</S:modified-path>... (optional)
    </S:log-item>
    ...multiple log-items for each returned revision...
  </S:log-report>

mergeinfo-report
----------------

Purpose: Retrieve the merge history for a portion of the repository
(e.g. a set of paths) at a particular revision.

Target URL: URL of item we're getting merge info for.

Note: <S:inherit> is a representation of the svn_mergeinfo_inheritance_t
      struct and can have the values 'explicit', 'inherited', or
      'nearest-ancestor'.  The default value is 'explicit' if <S:inherit>
      is not present or has any other value than those three. 

      <S:include-descendants> represents the 'include_descendants'
      boolean argument to svn_ra_get_mergeinfo().  It can be 'yes' or
      'no'; the default value is 'no' (mapping to FALSE).

Request:

  <S:mergeinfo-report xmlns:S="svn:">
    <S:revision>1</S:revision>
    <S:inherit>inherited</S:inherit>
    <S:include-descendants>yes</S:include-descendants>
    <S:path>/A/B/E/alpha</S:path>
  </S:mergeinfo-report>

Response:

  <?xml version="1.0" encoding="utf-8"?>
  <S:mergeinfo-report xmlns:S="svn:" xmlns:D="DAV:">
    <S:mergeinfo-item>
      <S:mergeinfo-path>/A_COPY/B/E</S:mergeinfo-path>
      <S:mergeinfo-info>/A/B/E:1,3-4</S:mergeinfo-info>
    </S:mergeinfo-item>
  </S:mergeinfo-report>