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>