WVCM: The Workspace Versioning and Configuration Management API

Abstract

This document provides an overview of the Workspace Versioning and Configuration Management API.  The WVCM API will minimize the complexity of clients that are capable of interoperating with a variety of both versioning and non-versioning repositories.  The WVCM API includes: basic workspace management, version history management, baseline management, activity management, and namespace versioning.

Table of Contents

1      Introduction.. 3

1.1       Relationship to the DeltaV/WebDAV/HTTP Protocols. 3

1.2       Basic Terms. 3

1.3       Versioning Terms. 4

1.4       Method Preconditions and Postconditions. 6

2      Basic Workspace Semantics.. 6

2.1       Creating a Workspace. 6

2.2       Sharing Resource Changes. 6

2.3       Controlled Folders. 6

2.4       Property Names and Property Name Lists. 7

3      Versioning Workspace Semantics.. 7

3.1       Creating a Version-Controlled Resource. 7

3.2       Modifying a Version-Controlled Resource. 7

3.3       Workspaces and Versioning. 8

3.4       Folder Versions. 8

3.5       Configurations and Baselines. 9

3.6       Activities. 10

3.7       Merging. 11

3.8       Labels. 12

3.9       Unreserved Checkout 12

3.10        Eclipsed Members of a Version-Controlled Folder 12

3.11        Placing a Folder under Baseline Control 13

3.12        Locating Version Histories in a Workspace. 13

4      Non-Versioning Provider.. 13

4.1       Resource. 13

4.2       ControllableResource. 13

4.3       Folder 14

4.4       Workspace. 14

5      Acknowledgements.. 14

6      References.. 14

7      Author's Address.. 14

 

1           Introduction

This document provides an overview of the Workspace Versioning and Configuration Management (WVCM) API.  There are two key concepts in the WVCM API: "workspaces" and "versioning". 

The purpose of a workspace is to provide an environment within which a user can make persistent modifications to a configuration of resources without interfering or disrupting the work of other users of those resources.  This requires that the user be able to persist changes to resources (both content changes and naming changes) without those changes being immediately visible to other users.  To provide this functionality, the persistent changes saved in one workspace (also known as a "sandbox" or a "view") are visible in other workspaces only after the user of that workspace explicitly exposes those changes for use by other workspaces, and after a user of another workspace explicitly requests to see the changes that have been exposed.

In some implementations, a workspace is stored primarily in local persistent storage of the client, and changes are exposed to other workspaces by uploading changed resource names and content to a shared server.  Changes are made visible in another workspace by downloading changes from the shared server to that other workspace.  In other implementations, only the resources being changed are stored on the client, while unmodified resources are stored only on the server.  These implementations are often preferable when there are large numbers of resources (e.g. thousands, or hundreds of thousands), since it would be prohibitively expensive to download all those resources to each client.  Finally, in some implementations, all workspace state is stored on the server.  These implementations have the advantages that they can be used by clients with no local persistent storage, and that the private workspace state can be seen from multiple clients (this is important when a user needs to be able to easily move from one host to another, or when several users are working very closely together).  These implementations are also used when key resources (such as high-performance databases) are required for effective workspace authoring, and these resources are only available on the server.  One of the key challenges of the WVCM API is to hide these implementation choices from a client.

The purpose of versioning is to provide an environment within which previous states of resource (both content and naming) are easily available.  The term "configuration management" is used to emphasize that it is not just isolated resource states that must be easily available, but also consistent configurations of related resources.

The benefits of versioning and configuration management include:

- A resource has an explicit history and a persistent identity across the various states it has had during the course of that history.  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.

- Resource states (versions) are given stable names that can support externally stored references for annotation and linking.  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.

- Sets of resources can be developed in parallel.  Each client has its own configuration of the controlled resources, and can make changes to its configuration without disturbing that of another client.  Consistent groups of changes can then be exposed for use by other clients.

1.1          Relationship to the DeltaV/WebDAV/HTTP Protocols

To maximize interoperability and the use of existing protocol functionality, the WVCM semantic model is designed to be compatible with the DeltaV [RFC3253], WebDAV [RFC2518], and HTTP [RFC2616] protocols.

1.2          Basic Terms

Provider

A WVCM "provider" is an implementation of the WVCM API.  Multiple WVCM providers can be available on a single client host and can be used concurrently by a single client.

Resource, Content, Property, Attribute

