WebDAV Working Group Jim Amsden, Geoff Clemm
INTERNET DRAFT IBM, Rational
<draft-ietf-webdav-versionmodel-00.html> February 1, 1999
Expires August, 1999

Web Versioning Model

Status of this Memo

This document is an Internet-Draft. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or made obsolete by other documents at any time. It is inappropriate to use Internet- Drafts as reference material or to cite them other than as "work in progress."

To view the list Internet-Draft Shadow Directories, see http://www.ietf.org/shadow.html.

Distribution of this document is unlimited. Please send comments to the Distributed Authoring and Versioning (WebDAV) working group at ietf-dav-versioning@w3.org, which may be joined by sending a message with subject "subscribe" to ietf-dav-versioning-request@w3.org. The main WebDAV mailing list at w3c-dist-auth@w3.org may also be used for comments. It may be joined by sending a message with subject "subscribe" to w3c-dist-auth-request@w3c.org.

Discussions of the WebDAV versioning working group are archived at http://lists.w3.org/Archives/Public/ietf-dav-versioning/. Discussions of the WebDAV working group are archived at http://www.w3.org/pub/WWW/Archives/Public/w3c-dist-auth.

Abstract

Distributed authoring for the web requires support for versioning resources, parallel development, and management of configurations of related resources. This document presents a high-level model of WebDAV versioning that realizes the requirements and use cases presented in the "Goals for Web Versioning" available at http://www.ietf.org/internet-drafts/draft-ietf-webdav-versionreqs-00.html.

Contents

Status of this Memo 1
Abstract
Contents
Introduction
WebDAV Versioning Semantics Overview
Versioning Model
Rationale
Security Considerations
References

Introduction

This document provides a model of the versioning extensions to WebDAV including parallel development and configuration management. This model will hopefully provide a framework in which the WebDAV versioning Working Group can specify and evaluate the semantics of various alternatives as they are being explored. The model provides a more formal definition of the elements manipulated by WebDAV, and the behaviors that are supported. By using this model, the working group can concentrate on the semantics of the versioning and configuration management operations without getting bogged down in the details of how it might be represented in a particular protocol or specific implementations. Once the objects and methods have been identified, the protocol can be specified so that these methods can be executed remotely by a WebDAV compliant server.

Various use cases were captured in the goals document, and explored by developing collaboration or object interaction diagrams that describe the sequence of events and how each participating object responds. This can be used to completely formalize the accepted versioning semantics of WebDAV and can be used as an adjunct to the published protocol specification. Such a model will be vary useful for fleshing out the exact semantics and for documenting those semantics in a form that is very useful to server implementers.

Finally, this model provides a tentative specification for a high-level API that could be used to simplify client access to the WebDAV versioning protocol.

In defining the semantics for WebDAV versioning, it is helpful to adhere to some guidelines. The purpose of these guidelines is to help select from various alternatives, and to ensure the result provides the required functions but is as simple as possible so that servers can easily implement the protocol on a variety of repository and configuration management systems, and clients can easily be written and used by web application authors.

WebDAV Versioning Semantics Overview

This section provides an overview of the WebDAV versioning semantics. Subsequent sections provide detailed methods and semantic rules.

Creating Versioned Resources

A resource is any potentially statefull entity that can be accessed on the web through a URL. The model below defines an interface, Resource that abstracts a web resource and its behavior. It also defines a specialization of Resource called ResourceCollection that adds containment or grouping behavior for Resources and other ResourceCollections using the Composite pattern.

A resource may or may not be versioned. When a resource is first created by using a WebDAV PUT or MKCOL method, or Resource.setContents(), it is created as an un-versioned resource. A resource may be checked in to make it a versioned resource, and to create the initial or first revision. A checked in revision cannot be modified by anyone at any time.

Naming Revisions: Revision Ids and Labels

Each revision of a versioned resource must be distinguished from any other revision. Revision names are used to distinguish revisions and consist of either a revision id or any number of revision labels. A revision of a versioned resource is given a system assigned revision id when it is checked in. This revision id acts as an immutable identifier distinguishing this revision from all others of the same versioned resource. The revision id cannot be changed, assigned to another revision, or reused.

A user may assign other revision names called revision labels to a revision in order to distinguish it from other revisions using more meaningful names.   The revision labels must be unique for any given versioned resource, but may be reassigned to any revision of the versioned resource at any time. Revisions of different versioned resources may have the same label. There is a distinguished, floating label called "latest" which always refers to the latest revision in a given activity.

Modifying a Versioned Resource

Subsequently, a client may checkOut the resource which creates a working resource. A working resource is identical to an un-versioned resource in all respects other than that it has one or more successors. It may be edited by setting its properties or contents any number of times. When the client is satisfied that the working resource is in a state that should be retained in the version history, the client does a Resource.checkIn() to create a new revision of the resource.

Users can use checkout/checkin to register intent to modify a versioned resource similar to the way lock and unlock are used in DAV level 2. The sense is reversed though. A checked in revision cannot be changed without checking it out first.

