| |
| 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. |
| |
| |
| |
| |