A "resource" is a locatable persistent object whose state consists of "content" (an arbitrary sequence of bytes) and a set of "properties" (name/value pairs).  An "attribute" is a user-defined property whose name consists of a user-selected namespace and a user-selected identifier, and whose value is a user-specified string.

Content

The "content" of a resource is an arbitrary sequence of bytes.

Attribute

An "attribute" is name/value pair whose name is user-defined and whose value is a string.

Property

A "property" is name/value pair whose name and value is system-defined.

Controlled Resource, Checked-Out, Checked-In

A "controllable resource" is a resource whose state can be "controlled".  When a resource is controlled, it becomes a "controlled resource".  A controlled resource must be "checked out" in order to modify its content, and then "checked in" to allow that modification to be visible in another workspace.  A controlled resource is always either in a "checked-in" or "checked-out" state.

Folder Resource, Binding, Member

A "folder resource", or simply "folder", is a controllable resource whose state contains a set of named "bindings".  Each folder binding defines a mapping from a name to another resource, called a "bound member" of the folder.  A folder must be checked-out to add, remove, or rename a controlled bound member of that folder, and then checked in to commit that modification.  The "members" of a folder are the folder itself and all bound members of any member of the folder.  In mathematical terms, the member relationship is the transitive closure of the bound-member relationship.  Note that a folder is a member of itself.

Configuration

A "configuration" is a set of resources associated with a particular folder, called the "root folder" of the configuration.  In particular, a configuration consists of all members of the root folder that are not members of another configuration.  Note that a folder (which is a single resource) is very different from a configuration (which is a set of resources).

Workspace Resource

A "workspace resource", or simply "workspace", is a configuration that can have both controllable and controlled members.

Proxy

A "proxy" for a resource is an in-memory object that contains copies of client-selected properties of the resource, and that can be used to apply methods to the resource.

1.3          Versioning Terms

Version Control

When a resource is "version-controllable", a history of its checked-in states is kept after it is controlled.  When a version-controllable resource is controlled, it becomes a "version-controlled" resource.

Version Resource

A "version resource", or simply "version", is a resource that contains a copy of a particular state of a version-controlled resource.  A new version is created whenever the version-controlled resource is checked in.  The server allocates a distinct new location for each new version, and this location will never be occupied by any resource other than that version.  The content of a version never changes.

Predecessor, Successor, Ancestor, Descendant

When a version-controlled resource is checked out and then subsequently checked in, the version that was checked out becomes a "predecessor" of the version created by the checkin.  A client can specify multiple predecessors for a new version if the new version is logically a merge of those predecessors.  When a version is connected to another version by traversing one or more predecessor relations, it is called an "ancestor" of that version.  The inverse of the predecessor and ancestor relations are the "successor" and "descendant" relations.  Therefore, if X is a predecessor of Y, then Y is a successor of X, and if X is an ancestor of Y, then Y is a descendant of X.

Version History Resource

A "version history resource", or simply "version history", is a resource that contains all the versions that are descendants of a particular version, called the "root version" of that version history.  A version history is located in a server defined namespace and therefore is unaffected by any deletion or movement of version-controlled resources.  A workspace contains at most one version-controlled resource for a given version history.

Version Name

A "version name" is a string chosen by the server to distinguish one version of a version history from the other versions of that version history.  Versions from different version histories may have the same version name.

Label

A "label" is a string that can be used to select a version from a version history.  A label can be assigned by either a client or the server.  The same label can be used in different version histories.

Fork, Merge

When a second successor is added to a version, this creates a "fork" in the version history.  When a version is created with multiple predecessors, this creates a "merge" in the version history.  A server may restrict the version history to be linear (with no forks or merges), but an interoperable versioning client should be prepared to deal with both forks and merges in the version history.

The following diagram illustrates several of the previous definitions.  Each box represents a version and each line between two boxes represents a predecessor/successor relationship.  For example, it shows V3 is a predecessor of V5, V7 is a successor of V5, V1 is an ancestor of V4, and V7 is a descendant of V4.  It also shows that there is a fork at version V2 and a merge at version V7.

                     History of foo.html

    

                             +---+

       Root Version -------> |   | V1

                             +---+           ^

                               |             |

                               |             |

                             +---+           |

       Version Name ----> V2 |   |           | Ancestor

                             +---+           |

                             /    \          |

                            /      \         |

                       +---+       +---+

                       |   | V3    |   | V4

                    ^  +---+       +---+

                    |    |           |       |

       Predecessor  |    |           |       |

                       +---+       +---+     |

                       |   | V5    |   | V6  | Descendant

                       +---+       +---+     |

       Successor    |       \      /         |

                    |        \    /          |

                    v        +---+           v

                             |   | V7

                             +---+

 