The resource may be checked in as either mutable or immutable. An immutable revision cannot be changed and provides a stable environment for history management, change recovery, merging, and configuration management. A mutable revision is more suitable for situations where versioning is treated more informally, and it is not necessary or desirable to maintain strict version histories, or to be guaranteed that it is always possible to backtrack to a previous point in time and recover. This form of versioning is typical of modern document management systems. If the revision is mutable, a subsequent checkout makes the revision a working resource, and allows the revision to be updated in place without creating a new revision. Any previous contents of the revision are lost. A mutable revision can also be checked out creating a new revision if the user wants to retain the previous revision. If the revision is immutable, a checkout must create a new revision. Servers may choose to not allow revisions to be checked in as mutable, or they may not allow a revision to be checked out without creating a new revision.

Parallel Development with Activities

When a revision of a versioned resource is already checked out, another user cannot check it out again and therefore cannot make any changes. In order to increase resource availability, avoid serializing work, and allow multiple users to make changes simultaneously, a server may support parallel development. Parallel development allows users to choose to do work on a resource that is checked out by someone else in a different context, and to merge those changes together at some later time.

Resources are checked out in the context of an activity. An activity abstracts a set of related changes a user is making to revisions of versioned resources. Each activity represents a parallel thread of development. Servers that don't support parallel development only support one activity. A revision that is already checked out in an activity cannot be checked out again in the same activity. If parallel development is desired, a user can checkout the revision in another activity and merge them later.

Selecting Revision through the Workspace

Resources, working resources, and revisions of versioned resources are all accessed using a URL. Specific revisions of a versioned resource can be accessed by specifying the resource URL and a version label. However, versioned resources are usually accessed using a simple URL. The revision selected when a specific revision name is not specified is resolved through a workspace. A workspace is a resource that provides a context defining a mapping between URLs for versioned resources, and specific revisions. This allows versioned resources and un-versioned resources to be accessed the same way supporting relative ULRs and DAV level-2 clients that are not versioning aware.

A workspace contains a revision selection rule. A revision selection rule can specify any number of entries consisting of revision labels, activities, configurations, or the special floating labels "checkedout" or "latest". The rules are applied in order until the first match is found. A label matches a revision having the matching label. Activity specifies the latest revision that was modified in an activity. Configurations specify a revision contained in the configuration. Checkedout specifies any revision that is currently checked out. Finally, latest refers to the latest revision. Any potential matches after the first match are ignored. Revisions are selected by iterating over the entries in the revision selection rule in order until a matching revision is found. If there is no matching revision, then a resource not found status is returned. This rule is applied to collections to select the revision that determines their member versioned resources, and to other resource to determine the revision containing their contents.

The first three entries of the revision selection rule are defined by the server, and are fixed. These entries are: "checkedout", the current activity, and the merge activity. The result is that revisions are selected using the following rules in order: 1) if there is a checked out revision, then it is selected. else 2) if there is a revision that is checked in under the current activity, then it is selected, else 3) if the resource is a member of any activity in the process of being merged into this workspace, then it is selected, else 4) finally, other entries in the workspace revision selection rule are applied to select the revision. The revision selection rule can only contain one or two activities, the current activity and optionally the merge activity. This is required to prevent non-deterministic merge conflicts.

If a request is made and no workspace is specified, a default workspace containing "checkedout", activity named "mainline", no merge activity, and "latest" in the version selection rule is used.

Configuration Management

A workspace represents a volatile set of revisions. Any new checkouts, changes to the current activity, merging operations, changing labels, or changes to the revision selection rule may result in the selection of different revisions. A configuration is a resource that represents a set of  immutable revisions. A configuration contains a specific revision of each member versioned resource. A configuration cannot contain a mutable revision because the semantics of configurations cannot be guaranteed. A workspace whose version selection rule contains a configuration will always return the same revisions as long as there are no revisions checked out and nothing in the current activity.

Configurations are convenient for defining a persistent set of revisions that relate to each other in some specific way at some point in time. This can be useful for publishing consistent versions of resources to publish or deploy an application, or for recovering to a specific version state for legal or maintenance reasons.

Collections, activities, and configurations are all related in that they have members. The members of a collection are the versioned resources it contains, without specifying any particular revision. The members of an activity are the revisions that have been changed. The members of a configuration are particular revisions. So while they are similar, each has it's own special semantics.

Versioned Collections

A collection contains a set of members. For versioned collections, the members are versioned resources, not particular revisions. To add or remove members from a revision of a versioned collection, it must be checked out just like any other resource. Creating a new revision of a member, or modifying a member has no effect on the collection. Deleting a versioned resource that is an internal member from a collection does not delete the versioned resource, it only deletes the member from that version of the collection. The resource may still be a member of a previous or subsequent revision of the collection. The URL for a collection without a particular revision name is resolved to a particular revision using the workspace the same as any other resource. If the collection is part of a URL for some other resource, then its members are determined from the selected revision.

When a revision of a collection is added to a configuration, then recursively, so are all its members. This is similar to COPY and MOVE which must specify infinite depth.

Revision History

A revision may have more than one predecessor and more than one successor. A predecessor of a revision is a revision that this revision was derived from. A successor of a revision is a revision derived from this revision. Each revision has a line-of-descent that consists of a path from the initial revision of the resource to the selected revision along the successor/predecessor relationships. A line-of-descent specifies a portion of the overall history of the versioned resource.

