|  | 
 | Ben's Quick Summary of WebDAV and DeltaV | 
 | ========================================= | 
 |  | 
 | * WebDAV: RFC 2518.  Extends the standard HTTP methods to make web | 
 |   servers behave as traditional fileservers, complete with a locking | 
 |   model and meta-data properties. | 
 |  | 
 | * DeltaV: RFC 3253.  Adds more HTTP methods to WebDAV, introducing | 
 |   versioning concepts.  Provides a number of flexible versioning | 
 |   models that servers can support, and some backwards-compatibility | 
 |   modes for older WebDAV or HTTP/1.1 clients. | 
 |  | 
 |  | 
 | ---------------------------------------- | 
 |  | 
 | WebDAV | 
 | ====== | 
 |  | 
 | Key concepts introduced:  properties, collections, locking. | 
 |  | 
 | New HTTP client request headers:  {Depth, Destination, If, ...} | 
 | New HTTP server response headers: {DAV, ...} | 
 |  | 
 |  | 
 | * Property:    a meta-data name/value.  every property exists in  | 
 |                some unique "namespace", defined using xml namespaces. | 
 |  | 
 |   - a "live" property is one that is controlled by the server, like a | 
 |     file's content-length, for example, or a file's | 
 |     checked-in/checked-out state.  often the property is read-only; if | 
 |     not, the server enforces the propval's syntax/semantics. | 
 |  | 
 |   - a "dead" property is one that is invented and controlled by a | 
 |     user, just like file contents. | 
 |  | 
 |   - new HTTP methods:  PROPFIND, PROPPATCH to change propval. | 
 |  | 
 |  | 
 | * collection:  a directory.  contains a bunch of URIs and has props. | 
 |  | 
 |   - each child is called a 'member' URI.  each internal member URI | 
 |     must be relative to parent collection. | 
 |                    | 
 |   - collection URIs are supposed to end with trailing slashes. | 
 |     servers should auto-append them if not present. | 
 |  | 
 |   - new HTTP method:  MKCOL to create collection. | 
 |  | 
 |  | 
 | * locking:  a way of serializing access to a resource. | 
 |  | 
 |   - locking is totally optional -- the only 'flexible' part of the | 
 |     WebDAV spec.  a WebDAV server may support locking to any degree: | 
 |     either not at all, or some combination of exclusive or shared | 
 |     locks.  An OPTIONS response can return a header of DAV: 1 or DAV: | 
 |     2.  Level-2 support means locking is available. | 
 |  | 
 |   - new HTTP method: LOCK.  creates a lock and attaches it to the | 
 |     resource.  the server returns a 'lock token' to the client, which | 
 |     is defined to be any universally unique URI.  the 'lock' attached | 
 |     to the resource has these properties: | 
 |  | 
 |       * owner:   some authenticated username | 
 |       * token:   the specific lock identifier | 
 |       * scope:   either "exclusive" or "shared" | 
 |       * type:    "write".  [other types may exist someday] | 
 |       * depth:   for a collection, either 0 or infinity. | 
 |       * timeout: some value in seconds | 
 |        | 
 |        - exclusive locks behave how you think -- only one per resource | 
 |          allowed.  shared locks, on the other hand, are just for | 
 |          communication -- any number of them can be attached. | 
 |  | 
 |        - lock tokens are *not* secret: anyone can query the | 
 |          "DAV:lockdiscovery" property to see all the locks attached to | 
 |          a resource, which includes detailed descriptions of every | 
 |          field above. | 
 |  | 
 |        - to remove a lock with UNLOCK, or to modify something with an | 
 |          exclusive lock, the client must provide *two* things: | 
 |  | 
 |             1. authentication/authorization.  prove you own and/or are | 
 |                allowed to mess with the lock.  this happens via | 
 |                existing HTTP methods. | 
 |  | 
 |             2. the lock token, i.e. the "name" of the lock.  (this | 
 |                requirement also prevents some non-DAV aware program | 
 |                from using your auth credentials and accidentally doing | 
 |                an ignorant PUT.  think of it as credentials for your | 
 |                client software!) | 
 |  | 
 |        - 'DAV:supportedlock' live property: indicates what kinds of | 
 |           locking is allowed on a resource. | 
 |  | 
 |        - the rfc defines an 'opaquelocktoken' scheme that all dav | 
 |          servers must know how to understand: clients may generate and | 
 |          post them in an If: header. | 
 |  | 
 |        - a collection can have a lock of either Depth 0 or Infinity. | 
 |          a lock on a collection prevents adding/removing member URIs. | 
 |          if a lock-holder adds something to a deeply locked | 
 |          collection, then the newly added member becomes part of the | 
 |          same write lock. | 
 |  | 
 |        - a 'null resource' (which normally returns 404) can be locked, | 
 |          in order to reserve a name.  see section 7.4. | 
 |  | 
 |  | 
 | * other methods added by WebDAV: | 
 |  | 
 |    - COPY:  - copies resource to Destination: header. | 
 |             - optional "Overwrite: [T | F]" header defaults to T. | 
 |             - for collections, either Depth: [0 | infinity] allowed. | 
 |             - client can specify how to behave when copying props. | 
 |  | 
 |    - MOVE   - defined to be COPY + DELETE, but an atomic operation. | 
 |  | 
 |  | 
 | ------------------------------------------------------------------------- | 
 |  | 
 | DeltaV | 
 | ====== | 
 |  | 
 | Models | 
 | ====== | 
 |  | 
 | A DeltaV server can support two different ways of working: server-side | 
 | working copies, and client-side working copies.  These systems aren't | 
 | mutually exclusive at all.  An OPTIONS request reveals which systems | 
 | the server supports. | 
 |  | 
 |  | 
 | The General Concepts | 
 | ==================== | 
 |  | 
 | If you understand this, everything will become really clear.  These | 
 | are the fundamentals. | 
 |  | 
 | DeltaV allows you version any kind of resource -- a file, a | 
 | collection, whatever. | 
 |  | 
 |  * If you take a resource on a server and put it under version control | 
 |    (using the VERSION-CONTROL method), a "Version Controlled | 
 |    Resource", or VCR, is created.  A VCR is a special thing: it's a | 
 |    unique, permanent URL used to talk about an entity under version | 
 |    control, no matter how many times it changes. | 
 |  | 
 |  * Every time you change a VCR (discussed below), a new "Version | 
 |    Resource" is created, or VR.  The VR is also a unique, permanent | 
 |    URL, representing some immutable object on the server; it | 
 |    represents the contents and (dead) properties of the VCR at one | 
 |    particular moment in time. | 
 |  | 
 |  * At any given time, a VCR has a "pointer" to some particular VR of | 
 |    itself.  The pointer is just a property, called "DAV:checked-in". | 
 |    By definition, the contents of the VCR are always equal to the | 
 |    contents of the VR it points to.  If you change the pointer to a | 
 |    different VR, the VCR's contents magically change to match. | 
 |  | 
 |  * All of a VCR's VR objects need to be organized somehow.  And in | 
 |    fact, they *are* organized into a little tree of predecessors and | 
 |    successors.  It turns out that every VCR has a "history" resource | 
 |    sitting in the background.  (The history resource may or may not be | 
 |    directly accessible, depending on whether the server supports the | 
 |    'Version History' feature.)  Regardless, a VCR's history resource | 
 |    is a container that contains all of the VRs, organized into a | 
 |    tree.  You might think of a history resource like an RCS | 
 |    file... except that the history is allowed to contain 'forks', | 
 |    i.e. a VR in the history might have multiple predecessors or | 
 |    successors.  Also, each VR in a history can have a human-readable | 
 |    "label" attached to it, so it's easier to talk about which VR you | 
 |    want. | 
 |  | 
 |  | 
 | Changing a VCR | 
 | ============== | 
 |  | 
 | So, how do you make a change to VCR, then?  It all depends on what | 
 | deltaV features the server supports. | 
 |  | 
 |  * If the user is using the server-side working-copy model: | 
 |  | 
 |      - The client creates something called a 'workspace', using | 
 |        MKWORKSPACE. | 
 |  | 
 |      - CHECKOUT a VCR into the workspace.  The VCR's 'DAV:checked-in' | 
 |        property suddenly becomes a 'DAV:checked-out' property... but | 
 |        it still points to the same VR. | 
 |  | 
 |      - Use PUT and PROPATCH to change the contents or dead props of | 
 |        the VCR.  If you want to revert everything, just UNCHECKOUT. | 
 |  | 
 |      - CHECKIN the VCR.  A new VR is created in the VCR's history, and | 
 |        the 'DAV:checked-out' property becomes a 'DAV:checked-in' | 
 |        property, pointing to the new VR. | 
 |  | 
 |  * If the user is using the client-side working-copy model: | 
 |  | 
 |      - The client creates something called an 'activity', using | 
 |        MKACTIVITY. | 
 |  | 
 |      - CHECKOUT a VR into the activity.  This creates a temporary | 
 |        'working resource' (WR) in the activity.  The VCR's | 
 |        'DAV:checked-in' property suddenly becomes a 'DAV:checked-out' | 
 |        property... but it still points to the same VR.  The WR has a | 
 |        'DAV:checked-out' property that points to VR as well. | 
 |  | 
 |      - Use PUT and PROPATCH to change the contents or dead props of | 
 |        the WR.  If you want to revert everything, just UNCHECKOUT. | 
 |  | 
 |      - CHECKIN the WR.  A new VR is created in the VCR's history, and | 
 |        the VCR's 'DAV:checked-in' property points to it.  And | 
 |        normally, the temporary WR is deleted.       | 
 |  | 
 | See?  Not such a big deal.  Ahem. | 
 |  | 
 |  | 
 | Auto-Versioning | 
 | =============== | 
 |  | 
 | What if some regular WebDAV client tries to use a deltaV server?  Or | 
 | an even dumber HTTP 1.1 client?   | 
 |  | 
 | If the server supports the 'auto-versioning' feature, then all | 
 | resources gain a new live property called 'DAV:auto-version'.  The | 
 | value of this property indicates how the server should behave when a | 
 | non-deltaV client does an ignorant PUT or PROPPATCH on a resource.  I | 
 | won't go into detail, but there are many possible behaviors: | 
 |  | 
 |   * do an implicit (auto-) CHECKOUT and CHECKIN. | 
 |   * auto-CHECKOUT, and wait for a lock to vanish before auto-CHECKIN. | 
 |   * same as above, but if not locked, wait for an explicit CHECKIN. | 
 |   * require a lock.  LOCK causes auto-CHECKOUT, UNLOCK causes auto-CHECKIN. | 
 |  | 
 |  | 
 |  | 
 | Basic Features | 
 | ============== | 
 |  | 
 | DeltaV has a bunch of "basic features", and a bunch of "advanced | 
 | features".  Here are the basic features, in a nutshell. | 
 |  | 
 |  | 
 | * Version Control feature | 
 |  | 
 |     * new VERSION-CONTROL method to create a VCR. | 
 |  | 
 |     * resources gain a whole bunch of new live props (not all listed | 
 |       here), such some of which include DAV:checked-[in|out], | 
 |       DAV:auto-version, DAV:comment, the author.  VRs have properties | 
 |       that describe lists of successor and predecessor VRs. | 
 |  | 
 |     * new REPORT method.  two 'standard' reports are defined, but | 
 |       custom reports can be created. | 
 |  | 
 |  | 
 | * Checkout-in-place feature | 
 |   | 
 |     * new CHECKOUT, CHECKIN, UNCHECKOUT methods, which are able to | 
 |       modify VCRs in-place. | 
 |  | 
 |  | 
 | * Version History feature | 
 |  | 
 |     * version histories become tangible URLs.  introduce new dav | 
 |       resourcetype called 'DAV:version-history'. | 
 |  | 
 |     * all VCRs and VR's gain a 'DAV:version-history' prop that points | 
 |       to their history resource. | 
 |  | 
 |     * a version-history has a 'DAV:version-set' property that lists | 
 |       all VRs it contains, and a 'DAV:root-version' that points to the | 
 |       very first VR in the history. | 
 |  | 
 |     * a special REPORT allows one to convert a version-history URL | 
 |       into the VCR it represents.  (i.e. reverse-lookup.) | 
 |  | 
 |  | 
 | * Workspace feature | 
 |  | 
 |     * MKWORKSPACE creates a server-side working area.  an OPTIONS | 
 |       request can tell you where the client is allowed to do this. | 
 |  | 
 |     * the workspace resource has a property that lists all the | 
 |       resources it contains.  regular resources have a property | 
 |       indicating what workspace they're in. | 
 |  | 
 |     * The workspace can hold unversioned items put there by PUT & MKCOL. | 
 |       It can hold VCRs via CHECKOUT. | 
 |  | 
 |     * Special:  the VERSION-CONTROL method can create a *new* VCR from | 
 |       a history.  If two people both CHECKIN VCRs created from the | 
 |       same history resource, then poof... the history develops forks! | 
 |  | 
 |  | 
 | * Update feature | 
 |  | 
 |     * UPDATE method is able to tweak a VCR to "point" to a new VR. | 
 |       Very simple! | 
 |  | 
 |  | 
 | * Label feature | 
 |  | 
 |     * LABEL method allows you to attach a human-readable name to a | 
 |       particular VR.   | 
 |  | 
 |     * Each VR can have many names.  They're listed in a | 
 |       'DAV:label-name-set' property. | 
 |  | 
 |     * New http request header, "Label:", can be used to target | 
 |       a specific VR of a VCR.  This works when doing a GET of a VCR. | 
 |       It also works as you think on COPY, CHECKOUT, UDPATE, etc. | 
 |  | 
 |  | 
 | * Working Resource feature | 
 |  | 
 |     * This feature essentially allows client-side working copies to | 
 |       synchronize their data with the server. | 
 |  | 
 |     * all VRs gain two properties that control whether or not | 
 |       histories can (or should) contain forks. | 
 |  | 
 |     * a CHECKOUT of a VR creates a temporary 'working resource' (WR), | 
 |       which can then be modified.  When the WR is checked in, a new VR | 
 |       is created as usual, the WR vanishes, and the VCR is updated to | 
 |       point to the VR as usual. | 
 |  | 
 |     * note that this technique is an alternative to the | 
 |       Checkout-in-place feature, whereby VCRs are directly checked out | 
 |       and modified. | 
 |  | 
 |  | 
 |  | 
 | Advanced Features | 
 | ================= | 
 |  | 
 | The advanced features of deltaV introduce a bunch of new concepts. | 
 | Here are the fundamentals. | 
 |  | 
 | [Whenever I say, "points to", I'm talking about some object leading to | 
 | another object via a specific property.] | 
 |  | 
 | * A "configuration" is a set of VCRs.  In particular, it contains a | 
 |   "root collection" which organizes the VCRs in some way. | 
 |  | 
 |   Note that this is _different_ than a versioned collection.  The main | 
 |   difference is that a collection is a *single* resource which | 
 |   contains dead-props and some directory-entries; its VRs just capture | 
 |   various states of the props and dirents.  But it's just ONE | 
 |   resource.  A configuration, however, is a SET of VCRs.  The VCRs may | 
 |   not necessarily be related to each other, either.  A configuration | 
 |   is a flexible thing -- its VCRs can be tweaked to point to | 
 |   different VRs, however you want, with no versioning happening in the | 
 |   background.  A collection, on the other hand, has a static set of | 
 |   dirents; to change them, you have to do a CHECKOUT, CHECKIN, which | 
 |   results in a new, static collection VR. | 
 |  | 
 | * A "baseline" is a special kind of resource which remembers this | 
 |   state of a configuration... it knows exactly which VR each VCR in | 
 |   the configuration should point to.  Just like a VR is a 'snapshot' | 
 |   of a VCR, a baseline is a 'snapshot' of the configuration.  And just | 
 |   like a VR, a baseline can have a human label too. | 
 |    | 
 | * Another kind of resource is a "version controlled configuration", or | 
 |   VCC.  This resource floats out in space;  its sole purpose is to | 
 |   magically connect a configuration to a baseline.   Specifically, | 
 |   each VCR in the configuration points to the VCC, and the VCC points | 
 |   to a baseline. | 
 |  | 
 |   And here's the usual magic: if you make the VCC point to a different | 
 |   baseline, then poof, the whole configuration suddenly switches to | 
 |   the baseline.  (That is, all of the configuration's VCRs suddenly | 
 |   point to the specific VRs of the baseline.) | 
 |  | 
 | * Finally, it's worth mentioning that a baseline resource points to a | 
 |   "baseline collection" resource.  This collection is a tree made up | 
 |   of the VRs in the baseline, easily browseable.  You can think of it | 
 |   as a "what-if" sort of preview -- i.e. "what would the configuration | 
 |   look like if I made its VCC point to this baseline?"  It also means | 
 |   people can view a baseline in action, *without* having to tweak a | 
 |   VCC, which might require write access of some kind. | 
 |  | 
 |  | 
 | Got all that?  Good.  Make some pictures.  :-) | 
 |  | 
 |  | 
 | How to create new baselines | 
 | =========================== | 
 |  | 
 | The "in-place" method: | 
 |  | 
 |    Get this.  A VCC is really just a special kind of VCR!  But it's a | 
 |    VCR which represents the *whole state* of a configuration.  Just | 
 |    like a normal VCR, the VCC's "DAV:checked-in" property points to a | 
 |    baseline, which just a special kind of VR. | 
 |  | 
 |    That means you can do a CHECKOUT of the VCC in-place... then tweak | 
 |    the configuration to point to a new set of VR's... then CHECKIN the | 
 |    VCC.  Poof, a new baseline is created which captures your new | 
 |    configuration state.  And the VCC now points to that new baseline. | 
 |  | 
 | The "working resource" method:    | 
 |  | 
 |    Okay, so a baseline is a special kind of VR.  Fine, so we do a | 
 |    CHECKOUT of it, and get a "working baseline", which a special kind | 
 |    of WR.   | 
 |  | 
 |    Now, assuming you're using this method all around, you checkout the | 
 |    configuration's various VRs as WRs, modify the WRs, and check them | 
 |    back in to create new VRs.  Finally, you CHECKIN the working | 
 |    baseline, which creates a new baseline that captures the state of | 
 |    the configuration.  (The working baseline isn't something you tweak | 
 |    directly;  it's more like a token used at CHECKIN time.) | 
 |  | 
 |  | 
 | How Merging Works... at least for SVN. | 
 | ================= | 
 |  | 
 | The deltaV MERGE command is very fancy.  It tracks merge ancestors in | 
 | properties, and sets flags for clients to manually resolve conflicts | 
 | on the server. | 
 |  | 
 | Subversion uses MERGE in a simpler way: | 
 |  | 
 |   1. We checkout a bunch of VRs into an activity, and patch them as a | 
 |      bunch of WRs. | 
 |  | 
 |   2. We checkout a "working baseline" into the activity, from whatever | 
 |      baseline represents the HEAD svn revision. | 
 |  | 
 |   3. We issue a MERGE request with the activity as the source. | 
 |  | 
 |      By definition, this causes the whole activity to be | 
 |      auto-checked-in.  First each WR in the activity is checked-in, | 
 |      causing the configuration to morph.  Then the working-baseline in | 
 |      the activity is checked-in, which creates a new baseline that | 
 |      captures the configuration state. | 
 |  | 
 | Of course, mod_dav_svn doesn't actually do all the checkin stuff;  but | 
 | what's important is that the *result* of the MERGE is exactly as IF | 
 | all this stuff had happened.  And that's all that matters. | 
 |  | 
 |  | 
 |  | 
 |  |