Folder Version Resource

A "folder version resource", or simply "folder version", captures the names of its controlled bindings.  A controlled binding is a binding to a controlled resource.  A folder version is created by checking out and then checking in a controlled folder.  The list of controlled bindings of a folder version never changes.

Baseline Resource

A "baseline resource", or simply "baseline", of a folder is a version of the configuration that is rooted at that folder.  In particular, a baseline captures the version identified by the CheckedIn property of every version-controlled member of that configuration.  Note that a folder version (which captures the state of a single resource) is very different from a folder baseline (which captures the states of a set of resources).

Baseline-Controlled Folder

A "baseline-controlled folder" is the root folder for a configuration that is being baselined.

Controlled Configuration Resource

A " controlled configuration resource", or simply " controlled configuration", is a special kind of version-controlled resource that is associated with a baseline-controlled folder, and is used to create and access baselines of that folder.  When a folder is both version-controlled and baseline-controlled, a client can create a new version of the folder by checking out and checking in that folder, and it can create a new baseline of that folder by checking out and checking in the controlled configuration of that folder.

Activity Resource

An "activity resource", or simply "activity", is a resource that selects a set of versions that correspond to a single logical change, where the versions selected from a given version history are required to form a single line of descent through that version history.

1.4          Method Preconditions and Postconditions

A "precondition" of a method describes the state on the server that must be true for that method to be performed.  A "postcondition" of a method describes the state on the server that must be true after that method has completed.  If a method precondition or postcondition for a request is not satisfied, a WvcmException will be thrown, containing an integer that identifies the exact condition that was not satisfied.

2           Basic Workspace Semantics

Although the WVCM API is designed to supported workspace management by a versioning server, a simple subset of the WVCM API can be used to support workspace management by a non-versioning server.  In this simplified form, only Resource, ControllableResource, Folder, and Workspace resources are supported.  Each workspace has both private client-side persistent state, as well as server-side persistent state that it shares with other workspaces.  In particular, a copy of the resource state of each checked-in controlled resource is stored persistently on the server.

2.1          Creating a Workspace

In order to create a workspace, a client specifies the location in the local client file system for the root folder of the workspace.  In addition, the client must specify the location on the server for the checked-in controlled resource state that is shared with other workspaces.  A client can then create, browse, and update uncontrolled workspace members (files and folders) through WVCM API calls, or alternatively, through native client file system commands.

2.2          Sharing Resource Changes

In order to share changes to a resource with other workspaces, the client must first put that resource under control using the doControl WVCM API call.  In order to update a controlled resource, a client must first check out that resource using the doCheckout WVCM API call.  A checked-out controlled resource can then be updated in the same ways that an uncontrolled resource is updated, i.e. using WVCM API calls or native client file system commands.  When a client is ready to expose the modified state of a controlled resource to other workspaces, it must use the doCheckin WVCM API call.  If the state of that resource on the server has not changed since the doCheckout call was performed, the local resource state is copied to the server.  If the state of that resource on the server has changed (as a result of a doCheckin call from a client in another workspace that shares that server state), the client must merge its changes with the changes made to the server.  In particular, the client must save its changes to a temporary location, use the doRefresh WVCM API call to retrieve the modified server state, merge its changes with that new state retrieved from the server, and attempt the doCheckin again.  Note that a WVCM implementation will commonly mark a checked-in controlled resource as read-only, to prevent local file system commands from incorrectly modifying a checked-in resource. 

2.3          Controlled Folders

In order to put under control a bound member of a controlled folder, or to add, remove, or rename a controlled bound member of a controlled folder, the folder must first be checked out and then checked in to commit the change.  A request (e.g. doControl, doUnbind, doRebind) MUST fail if it attempts to modify a controlled binding of a checked-in controlled folder.

2.4          Property Names and Property Name Lists

Many property values are defined as a list of references to other resources.  The PropertyNameList provides a mechanism for retrieving in one request the properties from the resources identified by those references.  This not only decreases the number of requests required, but also allows the server to minimize the number of separate read transactions required on the underlying persistent store.

3           Versioning Workspace Semantics

When a server supports versioning, the history of the content of a controlled resource is captured in the form of a set of versions of that resource.  Unlike non-versioning servers, where work can only be effectively shared between the client workspaces that are associated with a common server location, a versioning server allows work to be shared in a very flexible manner between arbitrary workspaces, by merging consistent sets of versions created in one workspace into the corresponding controlled resources of another workspace.