Each revision has a predecessor relationship with the revision it was checked out or merged from, and a successor relationship with revisions that were checked out from it. Revisions are related to their predecessor through a is-derived-from or merged-from relationships. The revision history of a versioned resource includes these relationships.

Merging

Each activity represents a separate parallel thread of development. Users make their changes in the context of an activity. Changes to the same revision must be done in separate activities. At some point, a user may want to merge changes made to the same revision together to create a new revision containing the combined updates. In order to do a merge, it is first necessary to determine what must be merged. A merge conflict report lists the resources that have been modified in parallel in different activities. The merge conflict report is generated using the following rules: 1) if the merge source specifies a predecessor of the revision selected by the workspace, then the workspace revision is selected, else 2) if the merge source specifies a successor of the revision selected by the workspace, then the merge source revision is selected, else 3) the merge source and the current workspace specify revisions that are on different lines-of-descent which results in a merge conflict that is included in the merge conflict report.

A user can request the differences between two revisions of a resource (servers may provide a differences report, but they must at least indicate if they are the same or not). A user can request conflicts between an activity and the current workspace to generate a merge conflict report. A user can also request the differences between a configuration and the current workspace which lists at least the activities that are contained in the configuration but not in the workspace and vice versa. So differences are detected at different levels: content differences for resources, revision differences for activities, and activity differences for configurations.

Once the merge conflicts are known, a user resolves the conflicts by merging the source activity with the workspace. This enters the merge source into the workspace, and sets the current conflicts that must be resolved. The conflicts are resolved by merging the revisions from the merge source into the revision selected by the workspace to create a new working resource. Servers may perform some default auto merging, but at a minimum, the merge is done by checking out the revision in the current activity (if it is not already checked out) and noting the merge from the merge source. This creates an additional successor/predecessor relationship between the merge source and workspace revisions called merged-from. The conflict is now removed because the working resource is now a successor of both the source and target revisions. It is the user's responsibility to apply the differences in the two revisions in an appropriate manner. The merge is complete when all the conflicts are resolved, all differences have been merged, and the resources are all checked back in. The merge source can now be removed from the workspace as all of its changes are now included in the current activity. Only one activity can be merged at a time in order to provide deterministic, manageable conflict reports.

When merging mutable revisions, the merge conflict report may be inaccurate as the source revision may change without the system being aware. Users are responsible for applying any changes to ancestor revisions to their descendants as appropriate. The system cannot determine if there are any changes that need to be applied other than by looking a the last-modified dates of the revisions.

Locking Versioned Resources

Locking a versioned resource prevents any revision from being checked out in any activity. Locking a revision of a versioned resource prevents just that revision from being checked out in any activity.

The following sections define the model in more detail, and provide the semantic rules for versioning, branching, and configuration management.

Versioning Model

wpe1.gif (20529 bytes)

Repository

A Repository represents a central point of control and a source for resources managed by the repository. It is introduced to support methods that apply to all resources contained in the repository. A repository corresponds to the root collection of the resources contained in it.

Repository
getDefaultActivity() : Activity Get the default activity for this repository. If the default activity was never set, an activity called "mainline" is returned.
setDefaultActivity(defaultActivity : Activity) Set the default activity for this repository to the given value.
getActivities() : Activity[] Get a list of all the activities that currently exist in this repository.
getWorkspaces() : Workspace[] Get a list of all the workspaces that currently exist in this repository.

Resource

Interface Resource represents anything on the Web that is accessible through a URL, i.e., a WebDAV resource. Resource provides a number of methods that abstract resource behavior as specified by WebDAV including:

The following table gives the methods of Resource concerning versioning and configuration management, and a brief description of their semantics. Not all of these methods will correspond directly to WebDAV protocol. Many of them are client convenience methods to make the semantics clearer and easier to use. These methods should be considered to be implemented in terms of other more primitive methods that do correspond directly to methods of the protocol.

Note that in the model above, all the types are interfaces even though associations are shown. This is just to simplify the model for exploratory purposes. The model also does not imply any particular implementation of these interfaces. The model should include implementation classes that use the State pattern to factor out the differences in behavior that arise as a resource goes through its lifetime. A Resource implementation delegates state-dependent methods to its current state object where they can be implemented in a state-specific way. ResourceState is an abstract super-class of all Resource states. Its methods include all the methods of Resource that are state dependent. For example, setContents() is a state-dependent method. It's behavior changes depending on the lock state of the resource. Similarly, many of the methods that update a resource or its properties depend on the versioning and mutability states of the resource. Likely candidates for Resource states (subclasses of ResourceState) are:

This approach provides a simple way of modeling state-specific behavior without complicating the model with many more interfaces, classes, multiple-inheritance, etc. Also, many versioning methods can be equally well implemented on un-versioned resources. For example, getPredecessor() could just return NULL for an un-versioned resource as it doesn't have a predecessor. Neither does the root revision. Taking this approach simplifies both the model and the versioning semantics.

Resource

Resource.create(url : String, label : String = NULL) : Resource Instantiate a Resource with the given URL and label. If label is specified, the Resource corresponds to the instance with the given label. This method does not actually access the server, but creates a Resource instance that can be used to call other methods like exists(), getContents(), etc. That is, it sets the context of the resource and its URL and revision label.
Resource.create(url : String, workspace : Resource = NULL) : Resource Instantiate a Resource with the given URL in the context of the given workspace. If workspace is specified, the Resource corresponds to the revision selected by the workspace. This method does not actually access the server, but creates a Resource instance that can be used to call other methods like exists(), getContents(), etc. That is, it sets the context of the resource and its URL and workspace to use for resolving that URL to a specific revision.
checkIn(isMutable : boolean = false) Checkin a resource creating a new revision and releasing the resource in the current activity so others may check it out.

If isMutable is true, the revision is marked as a mutable revision and can be checked out in-place at some future time. A server may refuse to check in a resource as mutable.

If isMutable is false and the predecessor is mutable, the predecessor is set to the closest immutable ancestor. This is required to ensure accurate merge conflict reports.
checkOut(inPlace : boolean = false) : Resource Check out a resource in order to create a new working resource. A resource is checked out in the context of the workspace current activity, and can only be checked out once in a given activity.

If inPlace is true, and the revision is mutable, then the revision itself becomes a working resource and all updates are in place, destroying any previous contents.

CheckOut fails is the resource is not a versioned resource, is already checked out in the current activity, or is locked.

cancelCheckOut() Cancel the checkout of this working resource, delete the working resource, and remove any predecessor/successor relationships created by checkout or merge. An exception is raised if the resource is not currently checked out.
getVersioningOptions() : Element Get the versioning options for this resource. Versioning options are established by the server and include:
  • mutable/immutable revisions
  • multiple activities
  • can be a member of a configuration
  • is automatically versioned
isAutomaticallyVersioned() : boolean Return true if this resource is automatically versioned on each method that updates its state (content or properties). Automatic versioning is used to support updates by non-versioning aware clients.
getMutableProperties() : String[] Return a list of the names of mutable live properties for this resource. These are properties that may change even when the resource is checked in.
isVersioned() : boolean Return true if this resource is a versioned resource. A versioned resource has multiple revisions and a revision history.
getRevisionHistory() : Document Get the revision history for a versioned resource. The revision history lists the revisions of a resource and their predecessors and successors. The format of the document is given in section Revision History. The document will not contain any revisions if the resource is not versioned.
getRevisionId() : String Get the system-assigned revision id for this revision. This revision name cannot be changed, and cannot be reused if this revision is deleted. Returns NULL if the resource is not versioned.

The revision id must be unique for the revision across all time. Servers may choose to use an opaque identifier consisting of a time stamp similar to UUIDs for lock tokens.
addLabel(label : String) Add a label to this revision of a versioned resource. The versioned resource must not already have the label on any revision, and the label cannot be the same as any revision id. The label must be removed from one revision before it can be added to a different revision. The operation will fail if the resource is not a versioned resource.

Labels are used to provide meaningful names that distinguish revisions of a versioned resources. They can be used in the revision selection rule of the workspace to specify what revision should be used in that workspace. Revisions may also be accessed by a specific label overriding the workspace.

A revision does not need to be checked out to add a label.

removeLabel(label : String) Remove a label from a revision. An exception is raised if the revision does not have this label.

A revision does not need to be checked out to remove a label.

getLabels() : String[] Return all the labels on this revision, not including its revision id.
isLabeledWith(label : String) Return true if any revision of this versioned resource is labeled with the given label.
getRevisionDescription() : Element Get the description of this revision. The description is an XML element in order to support extensible description formats. This operation is valid for un-versioned resources.
setRevisionDescription(description : Element) Provide a description of this revision. The description is an XML element in order to support extensible description formats. This operation is valid for un-versioned resources.
getPredecessor() : Resource Get the predecessor of this revision, that is, the revision from which this revision was checked out. Returns NULL if the Resource has no predecessor.
getMergePredecessors() : Resource[] Get the predecessors of this revision that were established by merging changes from another activity. The list may be empty.
getSuccessors() : Resource[] Get the immediate successors of this revision, that is, revisions that were created by checking out this revision in some activity. The list may be empty.
getActivity() : Activity Get the activity this revision was created in. Returns NULL for un-versioned resources.
isCheckedOutIn(activity : Activity) : boolean Return true if this revision is checked out in the given activity.
mergeWith(mergeSource : Resource) : Resource Merge the given revision with this working resource or this revision in this workspace by setting the merge predecessor. If this resource is not a working resource, then perform the merge by checking out a new revision in the current activity, and adding a merge predecessor relationship with the new working resource. The result is a checked out working resource that the user agent must update to actually merge the changes.

The merge source can be a mutable revision, but once the merge has been done, any in-place changes to the merge source will not result in a new merge conflict.

mergeCandidates() : Activity[] Return a list of activities on different lines of descent for this revision that are candidates for merging. Returns NULL if the resource is not a versioned resource.
differencesWith(resource : Resource) : Document Return an XML document describing the differences between two revisions, both contents and properties.
isMutable() : boolean Return true if this revision is mutable, that is, it was checked in as a mutable revision. Mutable revisions may be checked out in place in order to make updates that do not require a new revision.

An immutable revision can never   be made mutable, but a new revision can be. A mutable revision can be made immutable by checking it out in place and checking it back is as immutable.