3.1          Creating a Version-Controlled Resource

In order to track the history of the content of a version-controllable resource, a user can put the resource under version control with a doControl request.  The doControl request on a version-controllable resource performs three distinct operations:

1) It creates a new version history resource.  Each version history resource is assigned a new distinct and unique server-defined location.

2) It creates a new version resource and adds it to the new version history resource.  The content of the new version resource is a copy of that of the controllable resource.  The server assigns the new version resource a new distinct and unique location.

3) It converts the controllable resource into a version-controlled resource.  Note that the location of the resource remains unchanged.  As part of this conversion, it adds a CheckedIn property that identifies the new version resource.

In the following example, foo.html is a controllable resource that is put under version control.  After the doControl request succeeds, there are two additional resources: a new version history resource and a new version resource in that version history.  The controllable resource is converted into a version-controlled resource, whose CheckedIn property identifies the new version resource.  The content of a resource is represented by the symbol appearing inside the box for that resource (e.g. "S1" in the following example). 

          ===doControl==>

    

                    |                       +----+ version

                    |   version-            |    | history

       controllable |   controlled          +----+ resource

       resource     |   resource              |

       /foo.html    |   /foo.html             |       

                    |                         v

         +----+     |     +----+ CheckedIn  +----+ version

         | S1 |     |     | S1 |----------->| S1 | resource

         +----+     |     +----+            +----+ /his/73/ver/1

 

Thus, whereas before the doControl request there was only one, uncontrolled resource, after doControl there are three separate, distinct resources, each containing its own state and properties: the version-controlled resource, the version resource, and the version history resource.  Since the version-controlled resource and the version resource are separate, distinct resources, when a method is applied to a version-controlled resource, it is only applied to that version-controlled resource, and is not applied to the version resource that is currently identified by the CheckedIn property of that version-controlled resource.  Although the content of a checked-in version-controlled resource is required to be the same as that of the version identified by its current CheckedIn property, its properties may differ.  An implementation may optimize storage by retrieving the content of a checked-in version-controlled resource from the version identified by its current CheckedIn property rather than storing it in the version-controlled resource, but this is just an implementation optimization.

3.2          Modifying a Version-Controlled Resource

In order to modify the content of a version-controlled resource, the version-controlled resource must first be checked out.  When the checked-out resource is checked in, a new version is created in the version history of that version-controlled resource.  The version that was checked out is remembered as the predecessor of the new version. 

The following diagram illustrates the effect of the checkout/checkin process on a version-controlled resource and its version history.  The symbol inside a box (S1, S2, S3) represents the current content of the resource represented by that box.  The symbol next to a box (V1, V2, V3) represents the location of that resource.

 

          ==doCheckout=>  ==doWriteContent=>  ==doCheckin=>

 

 

         /foo.html (version-controlled resource)

 

          +----+    |    +----+    |    +----+    |    +----+

          | S2 |    |    | S2 |    |    | S3 |    |    | S3 |

          +----+    |    +----+    |    +----+    |    +----+

       Checked-In=V2|Checked-Out=V2|Checked-Out=V2|Checked-In=V3

 

 

         /his/73 (version history for /foo.html)

 

         +----+     |   +----+     |   +----+     |   +----+

         | S1 | V1  |   | S1 | V1  |   | S1 | V1  |   | S1 | V1

         +----+     |   +----+     |   +----+     |   +----+

            |       |      |       |      |       |      |

            |       |      |       |      |       |      |

         +----+     |   +----+     |   +----+     |   +----+

         | S2 | V2  |   | S2 | V2  |   | S2 | V2  |   | S2 | V2

         +----+     |   +----+     |   +----+     |   +----+

                    |              |              |      |       

                    |              |              |      |      

                    |              |              |   +----+    

                    |              |              |   | S3 | V3   

                    |              |              |   +----+    

 

Note that a version captures only a defined subset of the state of a resource.  In particular, a version of a basic resource captures its content, but not its live properties.

3.3          Workspaces and Versioning

Multiple workspaces may be used to expose different versions and configurations of a set of version-controlled resources concurrently.  In order to make changes to a version-controlled resource in one workspace visible in another workspace, that version-controlled resource must be checked in, and then the corresponding version-controlled resource in the other workspace can be updated to display the content of the new version. 