Semantic Rules

  1. When a resource is initially created with setContents() (or any other creation method), it is created as an un-versioned resource.
  2. An un-versioned resource becomes a versioned resource when it is checked in. Checking in an un-versioned resource effectively creates the initial or root revision of the resource. This revision has no predecessors.
  3. A new successor of a revision, called a working resource, can be created by checking out the revision. The working resource is identical to an un-versioned resource in all ways except that it has a predecessor.
  4. A checkout operation on a mutable revision can be either in place, or create a new revision. A check out in place establishes the ability to modify the resource, and effectively makes the revision into a working resource so that it can be modified without making a new revision.
  5. A check out operation on an immutable revision, or a checkout that is not in place on a mutable revision effectively copies the resource to the working resource establishing a predecessor/successor relationship and initial state.
  6. Revisions are checked out in the context of the current activity of the workspace. An activity encapsulates a set of related changes on multiple resources.
  7. A working resource can be updated any number of times without creating a new revision.
  8. A revision that is already checked out (effectively has a successor working resource) cannot be checked out again in the same activity without first checking in the working resource, or checking it out in a different activity.
  9. Deleting a working resource is identical to deleting an un-versioned resource. It effectively cancels the check out.
  10. A working resource is released and available for other changes when it is checked back in. A working resource may be checked in as mutable or immutable.
  11. An immutable revision is created by doing checkIn with isMutable set to false. An immutable revision is frozen for all time and cannot be changed. This is the default behavior for check in.
  12. A mutable revision may be created by doing checkIn with isMutable set to true. The contents of a mutable revision may be changed at any time by checking the mutable revision out without creating a new revision. This is also known as check out in place.
  13. A server may choose to refuse to checkin a revision as mutable.
  14. A mutable resource cannot be a member of a configuration because the state of the configuration would not be stable or reproducible.
  15. Doing an immutable check in of a working resource when the predecessor is mutable changes the predecessor to the closest immutable predecessor. This is required to to support reliable merge conflict reports.
  16. Some live properties of an immutable resource may change over time due to relationships under the control of the server and out of the scope of WebDAV semantics.

ResourceCollection

ResourceCollection is a specialization of Resource that aggregates Resources and ResourceCollections using the Composite pattern. It provides methods for creating collections and accessing their members, as well as methods that add a depth parameter for controlling the behavior of Resource methods when they operate on collections. Depth specifies if the method applies to the collection, the collection and its immediate members, or the collection and recursively all its members.

The most significant new behavior is the ability to add, remove, and get members of the collection. Other Resource methods are overridden or specialized to support specific collection semantics or the depth parameter. Versioning adds a number of new methods:

ResourceCollection

addLabel(label : String, depth : String = ThisResource) Add a label to this revision of a versioned resource and potential recursively all its members. Any effected revision must not already have the label, and the label cannot be the same as the revision id. The operation will fail if the collection is not a versioned resource.

Labels are used to provide meaningful names that distinguish revisions of a versioned resources. They can be used in the revision selection rule of the workspace to specify what revision should be used in that workspace. Revisions may also be accessed by a specific label overriding the workspace.
removeLabel(label : String, depth : String = ThisResource) Remove a label from a revision and potential recursively all its members. An exception is raised if the revision does not have this label.
getCheckedOutMembers() : Resource[] Returns a list of the members of this collection that are checked out in the current activity.

Semantic Rules

  1. All the semantic rules for Resource apply to ResourceCollection as it is also a Resource.
  2. A collection is considered changed if members are added or removed. In particular, a collection is not considered to change if the contents of one of its members changes.
  3. A versioned collection can contain versioned or un-versioned members. A version of a collections specifies the URLs of the members of the collection.
  4. A un-versioned collection can contain versioned or un-versioned members.
  5. A checked in revision of a versioned collection cannot have its immutable properties updated, or members added or removed. A collection does not specify which revision of a versioned resource it contains, only what versioned and un-versioned resources make up its members. Revisions of its members are selected using the workspace version selection rules.
  6. Adding a member to a working collection resource adds the member as an internal member of the working resource.
  7. Deleting a member of a working resource that is contained in its predecessor effectively deletes the direct link to the predecessor member.
  8. Checking out a member of a collection has no effect on the collection.

Versioned Resource

A versioned resource represents all revisions of a particular resource. A versioned resource corresponds to the root or initial version of all the revisions of a resource.

 

VersionedResource

getVersioningOptions() : Element Get the versioning options for this resource. Versioning options include.
  • mutable/immutable revisions
  • multiple activities
  • can be a member of a configuration
  • is automatically versioned
isAutomaticallyVersioned() : boolean Return true if this resource is automatically versioned on each method that updates its state (content or properties). Automatic versioning is used to support updates by non-versioning aware clients.
getMutableProperties() : String[] Return a list of the names of mutable properties for this resource. These are properties that may change even when the resource is checked in.
getRevisionHistory() : Document Get the revision history for a versioned resource. The revision history list the revisions of a resource and their predecessors and successors. The format of the document is given in section Revision History. The document will not contain any revisions if the resource is not versioned.
delete() Delete this versioned resource. The versioned resource and all its revisions are removed from the repository. Any workspaces resolving to a revision of this versioned resource will return resource not found status. Configurations containing a revision of this resource will result in resource not found status when used in the revision selection rule for a workspace.

Activity

An activity represents a named set of revisions to versioned resources. A revision of a resource is checked out in the context of the current activity of the workspace. Edits are made in the context of that activity, and the association is maintained when the resource is checked back in. The same resource can be checked out in many different activities at the same time if the server supports parallel development on that resource. These activities may be merged into other workspaces at some later time to combine the changes. Activities may be used to manage units of work required to update a set of resources in some related way.

Activity

getMembers() : Resource[] Returns a list of revisions that were made in this activity.
contains(resource : Resource) : boolean Returns true if the resource is, or was modified (i.e., checked out) in this activity.
addLabel(label : String) Add a label to the latest revision of all versioned resources modified in this activity. Any effected revision must not already have the label, and the label cannot be the same as the revision id. The operation will fail if the resource is not a versioned resource.
removeLabel(label : String) Remove a label from the latest revision of all versioned resources modified in this activity. An exception is raised if the revision does not have this label.

Semantic Rules

  1. The default  activity is called "mainline". The Repository may provide some other default activity.
  2. The workspace revision selection rule contains the current activity.
  3. Resources are checked out in the context of the current activity.
  4. A revision cannot be checked out more than once at a time in the same activity.
  5. The server provides a collection that contains references to all activities.

Configuration

A Configuration represents a persistent, named set of specific revisions of resources. A configuration can be used to collect together consistent versions of resources that correspond to some release or other unit of work. Configuration specializes ResourceCollection in order to add these new semantics. When a collection is added to a configuration, its members are also recursively added to the configuration. Each member of a configuration must specify a particular version label. The configuration member is identified by its URL and revision id.

Configuration

add(revision : Resource) Add a revision of a resource to a configuration. The revision must be immutable. An exception is raised if the configuration already contains a revision of the resource. This is equivalent to copying a link to a revision into the configuration collection with the additional semantics given below.
add(url : String, label : String = null) Add the labeled revision of a resource to a configuration.

The revision must be immutable. An exception is raised if the configuration already contains a revision of the resource. This is equivalent to copying a link to a revision into the configuration collection with the additional semantics given below.

add(url : String, workspace : Workspace) Add the revision of a resource selected by the workspace to a configuration.

The revision must be immutable. An exception is raised if the configuration already contains a revision of the resource. This is equivalent to copying a link to a revision into the configuration collection with the additional semantics given below.

add(activity : Activity) Add the latest revision of all resources modified by the given activity to the configuration.

All revisions in the activity must be checked in and immutable. An exception is raised if the configuration already contains any revision of a resource in modified by the activity.

remove(revision : Revision) Remove a member revision from a configuration. An exception is raised if the configuration does not contain the revision. This operation is equivalent to deleting a resource from the configuration collection.
contains(revision : Revision) : boolean Return true if this configuration contains the given resource.
differencesWith(configuration : Configuration) : Activity[] Return a list of differences in activities between this configuration and the given configuration. The differences in activities between configurations gives a high level view of the differences between the configurations.

Semantic Rules

  1. A configuration can only contain references to immutable revisions. This is required to ensure the configuration is reproducible.
  2. Adding a revision of a collection to a configuration recursively adds a revision of its members. The revision of the member selected is either one having the same label as the collection, or selected by the given workspace depending on which method is used.
  3. An immutable revision of a collection cannot be contained in a configuration if, recursively, the revision of any of its members selected by the label or workspace are working resources, un-versioned resources, or mutable revisions. This is because the configuration cannot have mutable contents.

Workspace

A workspace is a resource that provides a means to map URLs of versioned resources to particular revisions. A workspace contains a current activity which encapsulates changes made to resources in that workspace. A workspace also contains a revision selection rule that is used to select a revision of a versioned resource. The revision selection rule contains a number of entries that specify implicitly or explicitly a revision. Each entry is examined in order until the first matching entry is found. A matching entry is one that refers to an existing revision of a versioned resource.

When an activity is merged into the workspace, revisions of the same resource that were modified in different activities will conflict. The conflict report is defined by:

<!ELEMENT ConflictReport (ConflictEntry*)>
<!ELEMENT ConflictEntry EMPTY>
<!ATTLIST ConflictEntry 
	source CDATA #REQUIRED
	target CDATA #REQUIRED
>

The revision selection rule for a workspace is defined by:

<!ELEMENT selectionrule (checkedout activity activity?(configuration | label | latest)*)>
<!ELEMENT configuration (#PCDATA)>
<!ELEMENT activity (label | latest)>
<!ELEMENT label (#PCDATA)>
<!ELEMENT checkedout EMPTY>
<!ELEMENT latest EMPTY>

Workspace

getSelectionRule() : Element Get the current revision selection rule. The rule is an XML element whose content contains the selection entries.
setSelectionRule(element : Element) Set the current revision selection rule. The element must be a DAV:selectionrule element.
getCurrentActivity() : Activity Get the current activity for this workspace. All checkouts are done in the context of the current activity. The workspace can only have one current activity at a time.
setCurrentActivity(currentActivity : Activity) Set the current activity for this workspace.
createActivity(url : String) : Activity Create an activity that represents a set of related changes to resources.
Resource getResource(url : String) Resolve a resource URL in the context of this workspace.
mergeWith(mergeSource : Activity) Merge the mergeSource activity with the current workspace. This results in potentially selecting different revisions, and the creation of merge conflicts that must be resolved. Until the conflicts are resolved, the revision returned is the revision that would have been returned before the merge.

This method returns a warning if the mergeSource includes mutable revisions. This is because the merge conflicts are not reliable.

differencesWith(configuration : Configuration) : Activity[] Return a list of differences in activities between this workspace and the given configuration. The differences in activities between a workspace and a configuration gives a high level view of the differences between the configurations.
getMergeConflicts() : Document Return an XML document containing the current merge conflicts in the workspace. If there are no merge conflicts, the merge activity is removed from the workspace.

Semantic Rules

  1. The name of an un-versioned resource is its URL.
  2. The name of a revision of a versioned resource is a composite name consisting of its URL and a revision name or workspace name. It is not yet known how this composite name will be represented as a URL. It may be that the version selection information will be given in a selection path header and the server will also effectively provide direct links to revisions that back-level clients can use to access particular revisions. Client applications are free to provide other naming syntax conventions that they map to the protocol convention. HTTP/1.1 does allow ; in URLs that could be used to separate the URL from a revision label.
  3. A workspace contains a revision selection rule that resolves a URL reference to versioned resource to a particular revision.
  4. A revision selection rule consists of a number of entries that are sequentially applied until a matching revision is found. There are two special entries, "checkedout", and "latest". These are effectively floating labels managed by the server referring to a checked out working resource, or the latest revision.
  5. Each entry in the revision selection rule is either a label name, activity name, configuration name, or one of the functors checkedout or latest.
  6. The first three entries in each revision selection rule are fixed by the server. These entries, in order are: checkedout, current activity, and merged activity. This rule ensures that checked out revisions, revisions in the current activity, or revisions in the activity currently being merged into the workspace are selected before any other revision.
  7. The revision selection rule can only contain two activities, the current activity and the merge activity. In addition, their positions are fixed in the revision selection to be the second and third entry respectively. This is required to keep the merge conflict report deterministic and reasonably simple.
  8. The if no label or workspace is given, the default workspace is used. The default workspace has a revision selection rule that specifies "checkedout", activity "mainline", and "latest". Non-versioning aware clients use the default workspace.
  9. The naming rules apply recursively from the root of a collection hierarchy to a particular revision contained in the hierarchy.
  10. Error 404, resource not found is returned if a label is specified, and the versioned resource does not have the given label, or if the current workspace does not have a matching selection entry for the given resource.
  11. When an activity is merged into the workspace, the revisions selected by the workspace may change. There are three cases:
  12. The server provides a collection that contains references to all workspaces in the repository.

Revision History

Method Resource.getRevisionHistory() returns an XML Document describing the complete version history of a versioned resource including all lines of descent, and all revision ids and labels. DASL or other searching techniques may be used to query the history for specific information, or DOM may be used by applications to access history details.

For example, consider a resource named http://hostname/webdav/versioning.htm (this document). Its revision history might look like:

wpe3.gif (4768 bytes)

The XML Document for this version graph can be created by doing a preorder traversal of the graph. Note that XML uses containment associations where the UML data model above uses a many-to-many association with an associated object. So a straight forward preorder traversal wouldn't look that good in XML and would require a lot of links. For the example graph above, a reasonable compromise might look like:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE versionhistory SYSTEM "versionhistory.dtd">

<D:revisionhistory xmlns:D="DAV:"
  href="http://hostname/webdav/versioning.htm">
  <D:revision id="1">
    <D:label>initialVersion</D:label>
    <D:label>root</D:label>
    <D:comment>This is the first version of the WebDAV versioning document</D:comment>
  </D:revision>
  <D:revision id="2">
    <D:label>workingGroupUpdates</D:label>
    <D:comment>First updates, and complete specification for versioning</D:comment>
      <D:branch id="CM">
        <D:comment>The CM branch adds configuration management to WebDAV versioning</D:comment>
        <D:revision id="CM1.1">
          <D:comment>This is the first version for the CM branch</D:comment>
        </D:revision>
        <D:revision id="CM1.2">
          <D:comment>This is the second version for the CM branch</D:comment>
        </D:revision>
        <D:revision id="CM1.3">
          <D:label>webDAVCM</D:label>
          <D:comment>This is the final version for the CM branch before merging with the parent document</D:comment>
        </D:revision>
      </D:branch>
      
      <D:branch id="TCCM">
        <D:comment>This branch adds configuration management to WebDAV versioning using the TeamConnection model</D:comment>
        <D:revision id="TCCM1.1">
          <D:comment>This is the first version for the TCCM branch</D:comment>
        </D:revision>
        <D:revision id="TCCM1.1">
          <D:label>webDAVTCCM</D:label>
          <D:comment>This is the final version for the TCCM branch before merging with the parent document</D:comment>
        </D:revision>
      </D:branch>
  </D:revision>
  <D:revision id="3">
    <D:comment>This is the third version of the WebDAV versioning document</D:comment>
  </D:revision>
  <D:revision id="4">
    <D:label>initialVersion</D:label>
    <D:label>root</D:label>
    <D:comment>This is the fourth version of the WebDAV versioning document</D:comment>
  </D:revision>
  <D:revision id="5">
    <D:label>initialVersion</D:label>
    <D:label>root</D:label>
    <D:comment>This is the fifth version of the WebDAV versioning document</D:comment>
  </D:revision>
  <D:revision id="6">
    <D:predecessor href="CM2.3"/>
    <D:label>CMVersion</D:label>
    <D:label>CM</D:label>
    <D:comment>This version includes configuration management</D:comment>
  </D:revision>
</D:revisionhistory>

The revisionhistory element contains an implied branch off the null element containing the main line of descent.

The DTD for the version history document is:

<?xml version="1.0" encoding="UTF-8"?>
<!-- WebDAV Version History DTD -->

<!ELEMENT revisionhistory (revision*)>
<!ATTLIST revisionhistory
	href CDATA #REQUIRED <!-- the URL for the versioned resource -->
>

<!ELEMENT revision (label*, comment?, branch*)>
<!ATTLIST revision 
	id ID #REQUIRED <!-- the revision id -->
>

<!ELEMENT branch (comment?, revision*)>
<!ATTLIST branch
	id ID #REQUIRED <!-- the branch name -->
>

<!ELEMENT comment (#PCDATA)>

Rationale

Versioning in the context of the world-wide web offers a variety of benefits:

  1. It provides infrastructure for efficient and controlled management of large evolving web sites. Modern configuration management systems are built on some form of repository that can track the revision history of individual resources, and provide the higher-level tools to manage those saved versions. Basic versioning capabilities are required to support such systems.
  2. It allows parallel development and update of single resources. Since versioning systems register change by creating new objects, they enable simultaneous write access by allowing the creation of variant versions. Many also provide merge support to ease the reverse operation.
  3. It provides a framework for coordinating changes to resources. While specifics vary, most systems provide some method of controlling or tracking access to enable collaborative resource development.
  4. It allows browsing through past and alternative versions of a resource. Frequently the modification and authorship history of a resource is critical information in itself.
  5. It provides stable names that can support externally stored links for annotation and link-server support. Both annotation and link servers frequently need to store stable references to portions of resources that are not under their direct control. By providing stable states of resources, version control systems allow not only stable pointers into those resources, but also well-defined methods to determine the relationships of those states of a resource.
  6. It allows explicit semantic representation of single resources with multiple states. A versioning system directly represents the fact that a resource has an explicit history, and a persistent identity across the various states it has had during the course of that history.

Non-goals

These non-goals enumerate functionality which the working group has explicitly agreed to exclude from this document; they are documented here for explanatory purposes. 

  1. Revisions in multiple revision histories (see [WEBDAV-GOALS], sections 5.9.1.3 and 5.9.2.5).  This capability was felt to be too rarely useful.
  2. Federated revision histories (that is, revision histories which are not stored on a single server).  This capability would introduce great difficulties.  A server implementer who needs it can use out-of-band server-to-server communication; but this communication is arguably out of the scope of WebDAV, which is a client-to-server protocol.
  3. Client-proposed version identifiers (see [WEBDAV-GOALS], section 5.9.2.8).  Labels do the job better.
  4. Change management or change control operations. It is envisioned that policies for change management and the mechanisms to to implement them will be quite variable for the number and types of users authoring content for the web. Therefore it is important to provide core capabilities for versioning, parallel development, and configuration management without hindering the policies client applications may choose to present to their users. It is intended that WebDAV versioning will provide these core capabilities, and that a variety of change management policies could be implemented on these core capabilities by client applications.

Security Considerations

To be written.  It is likely that implementing features to meet the goals described here will present few or no new security risks beyond those of base DAV.  One possible exception is that it may become more difficult to hide the contents of a resource when there may exist other versions with different access control lists.

References

[WEBDAV-VERSION-GOALS] J. Stracke, J. Amsden, "Goals for Web Versioning", Internet-Draft, draft-ietf-webdav-versionreqs-00.html, Jan., 1999.
[WEBDAV]Y.Y. Goland, E.J. Whitehead, Jr., A. Faizi, S.R. Carter, D. Jensen, "Extensions for Distributed Authoring on the World Wide Web -- WEBDAV", Internet-Draft draft-ietf-webdav-protocol-10. Nov., 1998
[WEBDAV-GOALS] J. Slein, F. Vitali, J. Whitehead, D. Durand, "Requirements for a Distributed Authoring and Versioning Protocol for the World Wide Web", RFC-2291.  February 1998.
[WEBDAV-ACP] J. Slein, J. Davis, A. Babich, J. Whitehead, "WebDAV Advanced Collections Protocol", Internet-Draft draft-ietf-webdav-collection-protocol-02.txt.  Nov., 1998.
[DASL] S. Reddy, D. Jensen, S. Reddy, R. Henderson, J. Davis, A. Babich, "DAV Searching & Locating", Internet-Draft draft-reddy-dasl-protocol-04.txt.  Nov., 1998.
[CVS] http://www.cyclic.com/cyclic-pages/books.html
[BONSAI] Mozilla.org, http://www.mozilla.org/bonsai.html