In order to ensure unambiguous baselining (see Section 3.5) and merging (see Section 3.7) semantics, a workspace may contain at most one version-controlled resource for a given version history.  This is required for unambiguous baselining because a baseline can only select one version for a given version-controlled resource.  This is required for unambiguous merging because the doMerge method must identify which version-controlled resource is to be the merge target of a given version.

Initially, an empty workspace can be created.  New resources can then be added to the workspace with methods such as doCreateResource.  Version-controlled resources for existing version histories can be added to the workspace with doCreateControlledResource requests.  Folders in the workspace can be placed under baseline control, and then initialized by existing baselines.

3.4          Folder Versions

As with any version-controllable resource, when a version-controllable folder is put under control, a version history resource is created to contain the versions of that folder.  In order to preserve standard versioning semantics (a version of a folder should not be modifiable), a folder version only records information about the version-controlled bound members of that folder.

In order to cleanly separate a modification to the namespace from a modification to content, a version of a folder has no members, but instead records in its ControlledBindingList property the binding name and version history resource of each version-controlled bound member of that folder.  Since a folder version records only a set of binding name and version history pairs, changing the version selected by a member of a version-controlled folder does not require a new version of the folder to be created.

In the following example, there are three version histories, named VH14, VH19, and VH24, where VH14 contains versions of a folder.  The version-controlled folder /x has version V2 of version history VH14 as its CheckedIn version.  Since V2 has recorded two version controlled bindings, one with binding name "a" to version history VH19, and the other with binding name "b" to version history VH24, /x MUST have two version-controlled bindings, one named "a" to a version-controlled resource for history VH19, and the other named "b" to a version-controlled resource for history VH24.  The version-controlled resource /x/a currently has V4 of VH19 as its CheckedIn version, while /x/b has V8 of VH24 as its CheckedIn version.

 

                                                         VH19

                                                      +---------+

                                                      | +---+   |

                                                      | |   |V4 |

                                                      | +---+   |

                                                      |   |     |

                                                      |   |     |

                                                      | +---+   |

                                                      | |   |V5 |

                                           VH14       | +---+   |

                                       +---------+    |   |     |

                                       | +---+   |    |   |     |

              a  +---+                 | |   |V1 |    | +---+   |

            ---->|   |CheckedIn=V4     | +---+   | a  | |   |V6 |

           /     +---+                 |   |   ------>| +---+   |

          /                            |   |  /  |    +---------+

     +---+                             | +---+   |

  /x |   |CheckedIn=V2                 | |   |V2 |

     +---+                             | +---+   |       VH24

          \                            |   |  \  | b  +---------+

           \  b  +---+                 |   |   ------>| +---+   |

            ---->|   |CheckedIn=V8     | +---+   |    | |   |V7 |

                 +---+                 | |   |V3 |    | +---+   |

                                       | +---+   |    |   |     |

                                       +---------+    |   |     |

                                                      | +---+   |

                                                      | |   |V8 |

                                                      | +---+   |

                                                      |   |     |

                                                      |   |     |

                                                      | +---+   |

                                                      | |   |V9 |

                                                      | +---+   |

                                                      +---------+

 

Although a folder version only records the version-controlled bound members of a folder, a version-controlled folder MAY have both controlled and uncontrolled bound members.  Uncontrolled bound members are not under version control, and therefore can be added or deleted without checking out the version-controlled folder.

Note that a folder version captures only a defined subset of the state of a folder.  In particular, a version of a folder captures its bindings to version-controlled resources, but not its live properties or bindings to uncontrolled members.

3.5          Configurations and Baselines

A configuration is a set of resources that consists of all members of a root folder except those resources that are members of another configuration.  A configuration that contains a large number of resources can consume a large amount of space on a server.  This can make it prohibitively expensive to capture the state of a configuration by creating a copy of all resources in the configuration.

A baseline is a version resource that captures the state of each version-controlled member of a configuration.  A baseline history is a version history whose versions are baselines.  New baselines are created by checking out and then checking in a special kind of version-controlled resource called a version-controlled configuration.

A folder that is under baseline control is called a baseline-controlled folder.  In order to allow efficient baseline implementation, the state of a baseline of a folder is limited to be a set of versions and their names relative to the folder, and the operations on a baseline are limited to the creation of a baseline from a folder, and restoring or merging the baseline back into a folder.  A client can use the doBaselineControl method to put a specified folder under baseline control.

As a configuration gets large, it is often useful to break it up into a set of smaller configurations that form the logical "components" of that configuration.  In order to capture the fact that a baseline of a configuration is logically extended by a component configuration baseline, the component configuration baseline is captured as a "sub-baseline" of the baseline.

The root folder of a configuration is unconstrained with respect to its relationship to the root folder of any of its components.  In particular, the root folder of a configuration can have a member that is the root folder of one of its components (e.g. configuration /sys/x can have a component /sys/x/foo), can be a member of the root folder of one of its components (e.g. configuration /sys/y/z can have a component /sys/y), or neither (e.g. configuration /sys/x can have a component /comp/bar).

In the following example, the folder /src is placed under baseline control, and is populated with members from an existing baseline.  A new version-controlled configuration (/repo/vcc/128) is created and associated with /src, and /src is initialized with version-controlled members whose CheckedIn versions are those selected by the BaselineFolder (/repo/bc/15) of the specified baseline (/repo/blh/13/ver/8).  The following diagram illustrates the resulting state on the server.

     +----------------------------+

     |Baseline-Controlled Folder  |<------+

     |/src                        |       |

     |----------------------------|       |

     |ControlledConfiguration     +---+   |

     +----------------------------+   |   |

                                      |   |

                                      |   |

     +----------------------------+   |   |

     |Controlled Configuration    |<--+   |

     |/repo/vcc/128               |       |

     |----------------------------|       |

     |RootFolder                  +-------+

     |----------------------------|

     |CheckedIn                   +-------+

     |----------------------------+       |

     |VersionHistory              +---+   |

     +----------------------------+   |   |

                                      |   |

                                      |   |

     +--------------------+           |   |

     |Baseline History    |<----------+   |

     |/repo/blh/13        |               |

     |--------------------+               |

     |VersionList         +-----------+   |

     +--------------------+    |   |  |   |

                               v   |  v   |

                                   |      |

     +--------------------+        |      |

     |Baseline            |<-------+------+

     |/repo/blh/13/ver/8  |

     |--------------------+   +------------+

     |BaselineFolder      +-->|Folder      |

     +--------------------+   |/repo/bc/15 |

                              +------------+

 

In order to create new baselines of /src, /repo/vcc/128 can be checked out, new versions can be created or selected by the version-controlled members of /src, and then /repo/vcc/128 can be checked in to capture the current state of those version-controlled members.

3.6          Activities

An activity is a resource that selects a set of versions that are on a single "line of descent", where a line of descent is a sequence of versions connected by successor relationships.  If an activity selects versions from multiple version histories, the versions selected in each version history must be on a single line of descent.

A common problem that motivates the use of activities is that it is often desirable to perform several different logical changes in a single workspace, and then selectively merge a subset of those logical changes to other workspaces.  An activity can be used to represent a single logical change, where an activity tracks all the resources that were modified to effect that single logical change.  When a version-controlled resource is checked out, the user specifies which activity should be associated with a new version that will be created when that version-controlled resource is checked in.  It is then possible to select a particular logical change for merging into another workspace, by specifying the appropriate activity in a doMerge request.

Another common problem is that although a version-controlled resource may need to have multiple lines of descent, a particular team may want all work done by members of that team to be on a single line of descent (to avoid merging between team members).  An activity resource provides the mechanism for addressing this problem.  When a version-controlled resource is checked out, a client can request that an existing activity be used or that a new activity be created.  Activity semantics then ensure that all versions in a given version history that are associated with an activity are on a single line of descent.  If all members of a team share a common activity (or sub-activities of a common activity), then all changes made by members of that team will be on a single line of descent.

The following diagram illustrates activities.  Version V5 is the latest version of foo.html selected by activity Act-2, and version V8 is the latest version of bar.html selected by activity Act-2.

             foo.html History       bar.html History

  

                   +---+                  +---+

              Act-1|   |V1           Act-1|   |V6

                   +---+                  +---+

                     |                      |

                     |                      |

                   +---+                  +---+

              Act-1|   |V2           Act-2|   |V7

                   +---+                  +---+

                  /     \                   |

                 /       \                  |

            +---+         +---+           +---+

       Act-1|   |V3  Act-2|   |V4    Act-2|   |V8   

            +---+         +---+           +---+

                            |               |

                            |               |

                          +---+           +---+

                     Act-2|   |V5    Act-3|   |V9

                          +---+           +---+

 

Activities appear under a variety of names in existing versioning systems.  When an activity is used to capture a logical change, it is commonly called a "change set".  When an activity is used to capture a line of descent, it is commonly called a "branch".  When a system supports both branches and change sets, it is often useful to require that a particular change set occur on a particular branch.  This relationship can be captured by making the change set activity be a "sub-activity" of the branch activity.

3.7          Merging

When a user wants to accept the changes (new versions) created by someone else, it is important not just to update the version-controlled resources in the user's workspace with those new versions, since this could result in "backing out" changes the user has made to those version-controlled resources.  Instead, the versions created in another workspace should be "merged" into the user's version-controlled resources.

The version history of a version-controlled resource provides the information needed to determine the result of the merge.  In particular, the merge should select whichever version is later in the line of descent from the root version.  In case the versions to be merged are on different lines of descent (neither version is a descendant of the other), neither version should be selected, but instead, a new version should be created that contains the logical merge of the content of those versions.  The doMerge request can be used to check out each version-controlled resource that requires such a merge, and set the MergeList property of each checked-out resource to identify the version to be merged.  The user is responsible for modifying the content of the checked-out resource so that it represents the logical merge of that version, and then adding that version to the PredecessorList of the checked-out resource.

If the server is capable of automatically performing the merge, it MAY update the content and PredecessorList of the checked-out resource itself.  Before checking in the automatically merged resource, the user is responsible for verifying that the automatic merge is correct.

The doMerge method performs the logical merge of a specified version (the "merge source") into the version-controlled resource (the "merge target").  If the merge source is neither an ancestor nor a descendant of the CheckedIn or CheckedOut version of the merge target, the doMerge checks out the merge target (if it is not already checked out) and adds the merge source to the MergeList of the merge target.  It is then the client's responsibility to update the content of the checked-out merge target so that it reflects the logical merge of the merge source into the current state of the merge target.  The client indicates that it has completed the update of the merge target, by deleting the merge source from the MergeList of the checked-out merge target, and adding it to the PredecessorList.  As an error check for a client forgetting to complete a merge, the server MUST fail an attempt to doCheckin a version-controlled resource with a non-empty MergeList.

When a server has the ability to automatically update the content of the merge target to reflect the logical merge of the merge source, it may do so unless noAutoMerge is specified in the doMerge request.  In order to notify the client that a merge source has been automatically merged, the doMerge request MUST add the auto-merged source to the AutoMergeList property of the merge target, and not to the MergeList property.  The client indicates that it has verified that the auto-merge is valid, by deleting the merge source from the AutoMergeList, and adding it to the PredecessorList.

When doMerge is applied to a workspace, multiple merge sources can be specified in a single doMerge request.  The set of merge sources for a doMerge request is determined from the sourceList of the doMerge request as follows:

- If a sourceList member identifies a baseline, that baseline is a merge source.

- If a sourceList member identifies a version-controlled resource, the CheckedIn version of that version-controlled resource is a merge source.

- If a sourceList member identifies a folder, the CheckedIn version of each version-controlled resource that is a member of that folder is a merge source.

- If a sourceList member identifies an activity, then for each version history containing a version selected by that activity, the latest version selected by that activity is a merge source.  Note that the versions selected by an activity are the versions in its ActivityVersionList unioned with the versions selected by the activities in its SubactivityList.

Any member of the workspace is a possible merge target.  The merge target of a particular merge source is the version-controlled resource whose CheckedIn or CheckedOut version is from the same version history as the merge source.  If a merge source has no merge target, that merge source is ignored.

If the merge source is a baseline, the merge target is a version-controlled configuration for the baseline history of that baseline, where the baseline-controlled folder of that version-controlled configuration is a member of the workspace.

The response to a doMerge request identifies the resources that a client must modify to complete the merge. It also identifies the resources modified by the request, so that a client can efficiently update any cached state it is maintaining.

3.8          Labels

A version "label" is a string that distinguishes one version in a version history from all other versions in that version history.  A label can automatically be assigned by a server, or it can be assigned by a client in order to provide a meaningful name for that version.  A given version label can be assigned to at most one version of a given version history, but client assigned labels can be reassigned to another version at any time.  Note that although a given label can be applied to at most one version from the same version history, the same label can be applied to versions from different version histories.

3.9          Unreserved Checkout

The unreserved property on a checked-out version-controlled resource indicates whether the ActivityList of another checked-out resource associated with the version history of this version-controlled resource can have an activity that is in the ActivityList property of this checked-out resource.

A result of the requirement that an activity must form a single line of descent through a given version history is that if multiple checked-out resources for a given version history are checked out unreserved into a single activity, only the first doCheckin will succeed.  Before another of these checked-out resources can be checked in, the user will first have to merge into that checked-out resource the latest version selected by that activity from that version history, and then modify the PredecessorList of that checked-out resource to identify that version.

 

3.10    Eclipsed Members of a Version-Controlled Folder

A doUpdate or doMerge request can give a version-controlled folder a version-controlled bound member that has the same name as an existing uncontrolled bound member.  In this case, the uncontrolled bound member takes precedence and is said to "eclipse" the new versioned-controlled bound member.  If the uncontrolled bound member is removed (e.g. by a doUnbind or doRebind), the version-controlled bound member is exposed.

3.11    Placing a Folder under Baseline Control

A folder can be placed under baseline control with a doBaselineControl request.  When a folder is placed under baseline control, the ControlledConfiguration property of the folder is set to identify a new version-controlled configuration.  This version-controlled configuration can be checked out and then checked in to create a new baseline for that folder.  A new baseline history is created containing a baseline that captures the state of the version-controlled members of the folder, and the CheckedIn version of the version-controlled configuration will be that baseline.

A baseline-controlled folder for an existing baseline history can be created with a doCreateBaselineControlledFolder request.  When the folder is created, the ControlledConfiguration property of the folder is set to identify a new version-controlled configuration whose CheckedIn version will be a specified baseline, and the folder is initialized to contain version-controlled members whose CheckedIn versions and relative names are determined by the specified baseline.

3.12    Locating Version Histories in a Workspace

Many properties identify a version from some version history.  It is often useful to be able to efficiently locate a version-controlled resource for that version history.  The doLocateByHistory method can be applied to a workspace to locate the workspace member that is a version-controlled resource for one of the specified version history resources.

4           Non-Versioning Provider

A non-versioning provider can stub out all interfaces except for the ones listed in this section.

4.1          Resource

String getDisplayName()

setDisplayName(String s)

String getComment()

setComment(String s);

java.util.Date getCreationDate()

setCreationDate(java.util.Date date);

String getCreatorDisplayName()

setCreatorDisplayName(String s)

java.util.Date getLastModified()

java.util.Locale getContentLanguage()

setContentLanguage(java.util.Locale contentLanguage);

long getContentLength()

String getContentType()

setContentType(String contentType);

String getContentCharacterSet()

setContentCharacterSet(String contentCharacterSet);

String getContentIdentifier()

String getAttribute(AttributeName name)

setContentCharacterSet(AttributeName name, String value);

Resource doReadProperties(PropertyNameList w)

void doWriteProperties()

Resource doReadContent(PropertyNameList w, OutputStream content)

void doWriteContent(InputStream content, String contentIdentifier)

void doUnbind()

void doCopy(Resource destination, boolean overwrite)

void doRebind(String destinationLocation, Boolean overwrite)

 

4.2          ControllableResource

Workspace getWorkspace()

Boolean getIsCheckedOut()

ControllableResource getServerState()

Boolean getIsStale()

Boolean getIsDirty()

void doCreateResource()

void doControl()

void doCheckout()

void doCheckin()

void doRefresh(Boolean IgnoreDirty)

 

4.3          Folder

<Resource>Iterator doReadMemberList

 (PropertyNameList wantedPropertyList, boolean deep)

 

4.4          Workspace

<ControlledResource>List getWorkspaceCheckoutList()

String getWorkspaceServerLocation()

setWorkspaceServerLocation(String location)

5           Acknowledgements

This API is the collaborative product of the author and the members of the JSR-147 expert team: Nick Crossley(Telelogic), John Dooley (Broadvision), Tim Ellison (IBM), Peter Raymond (Merant), and Eric Sedlar (Oracle).  We would like to acknowledge the foundation laid for us by the authors of the DeltaV protocol.

6           References

[RFC2518] Y.Goland, E.Whitehead, A.Faizi, S.R.Carter, D.Jensen, "HTTP Extensions for Distributed Authoring - WEBDAV", RFC 2518, February 1999.

[RFC2616] R.Fielding, J.Gettys, J.C.Mogul, H.Frystyk, L.Masinter, P.Leach, and T.Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.

[RFC3253] G.Clemm, J.Amsden, T.Ellison, C.Kaler, J.Whitehead, "Versioning Extensions to WebDAV", RFC 3253, March 2002.

7           Author's Address

Geoffrey Clemm

IBM

20 Maguire Road, Lexington, MA 02421

 

Email: geoffrey.clemm@us.ibm.com