\input texinfo   @c -*- texinfo -*-

@setfilename user-guide.info
@setcontentsaftertitlepage
@setshortcontentsaftertitlepage
@c @setchapternewpage odd
@footnotestyle end
@set TITLE OpenCM User's Guide
@set AUTHOR Jonathan S. Shapiro
@set MODYEAR 2002
@set OPENCMURL http://www.opencm.org
@set OPENCMD cm
@dircategory Programming
@direntry
* OpenCM: (opencm).    The OpenCM Configuration management System
...
@end direntry

@c Following file is included so that the autoconf/make system can be
@c used to set the proper version number without processing the entire
@c texinfo input -- who knows *what* conflicts would arise if we did
@c that.

@include version.texi

@settitle @value{TITLE}

@ifinfo
This file provides instructions on how to use the OpenCM configuration
management system.

Copyright @copyright{} @value{MODYEAR}, The EROS Group, LLC and Johns
Hopkins University.

Permission is granted to redistribute this document without royalty or
fee, provided that this copyright notice remains intact.

@end ifinfo
@c
@c  This title page illustrates only one of the
@c  two methods of forming a title page.

@macro cmdarg{a}
@i{\a\}
@end macro

@macro cmdref{a}
@b{\a\}
@end macro

@macro note{a}
@quotation
@i{NOTE: \a\}
@end quotation
@end macro

@macro issue{a}
@quotation
@ifhtml
@html
<font color="blue">
@end html
@end ifhtml
@b{Issue:} \a\
@ifhtml
@html
</font>
@end html
@end ifhtml
@end quotation
@end macro

@macro fix{a}
@ifhtml
@html
<font color="red">
@end html
@end ifhtml
@i{\a\}
@ifhtml
@html
</font>
@end html
@end ifhtml
@end macro

@titlepage
@title @value{TITLE}
@c @subtitle SUBTITLE-IF-ANY
@c @subtitle SECOND-SUBTITLE
@author @value{AUTHOR}

@c  The following two commands
@c  start the copyright page.
@page
@vskip 0pt plus 1filll
Copyright @copyright{} @value{MODYEAR}, The EROS Group, LLC and Johns
Hopkins University.

Permission is granted to redistribute this document without royalty or
fee, provided that this copyright notice remains intact.
@end titlepage

@html
<center>
<h1>@value{TITLE}</h1>
<p>
<em>@value{AUTHOR}</em>
</p>
</center>
@end html

@ifhtml
@html
<table>
<tr valign=top>
<td width="10%">&nbsp;</td>
<td>
@end html
Copyright (C) @value{MODYEAR}, The EROS Group, LLC and Johns Hopkins
University.

Permission is granted to redistribute this document without royalty or
fee, provided that this copyright notice remains intact.
@html
</td>
<td width="10%">&nbsp;</td>
</tr>
</table>
@end html
@end ifhtml

@ifhtml
@contents
@end ifhtml

@node Top
@top OpenCM: An Introduction
This document describes how to use the OpenCM configuration management
system. It is intended for both new and expert users. The first portion
of the document provides a tutorial introduction to OpenCM. Later sections
deal with specific ``expert'' issues.

This document applies to versions @value{VERSION} and later of the
OpenCM configuration management system, which is most commonly
installed as a program named @code{@value{OPENCMD}}.

OpenCM has been tested only on Linux systems, though we have every
expectation that it will work on UNIX systems in general. A port to the
cygwin environment would be helpful, and we would be happy to
re-integrate the necessary changes.

@note{This manual makes reference in many places to disconnected
development and replication functionality (the two are intimately
related). These features are @i{not} included in release
0.1. Replication is very sensitive to schema changes, and we found that
keeping the code up to date was significantly delaying our release
date. Rather than continue to delay the release, we removed the
replication feature temporarily.
Replication should re-appear in release 0.2 or 0.3, as it is very high
on our priority list. Rather than remove references to the replication
logic from the manual, we have left them present so you can see what is
coming.}

@menu
* Basic Concepts::       Basic concepts of configuration management.
* Setting Up OpenCM::    Preparing to use OpenCM.
* Client/Server OpenCM:: Running and using an OpenCM server.
* Basic Usage::          Basic usage of OpenCM.
* Collaborating::        Using OpenCM in multiperson teams.
* CVS Quickstart::       Getting started if you know CVS.
* Getting Started::      Working with your first project.
* Command Reference::    Using OpenCM for group development.
* Upgrading::            Handling repository upgrades.
* Futures::              Things that need to be done.
* Holding Buffer::       Text I don't know what to do with.
@end menu

@chapter Why Another CM System?

In the open source world, the current ``gold standard'' for
configuration management is @uref{http://www.cvshome.org,CVS}. CVS has
been successful because it is an effective 80% solution. It is an
excellent example of open source at its best and worst: on the plus
side, the community needed a tool and they went out and built one. On
the minus side, when it hit ``good enough,'' development on it
essentially reverted to maintenance mode. OpenCM will probably be subject
to the same effect, but we hope we have set a higher initial bar.

While a lot of people use CVS, everybody who uses it has a pet list of
things they wish CVS did better.  In the
@uref{http://www.eros-os.org,EROS project}, our list of key missing
features in CVS was:

@itemize @bullet
@item
Real configurations. CVS fakes it pretty well, but there are problems
when (e.g.) files get renamed.

@item 
Access controls at the branch, and file levels. We wanted to let
students and collaborators integrate code without encouraging damage to
the entire code base.

@item
Repository accounts. We needed a system where we did not have to give
out accounts on the repository host system in order to let people use
the repository. Not everything we do is public. Some of it is security
sensitive, and giving out accounts widely is an invitation to being
hacked. The CVS password mechanism is laughably bad, and CVS doesn't
implement adequate access checks for our use.

@item
Disconnected development. We work on airplanes a lot, and we work with
collaborators all over the world who prefer to periodic merges rather
than work on the main trunk of the development tree. Both are examples
of disconnected development.

Effective disconnected development needs to preserve history as well as
patches. Patch integration just isn't effective or scalable, as the
Linux project has demonstrated.
@fix{what is an appropriate link for Linux?}
@end itemize

There are several existing alternatives to CVS, each with strengths and
weaknesses:
@table @asis
@item Perforce
The @uref{http://www.perforce.com,Perforce} system is a commercial
product, but is licensed at no charge for use on open source
projects. To all appearances, Perforce is a good product, but we have
commercial collaborators and a need to manage open but unreleased
code. The Perforce license does not support this. Also, Perforce does
not provide disconnected development, which is a critical concern for
us.

@item Bitkeeper
Another frequently mentioned candidate is
@uref{http://www.bitkeeper.com,bitkeeper}, which has had success in a
few of the Linux kernel projects. At the time we started the OpenCM work,
BitKeeper didn't exist.  Bitkeeper shares several features with OpenCM,
but its license is, for us, problematic. The BitKeeper authentication
model did not satisfy our need to avoid adding accounts on the server,
and BitKeeper provides no end to end integrity controls. It's repository
architecture is not conceived as a software distribution mechanism, and
no architectural attention has been given to the possibility of damage
to a managed code base by a hostile mirror.

@item PRCS
Josh MacDonald's
@uref{http://www.xcf.berkeley.edu/~jmacd/prcs.html,PRCS} is a system
that heavily influenced the OpenCM design, and we anticipate integrating
some of his @uref{http://www.xcf.berkeley.edu/~jmacd/xdelta.html,XDELTA}
and XDFS work in the future. Josh's work does not address our concerns
about end to end provenance control, integrity, or disconnected
development, though it could easily evolve in these directions.

@item VESTA
@i{VESTA was announced as we were writing this. We need a good
comparative description here.}
@end table
None of these quite met our needs, and we reluctantly decided that we
needed to build something different.



@section Features at a Glance
@cindex Features at a Glance

OpenCM is designed as a mostly drop-in replacement for CVS. Like CVS, OpenCM
uses a "checkout, modify, merge" development process. Unlike CVS, it
provides integrity checks, replication, access controls, and provenance
tracking.

OpenCM uses SSL-based cryptographic authentication for user
management. The OpenCM administrator can add new users to the OpenCM
repository subsystem without giving them access to the rest of the
machine.

OpenCM is a true configuration management system. Every change to a
branch is committed as a single, traceable unit. It is therefore
possible to recover with confidence any version of a software system.

OpenCM tracks both commentary and change history across
replicates. Patches are not used as a change transmission device. The
entire trail of evolution is preserved by every merge.

While the command-line OpenCM client (the one described in this manual) is
designed for workspaces that live in file systems, nothing in the OpenCM
protocol or repository relies on this assumption. With a suitable
client, OpenCM could equally well be used for a repository-based IDE.

OpenCM lets you develop while disconnected. You can check out a project,
get on an airplane, modify the code, and commit to your laptop. Later,
you can merge the result back into the main repository without losing
any of the history or comments from your work.  

OpenCM can be used as a source or binary @emph{deployment} vehicle. It is
very straightforward to set up replicating repositories, and a user can
determine whether the copies obtained from the replicates are authentic.

OpenCM handles binary files as well as text.

@note{Binary merge management is not currently addressed. Future
versions of OpenCM will have content-sensitive merge facilities to better
support this.}

OpenCM uses your connection efficiently. Because OpenCM uses cryptographic
hashes for object names, it is readily able to determine what objects
you already have. Similarly, there is no need for OpenCM to connect to the
server to determine what has changed in your workspace.


@node Basic Concepts
@chapter Basic Concepts
@cindex Concepts

OpenCM is a configuration management system: a system for managing
source code, documents, or other complex, changing content. It is
appropriate when you have multiple documents or files, and you need to
keep versions of these files synchronized with each other as part of
some larger work.

For example, you might have a book with 10 chapters, each stored in a
separate file. You might revise two of these chapters to make a new
revision of the book. The new revision contains 8 chapters that are
the same as the previous book, and two chapters that have been
replaced. Organizing these relationships is the job of a
@dfn{configuration management system}.

@section Versioning Concepts

To manage versions of your work, OpenCM applies two levels of
organization on your work. As you work, OpenCM maintains a ``branch.''
A @dfn{branch} is a sequence of ``configurations of a work in
progress''. A @dfn{configuration} is a consistent set of files or
objects. OpenCM records each file or object as a separate @dfn{entity}.

As you make changes to your work, you periodically will reach a point
where you want to save your work. In OpenCM, this is done using the
@command{commit} command. The commit command examines your workspace,
identifies all of the files that have been changed, added, or deleted,
and builds a new configuration of your work. Committing your changes
has two consequences:
@enumerate 1
@item
Your entire current working state is saved as a consistent whole.
@item 
Subject to access checks, other users can obtain a copy (check out) of the
new version that you have just committed.
@end enumerate

OpenCM tracks versions of @emph{systems}, not files. Each configuration
is a complete version of your work. Even if you change just one line
of one file, a new configuration is created when you commit. For this
reason, OpenCM does not track versions of files. It tracks versions of
branches. A branch is simply a sequence of committed configurations.

@fix{A figure is needed here.}

@section Users and Access Control

Every OpenCM user has one (or more) unique cryptographic key(s) that
identify that user. Whenever you use OpenCM, your session begins with
key authenticatation. Your key is used to determine whether you can read
or write on this repository (at all) and whether you have read or write
access to specific objects in the repository. In OpenCM, the
access-controlled objects are branches, users, groups, and
directories. Whenever you change one of these objects, a new
``revision'' is created in the repository recording the time of the
change, the identity of the previous revision, and the authenticated
user.

@fix{A figure for revisions is needed here.}

OpenCM users can have multiple keys used for different purposes. For
example, it is usually appropriate for the OpenCM administrator to have
one key for administrative purposes and another for day to day
activities.

@section Name Spaces

Every OpenCM user has a unique name space, or @dfn{home directory}, 
that is created when the user is added to the repository.  
The @dfn{home directory} stores key-value pairs that map 
human readable names (keys) to the cryptographically generated
names (values) of OpenCM objects of interest.  Since the names of the OpenCM
archived objects are not easily remembered (given the cryptographic nature
of the names), the directory entries provide an essential means for defining
easily remembered or easily understood names for referencing OpenCM
objects.  

Most needed entries in the @dfn{home directory} are inserted automatically 
by the system, for such actions as creating new branches, adding users, and 
creating groups.  These entries allow the user to manipulate the associated 
OpenCM objects via a human-readable name, since most OpenCM client commands
accept either an absolute OpenCM object reference or a key from a user's
@dfn{home directory}.  The entries in OpenCM directories 
are user-specific and each user maintains total control over the entries in 
his own directory.  So, even though the system will automatically enter 
key-value pairs on behalf of a user, the user can always delete or modify 
those entries.  OpenCM provides a complete set of client commands for listing
and modifying the contents of the @dfn{home directory}.

@section More on Names
All objects in an OpenCM archive are ultimately referenced via a Uniform
Resource Identifier (URI).  Although the URI format is commonly understood,
OpenCM uses cryptographically generated names, which tend to make the URIs
of objects unreadable.  (This was the motivation for providing a home
directory for each user as previously explained.)  To generate a URI, OpenCM
uses a combination of the universally unique repository ID (as the ``network
location'' part of the URI) and a universally unique random name (as the 
``path'' part of the URI).  Although unreadable, this aspect of OpenCM is
absolutely essential for supporting distributed modification and replication
of any archived object because any OpenCM archived object is guaranteed to 
have a unique URI associated with it.

@section Workspaces and Development Model
An OpenCM user interacts with a repository via a local Workspace.  The
user's Workspace is simply a local organization of one version
(usually the latest) of a given branch.  The Workspace is organized in a file
system directory on the user's local machine.  Any modifications to
the objects are done locally.  When ready, the user commits or
uploads the entire set of modifications to the repository.

A typical development scenario is that a user checks out a branch of a
repository to which he has access.  He then makes modifications to the local
copies of the repository objects, and when ready, commits those modifications
back to the repository.  For concurrent development, OpenCM
supports merging different branches (assuming they have a common ancestor) and
updating a user's Workspace to incorporate changes committed by other users. 
In addition, a user may create empty branches, as well as fork current
branches in order to support new/parallel lines of development.

All development on a branch is done in the context of a Workspace.  In other
words, all direct modifications of objects and any indirect modifications as
a result of merging or updating a branch happen only to the local copies of
objects in a user's Workspace.  No permanent changes to archived objects 
happen until a Workspace is committed to the repository.

@section Users and Access Control

This section needs to be filled in. It needs to describe:

@itemize @bullet
@item
Versions
@item
Configurations
@item
Workspaces
@item
Namespaces
@end itemize

@node Setting Up OpenCM
@chapter Setting Up OpenCM
@cindex Setting Up OpenCM

So far, OpenCM has been tested only on Linux systems. For now, you can
obtain the latest copy of OpenCM from @uref{http://www.opencm.org, the
OpenCM web site}. OpenCM is delivered as a gzipped tar file. For Linux,
it is also available as a RPM file.

@section Installing OpenCM

While it is possible to rebuild OpenCM from scratch, we recommend that
if you install OpenCM using the RPM mechanism. RPM keeps track of what
files need to be deinstalled if you decide to remove OpenCM. 

@note{There are other package management systems that do this as
well. We do not currently support this simply because we do not know how
to build packages for them. If you have a favorite package utility that
you would like us to support, please file a bug report in the
@uref{http://www.opencm.org/~bugzilla,bug database}. Take a moment to
see if such a request already exists, and add your vote to it if
appropriate.}

@subsection Installing Using RPM
To install OpenCM with RPM:

@example
# rpm -ivh opencm-@value{VERSION}-1.rpm
@end example

Installing the OpenCM RPM installs the necessary commands, this manual,
and the help files under @file{/usr/bin} and @file{/usr/share}. The next
step is to set up a repository.

You can perform a minimal test of the resulting installation by checking
the version of the OpenCM system:
@example
# src/@value{OPENCMD} version
Client: opencm version @value{VERSION}
@end example

@subsection Rebuilding OpenCM From Scratch

Before downloading OpenCM, we recommend that you begin by creating an
empty directory. Download the OpenCM tar file to that directory and
follow the directions below.

First, unpack the tar file by using the following command:
@example
# gunzip opencm-@value{VERSION}-1.tar.gz
# tar -xvf opencm-@value{VERSION}-1.tar
@end example
If your @command{tar} command supports the @option{-z} option, it may be
possible to skip the @command{gunzip} step by using the @option{-z}
option to @command{tar}.  Note that some web servers will decompress the
file before transmitting it, but will still give you a file name ending
in @file{.gz}. If @command{gzip} indicates that the file is not a
compressed file, try using tar on the @file{.gz} file directly. What the
heck, it might work.

You will now have a subdirectory called @file{opencm/}. Change into this
directory using @command{cd}. Configure and compile OpenCM using autoconf
and configure:
@example
# cd opencm
# autoconf
# ./configure
# make
@end example
@noindent
With a bit of luck, this will get OpenCM built for your system. You will
need to have the @command{OpenSSL} system installed to perform this
compile.

By default, OpenCM will configure to install under @file{/usr/local}. If
you prefer to install the OpenCM software in the ``official'' locations,
you should use replace the configure line above with
@example
# ./configure --prefix=/usr
@end example

Before you actually do the installation (which must be done as root), it
is probably a good idea to check if OpenCM is vaguely working. To do
this, you might try the OpenCM binary by typing:
@example
# src/@value{OPENCMD} version
Client: opencm version @value{VERSION}
@end example

If OpenCM has built successfully, you can install it (as root) using
@example
# make install
@end example

OpenCM requires no special privileges. It can be run by any user for
personal use. For use as a public repository, it should be run as a
separate user account. Let's test it before we set that up.

@section Creating the Administrative User

Before you create the repository, you must first create the
cryptographic keys that will be used by the administrator of the
repository. OpenCM uses cryptographic methods (SSL/TLS) for user
authentication. It does not rely on or use the host operating system for
authentication at all. This is necessary for several reasons:
@enumerate
@item  
If OpenCM relied on the host authentication mechanism, it would not be
able to distribute successfully across different types of hosts.
@item
It is frequently desirable to authorize a user to use the OpenCM
repository on your machine. Because OpenCM uses cryptographic
authentication, it is @i{not} necessary to give this user an account on
the host. This ensures that their access is restricted to OpenCM.
@item
Cryptographic authentication does not rely on a single
administrator. Since OpenCM is designed as a globally replicatable
system, dependency on a local administration policy would be
inappropriate.
@end enumerate
@noindent
Even if your users @i{do} have a local account on the repository
machine, they will require an OpenCM crytographic account.

The administrative user has the authority to add new users to the
repository, and to revoke access to the repository. Because of this, it
is a @i{very} bad idea to use the administrative user's cryptographic
key as your daily working identity. We will show how to add other users
momentarily.

To create the administrative user key:

@example
@value{OPENCMD} create user admin
@end example
@noindent
You will be prompted for various information to create the X.509 keys.

When you create a user key, you @i{must} provide a valid email address.
OpenCM has no way to check that you provided a valid email address, but
the tool relies on the email address from the X.509 certificate to
identify a user in a human-friendly manner and (soon) to notify
subscribed users of changes to repository objects.  For the
Administrative user @option{admin}, we suggest using
@kbd{opencm-admin@@yourhost.com}, and setting up an appropriate email
alias in your system's aliases file. Later, when the time comes to
authorize users to access the repository, you should take care to check
the email address they have provided.

OpenCM will also show the common name field and other information for
user display purposes if provided, so it's a good idea to enter
pertinent data for that entry as well.  For the @option{admin} user, we
suggest you use something like @kbd{OpenCM Administrator for MumbleCo}
or @kbd{OpenCM Administrator for MyProject}.  That way, you will be able
to figure out later what project or activity this key goes with.  Take
the time to figure out what information the administrative key should
provide. Hopfully, You are going to live with this key for a long time.

@note{Typing passwords can be a real pain in the neck, but you should
@i{always} use a password for your OpenCM keys. The next version of the
OpenCM client will include a built-in key management agent similar to
@command{ssh-agent} to eliminate the need for this, so there is no good
excuse for avoiding a password.}

After the ``create user'' command has run, you will find that you have a
new directory called @file{.opencm} under your home directory. The
@file{.opencm} directory should now contain:
@example
users/
  admin.pem
  admin.key
@end example

@section Creating a Repository

The next step in the setup process is to create a repository.  If you
are creating a repository that will run as a server, this is the
tricky part.

OpenCM currently supports two file-based mechanisms for storing the
repository:

@table @asis
@item fs
The @b{fs} storage type is a mechanism based on flat files. It is used
primarily for testing OpenCM, and it @i{not} recommended for use as a
working repository. In a @b{fs} repository, every version of every
managed object is stored in a separate file.

@item gzfs
The @b{gzfs} storage mechanism is exactly like the @b{fs} mechanism, execpt
that gzip compression is used. For now, newly created repositories should use
the @b{gzfs} mechanism.

@end table
@noindent

In the future, other delta-encoding storage mechanisms will probably
be supported (most likely, the long awaited @b{sxd2}, which will fix
most of the issues with the old @b{sxd} repository). In addition,
support for database storage mechanisms have also been considered, but
are not supported at this time.

Once you have an admin user key, you can create the actual repository.
You will need to specify the path to the @file{admin.pem} file, which
is the file created when you created the admin user previously. There
is no need for this file to have any particular name. Whatever PEM
file you supply will be accepted as the administrative user's identity
for this repository. If you already have an administrator key set up
from creating some previous repository, it can be reused. It @i{is}
possible to change the administrator key later.

@subsection Creating a Personal Repository
OpenCM is designed to store all of its content in a single, server-wide
repository. If you are creating a repository for @i{personal} use,
this repository can be created using the @b{create repository} command:
@example
$ @value{OPENCMD} create repository /path/to/directory gzfs admin.pem
@end example
@noindent
When this command succeeds, the directory @file{/path/to/directory}
will exist, and a new OpenCM repository will
have been created.  

After you create the repository, you can see if you got this right by
typing:
@example
$ @value{OPENCMD} --repository file:/path/to/directory version
@end example

@subsection Creating a Public Repository
When OpenCM is installed, it creates a new, non-privileged user called
``opencm.'' To reduce any risk from server compromise, the OpenCM daemon
(the public server process) runs as this user. Unfortunately, this makes
creating the public repository slightly more complicated. You will only
need to do these steps once.

The first step is to become root on the server machine. Since the OpenCM
repository will probably live inside a directory that the OpenCM user
cannot write, you'll need to create the top-level repository directory
by hand. We will use @file{/home/OPENCM} as our example repository
directory. Make this directory writable to the opencm user, and you can
then run the @command{create repository} command using the su command:

@example
$ su
password: @i{type root password here}
# mkdir /home/OPENCM
# chown opencm.opencm /home/OPENCM
# su opencm -c "@value{OPENCMD} create repository \\
                /home/OPENCM gzfs /path/to/admin.pem"
@end example
@noindent
Note that we had to break up the last line for publication. The last
command should be typed on a single line.

Before you can use the public repository, you also need to edit the file
@file{/etc/opencm.conf}. Find the line with the @env{OPENCM_REPOSITORY}
variable. This variable is commented out in the distributed
configuration file. Change this line to read:
@example
OPENCM_REPOSITORY=file:/home/OPENCM
@end example
@noindent
The opencm server will not start automatically unless this variable is
set in /etc/opencm.conf

@subsection What Happened
When you create the new repository, OpenCM automatically creates several
objects in the repository:
@itemize @bullet
@item
An @dfn{administrator group}, which is the group of users who are
considered the administrators of this repository. The administrator
group has the authority to modify user objects, which gives it the right
to revoke, modify, or otherwise change the state of any user.

Any user can be added to the administrative group, but it is inadvisable
to give a day to day working cryptographic key administrative authority.

@i{Check the following statement -- this is how it should be, but it's
not clear to me that it is right.}

The administrator group is initially self-writable.
@item
An @dfn{everyone} group, which is a group containing all users known to
the server. Normally, all user objects are readable to the everyone
group. This allows anyone to show the informational fields of a user's
X.509 certificate. Unless the user chooses to be more public, each
user's @i{directory} is accessable only to that user.

The everyone group is writable by the administrator group and readable
by the everyone group. This means, pardon the awkwardness, that everyone
can see everyone.
@item
A ``home'' directory for the administrative user. The initial entries in
the administrator's directory are:
@example
everyone    # the group of all users
self        # the user object for the administrative user
users       # a directory containing entries for each user
            # this is now redundant and may soon go away.
@end example
@end itemize


@subsection Locating the Repository
Specifying the @option{--repository} option for every command quickly
becomes awkward.  When trying to find your repository, OpenCM checks the
following places in order:
@enumerate
@item
The @option{--repository} command line option, which expects a URI:
@example
$ @value{OPENCMD} -u admin --repository file:/path/to/directory version
@end example
@item
Your workspace (discussed below), which identifies the repository you
used when you checked out your working copy.
@item
The @env{OPENCM_REPOSITORY} environment variable:
@example
# export OPENCM_REPOSITORY='file:/path/to/directory'
@end example
@end enumerate
@noindent
Now that you have a repository created, it is a good idea to set the
@env{OPENCM_REPOSITORY} environment variable to tell OpenCM where it is.
From this point forward, we will assume that you have set the
@env{OPENCM_REPOSITORY} variable -- otherwise the example commands get
too long.

@note{A future version of OpenCM will use a systemwide configuration
file to locate the repository for the @b{opencm server} command,
allowing the server to more easily be started from the system startup
scripts.}

@subsection Verifying The Repository

Now that you have created the repository, it is possible to use the new
administrative key to test the newly created repository:
@example
$ @value{OPENCMD} -u admin version
Client: opencm version @value{VERSION}
Repository: opencm version @value{VERSION}
@end example
@noindent
If the @command{version} command is able to make a connection to the
repository, it reports the version of the server as well as the
client. If the command reports a repository version, you can have
reasonable confidence that the repository has been created correctly.

@section Creating Users

The repository is now ready to use, but using it with the administrator
account is generally not a bright idea. A better approach is to create a
user identities for each user who will use the repository. This proceeds
in two steps:

@enumerate
@item
Each user creates a new public/private key pair for themselves, and
provides the @i{public} key to the repository administrator.
@item
The repository administrator adds an account for the user.
@end enumerate

@subsection Creating the Key Pair
To create a new public/private key pair, you can proceed exactly as you
did when creating the administrator key above. At this point, you are
creating a key for your own use. This tutorial assumes that your name is
``Jack.''@footnote{If your name isn't Jack, and you don't know your
name, contact your @i{local} administrator for support.} To create the
key for Jack, type:
@example
@value{OPENCMD} create user jack
@end example
@noindent
Once again, be sure to use a valid email address.  

The create user command creates two files. The @file{jack.key} file is
the private key for the new user. The @file{jack.pem} file is the public
key and certificate for the new user. The private key should be secured
by using an appropriate pass phrase. The private key file is @i{never}
an argument to any OpenCM command.  The server administrator has no need
to see your private key. Indeed, this is why creating the user key and
adding a new user to a repository is done in separate steps.

@subsection Creating the User Account
Once a user key pair has been created, an account for this user needs to
be created on the repository. This step must be done by a member of the
repository administrative group. The user should send the PEM file to
the administrator to have the account created. If you send the PEM file
via email, it is probably a good idea to send it as an attachment rather
than as part of the message body -- some mail agents mangle long lines
of text, and it may be difficult for the administrator to correctly
reconstruct your certificate if this happens.

When the administrator receives the certificate, they can create
authorize this user by typing:
@example
@value{OPENCMD} -u admin adduser jack.pem rw
@end example

The argument @kbd{jack.pem} is the path to the certificate file for the
new user (NOT the private key file).  The final argument to this command
indicates the overall repository access for the new user.  Choices are
@kbd{r} (read only access), @kbd{rw} (read and write access), and
@kbd{w} (write only access). A user who has read-only access can obtain
material from the repository but cannot modify anything. Write-only
access is a bug that should be removed.

Jack is now ready to start using OpenCM for real work.

@subsection What Jack Sees

If you are Jack, and you have followed the setup procedure up to this
point (that is, you are also the administrator), your @file{.opencm}
directory should now contain:
@example
users/
  admin.pem
  admin.key
  jack.pem
  jack.key
@end example

When the new user Jack is created in the repository, a directory will be
created for them as well. Any user can list the content of their main
directory with the @command{ls} command:
@example
$ @value{OPENCMD} -u jack ls
[User] self         # Jack's user object
[Group] everyone    # the group of all users
@end example
@noindent

@subsection Deciding Which User to Use
Specifying the @option{-u} option for every command quickly becomes
awkward. OpenCM determines the name of the certificate file to use in
the following order:
@enumerate
@item
If the command line @option{-u} @i{name} has been supplied, OpenCM
will use this name.
@item
Otherwise, OpenCM uses the name specified by the @env{OPENCM_USER}
environment variable.
@item
Otherwise, OpenCM assumes that the user name is @kbd{default}.
@end enumerate
@noindent
Once a name is chosen, OpenCM uses the certificate and key found in
@file{~/.opencm/users/@i{name}.pem} and
@file{~/.opencm/users/@i{name}.key}.@footnote{The OpenCM
@option{--configdir} option can be used to override the location of the
@file{.opencm} directory.}
If you have a particular key that you wish to use by default, the
easiest thing to do is to copy or create a symbolic link to the PEM
file:
@example
# cd ~/.opencm/users
# cp jack.pem default.pem
# cp jack.key default.key
@end example
@noindent
Future versions of OpenCM will provide an automated means to specify a
preferred key on a server by server basis.

For the balance of this manual, we will assume that you have either
created a @file{default.pem} and @file{default.key} file or that you
have set the @env{OPENCM_USER} variable to your preferred user name.

@subsection Pass Phrases

You may come to feel (as we do) that typing a pass phrase for every
OpenCM command is impossibly cumbersome. Future versions of OpenCM will
make it possible to avoid retyping a password for this key.  @i{As a
temporary measure}, if you feel that your machine's login mechanism
provides adequate security for your short-term needs, you can remove the
password as follows:
@example
# cd ~/.opencm/users
# openssl rsa -in jack.key -out tmp.key
# mv tmp.key jack.key
@end example
@noindent
We cannot really encourage this practice, but we do understand why it is
tempting. We are working to integrate a password manager into OpenCM as
quickly as we can.

@node Client/Server OpenCM
@chapter Client/Server OpenCM
@cindex Client/Server OpenCM
OpenCM is designed as a client/server application. In most
installations, a server process (daemon) will manage the
repository. This chapter describes how to configure client and server,
and how to start the built-in OpenCM CGI support.

@section Setting up a Network Repository Daemon

Once you have created an OpenCM repository, you can start up OpenCM as a
server process by executing the @command{@value{OPENCMD} server} command:
@example
@value{OPENCMD} server file:/local/path/to/repository
@end example
@noindent
To avoid accidentally exposing the wrong repository, the
@command{@value{OPENCMD} server} command does not honor the
@env{OPENCM_REPOSITORY} environment variable or the settings of your
local workspace (if any). It requires that the local repository URI be
explicitly provided on the command line.

Once started, the server listens for client connection requests,
authenticates clients, and then processes OpenCM client commands sent
over the OpenCM wire protocol.  The daemon will remain running until
explicitly terminated (e.g. via SIGHUP).  A server process is not
required for OpenCM operation, but without it, remote access to the
repository is unavailable.

@section Using a Network Repository (Client)
To tell the client that it should access a network repository, simply
specify an OpenCM URI as the value of the @env{OPENCM_REPOSITORY}
environment variable:
@example
# export OPENCM_REPOSITORY='opencm://@i{host-name}'
@end example
@noindent
Any valid host name or IP address can be used as the repository host
name. Assuming that you are an authorized user on the server, all
requests will now be processed using the remote repository.

By now you may have noticed that OpenCM objects are named by URIs of the
form:
@example
$ opencm://host-crypto-name/object-crypto-name
@end example
Eventually, it will be possible using only the cryptographic host name
to connect directly to a publicly registered repository.

@section OpenCM CGI Support
OpenCM provides built-in support for execution as a CGI program....

@i{Describe how to set up the CGI service here.}

@node Basic Usage
@chapter Basic Usage
@cindex Basic Usage

To get a sense of how to use OpenCM, let's go through the process of
creating a new project and making a few changes. Along the way, we
will introduce the key ideas on which OpenCM is built.

@section Starting a new Project
This section describes how to create a new project, and introduces the
notion of a ``repository name.''

@subsection Creating a New Project

If you are starting a new project from scratch, you can create a new
line of development by typing:
@example
$ @value{OPENCMD} create project sample
@end example
@noindent
This creates a new, empty line of development and binds it to the name
@file{sample} in your OpenCM directory.

You will be prompted for various information about the new project,
including a name and a description of the project. The name is used by
various OpenCM commands to describe what you are working on. It is a
good idea to keep it descriptive but short, much as you would a
conventional file name.

@subsection Importing an Existing Code Base

If you already have a directory of files, you can create a new project
incorporating them in one step. First, place all of the files in your
project under a common (UNIX) directory somewhere. There should be
nothing in this directory other than your project files. Make this
directory your current directory Then type:

@example
$ @value{OPENCMD} import sample
# @i{other commands might add or drop files here}
$ @value{OPENCMD} commit
@end example

In effect, the @command{import} command creates a new project, checks it
out, and automatically adds all of the files in the current directory
and below. At this point, you can type other commands to add or remove
files it you like. The @command{commit} command then uploads all of this
state to the repository.

@c  At this point, we should digress briefly to introduce the first of the
@c  three OpenCM namespaces: repository names.
@c
@c  These are the two kinds of names that you will work with most
@c  frequently. The third relates to collaboration, and will be
@c  discussed in the next chapter.

@section Repository Names

At this point, we should digress briefly to introduce the first of the
three OpenCM namespaces: repository names.

Repository names are names that appear in a user's repository
directory. Each OpenCM repository maintains a directory space for every
user. The main function of this space is to provide a place to keep
track of work that you have in progress. In our repository creation
example:
@example
$ @value{OPENCMD} create project sample
@end example
@noindent
the name @file{sample} is a repository name. As with conventional
files, objects in the repository can be renamed or deleted. The
@command{mv} and @command{rm} commands are reserved for manipulating
managed content, so for repository names we use @command{rebind} and
@command{unbind}. To rename an object in the repository, use the
@command{rebind} command:
@example
$ @value{OPENCMD} rebind sample new-name
@end example
@noindent
The project should now be called @file{new-name}. You can see this by
using the @command{@value{OPENCMD} ls} command:
@example
everyone    # the group of all users
new-name    # @i{the project you just renamed}
self        # the user object for the administrative user
users       # a directory containing entries for each user
            # this is now redundant and may soon go away.
@end example

Repository objects can be organized into subdirectories. To illustrate
this, let's create a directory to hold the lines of development
associated with this new project, and relabel our new line of
development as the main line of development for the project.
@example
$ @value{OPENCMD} mkdir my-project
$ @value{OPENCMD} rebind new-name my-project/main
@end example

Finally, you can remove an object. We won't do it here, because we will
need this new project for the rest of the chapter, but assuming that
your object's repository name is @file{ties}, you could remove it by:
@example
$ @value{OPENCMD} unbind ties
@end example
@noindent
The object will not actually go away until all names binding it are
removed. Once all bindings are gone the object will be removed the next
time the repository store is garbage collected.

@section Using the Workspace

To start working on your new project, create an empty (UNIX) directory
somewhere, make it your current directory and type:
@example
$ @value{OPENCMD} checkout sample
@end example
@noindent
This will check out a copy of the previously create @file{sample}
project.  If you do not specify a particular version, OpenCM will check
out the most recent version of the line of development.

Since the sample project has no files yet, you will not initially see
anything new appear in your current directory. Running the UNIX @command{ls
-a} command, however, will reveal that a new OpenCM workspace has been
created. You will find that there is now a @file{.opencm} directory
here. Within this directory you will find a file named @file{Workspace}
that records information about your workspace and the pending operations
that need to be committed.

@subsection Adding Files

To add a file to the sample project, you first need to create the
file using a text editor. Assuming you called the file @file{hello.c},
you can then type:
@example
$ @value{OPENCMD} add file hello.c
A ./hello.c
@end example
@noindent The output from this command shows that @file{hello.c} was added
to the project.  Another way to display this information is with the
@command{@value{OPENCMD} status} command.
@example
$ @value{OPENCMD} status
[ A       ]      65 ./hello.c
@end example

In addition to displaying the flag 'A' to show that this file was added
to the project, this command displays the length of the file.

Something to notice here is that you did not need to specify a
repository. When you are operating within a workspace, OpenCM learns the
identity of the repository by consulting the @file{Workspace} file. The
correct Workspace is identified by proceeding up the file tree until one
containing a @file{.opencm} directory is found. Therefore, when you are
working within a workspace it is not necessary to specify a particular
repository.

OpenCM assumes that the workspace's repository should take precedence
over the one specified in your @env{OPENCM_REPOSITORY} environment
variable. If you need to override the workspace repository for some
reason, use the @option{--repository} option.

@subsection Checking Status, Committing Changes

When you are satisfied with your current round of changes, the
@command{@value{OPENCMD} commit} command can be used to check them in to the
repository. Once the changes are in the repository, you can recover this
particular state of your workspace at a later time.

Before we go ahead and commit these changes, let's take a look at the
current state of the project:
@example
$ @value{OPENCMD} ls sample
[Version] 0
@end example
@noindent
Once again, note that we didn't need to type a repository name because
we are operating from within a workspace. If we specifically list
version 0 of this line of development, we will see that there are no
files in it:
@example
$ @value{OPENCMD} ls sample/0
# @i{OpenCM prints no response -- this could be clearer, but it is correct.}
@end example

Now, let's go ahead and commit our new @file{hello.c} file into the
repository. The @command{@value{OPENCMD} commit} command will prompt you for a
message indicating what this commit is about:
@example
$ @value{OPENCMD} commit
[ A       ]      65 ./hello.c
opencm: Uploading CommitInfo Record... 
opencm: Uploading "./hello.c"
@end example
@noindent
After the commit, the @command{@value{OPENCMD} status} shows nothing, because by
default it does not display information about unmodified state in the
workspace:
@example
$ @value{OPENCMD} status
# @i{OpenCM prints no response}
@end example
@noindent
To see a more detailed status view, try the @option{-v} option:
@example
$ @value{OPENCMD} status -v
[same     ]      65 ./hello.c
@end example

Once again listing the project, we see that it now has two revisions:
@example
$ @value{OPENCMD} ls sample
[Version] 0
[Version] 1
$ @value{OPENCMD} ls sample/1
[Entity] hello.c
# @i{shap: the various outputs need cleanup for consistency.}
@end example

@subsection Modifying and Renaming Files

Let's copy the file so we can illustrate rename, modify, and delete:
@example
# @i{First, the UNIX command to copy the file:}
$ cp hello.c hello2.c
# @i{Next, add and commit this new file:}
$ @value{OPENCMD} add file hello2.c
N ./hello2.c
$ @value{OPENCMD} commit -m 'New file for demo purposes'
[ A       ]      65 ./hello2.c
opencm: Uploading CommitInfo Record... 
opencm: Uploading "./hello2.c"
@end example
@noindent
The @option{-m} option can be used to avoid bringing up an editor for
short messages by providing them directly on the command line.

While the output badly needs to be cleaned up, you can see this commit
message using the @command{@value{OPENCMD} show object} command:
@example
$ @value{OPENCMD} show object sample/2
URI:          opencm://rIrdJD4vIwPKANxDrEAxLYaQ3ZWQSA/9v8eiEdriVAD4CG76VNhQrUfYXrKjC
Sequence No:  4
nRevisions:   3
Read Group:   opencm://rIrdJD4vIwPKANxDrEAxLYaQ3ZWQSA/xgSjAvXiK3YzGEpvhD-kw4gbthZLkg
Mod Group:    opencm://rIrdJD4vIwPKANxDrEAxLYaQ3ZWQSA/xgSjAvXiK3YzGEpvhD-kw4gbthZLkg
Notify:       <null>
Name:         Sample
Description:  This is an initial creation of a sample project for purposes of
document writing.

Flags:        0x0
Signature      

[Change]
Change:       "chg_sha1_B53m9BMP-kwMwaHLNkAQj73eBKpsMK"
File ACLs:    "<null>"
CommitInfo:   "cmt_sha1_rR0IGBoWy9hLA2y7CFA6--m3E1cDOH"
Parent:       "chg_sha1_-CPBrDEeVETNQB4BpDACsjyeP5GksJ"
Merge Parent: "<null>"
Entities:
   0  ent_sha1_NvCPXBcfKSGDQlGA76AMu+o4VyQnjA
   1  ent_sha1_t+oIyCUnEaeLgO--HbAtTKop9auUSB
@end example
@noindent
Right now, the show command is not greatly useful because it displays
information mostly in internal terms. The CGI browser interface does a
better job at the moment, and we expect significant improvements in the
next version of OpenCM. Some of the items that are shown are important
for collaboration, though, and we will discuss them further in the next
chapter.

For now, let's change hello2.c o be a "goodbye" message:
@example
# @i{After editing:}
$ @value{OPENCMD} status
[  M      ]      67 ./hello2.c
@end example
@noindent
The M flag indicates that the file has been modified.

The name @file{hello2.c} at this point really isn't appropriate, and we
should probably rename the file. If you were not using a configuration
management system, you would do this with the UNIX @command{mv}
command. Watch what happens if you do that:
@example
$ mv hello2.c goodbye.c
$ @value{OPENCMD} status
opencm: File "./hello2.c" is missing.
? ./goodbye.c
@end example
@noindent
OpenCM is warning you that something confusing has happened. At this
point (@i{don't do this!}), you could add the @file{goodbye.c} file and
remove the hello2.c file by typing:
@example
$ @value{OPENCMD} add file goodbye.c
N ./goodbye.c
$ @value{OPENCMD} remove file goodbye.c
@end example
@noindent
but this is @i{not} the best way to proceed. If you do this, OpenCM will
not know that the file was renamed, and it will have difficulty
performing merges correctly for this file. 

Let's put the file back to
its original name and do things the right way:
@example
# @i{Restore the file back to its original name:}
$ mv goodbye.c hello2.c
$ @value{OPENCMD} mv hello2.c goodbye.c
$ ls
goodbye.c  hello.c
$ @value{OPENCMD} status
[  M  N   ]      67 ./goodbye.c
        Name was: "./hello2.c"
@end example
@noindent
OpenCM has renamed the file on your behalf, and it knows that the file
has been renamed. When you commit this change and other people fetch it
from the repository, OpenCM will be able to correctly preserve any
working changes @i{they} may have made to @file{hello2.c} in their
workspace.
@example
$ @value{OPENCMD} commit -m 'Created goodbye world and renamed appropriately'
[  M  N   ]      67 ./goodbye.c
        Name was: "./hello2.c"
opencm: Uploading CommitInfo Record... 
opencm: Uploading "./goodbye.c"
@end example

@subsection Other Useful Commands

OpenCM provides a means to record ``notes'' about your work in
progress. The @command{@value{OPENCMD} note} command allows you to record stray
thoughts as you work so that you can later incorporate them into your
commit message. OpenCM remembers these notes in its workspace
records. When it laters pops up an editor for you to enter a commit
message, it includes these notes in the file, allowing you to edit them
for incorporation into your commit message.

OpenCM provides both summary help and specific command help:
@example
$ @value{OPENCMD} help
The opencm commands are:

add         adduser     admin       bind        browse      checkout    
commit      create      debug       diff        gadd        gremove     
help        log         import      logmail     ls          merge       
mkdir       mv          ndiff       note        notes       options     
rebind      revert      rm          server      set         show        
status      tag         unbind      update      version     whoami  
$ @value{OPENCMD} help commit
@b{commit} [fsname]*

Uploads local changes to the repository. If one ore more fsnames are
provided, only those files will be commited. Otherwise, all local
changes are uploaded.

See also: @b{import}, @b{tag}
@end example

One last commonly used option is @b{-z[0-9]}, which enables zlib
compression when running commands against a remote server. By default,
@b{-z3} is in effect, which seems to provide most of the benefit
compression can provide without overly burdening the CPU. In some cases,
you may wish to disable compression completely, with @b{-z0}.

@section Branching and Merging

Sometimes it is appropriate to make a sequence of changes
experimentally. If the change is small, it may be perfectly fine to do
this in your workspace, but some changes are larger and more complicated
than this. Often, you want to save your work at various points so you
have a way to back up. In many configuration management systems, this is
more trouble than it is worth, and users avoid doing it. In OpenCM it is
relatively easy to do.

The first step is to create a new ``branch.'' A @dfn{branch} is simply a
line of development that diverges from some existing line of
development. It may represent a new product version that will never
rejoin the original effort, or it may be a private ``work in progress''
that will eventually be merged back into the main code base. In this
case, we will use a somewhat contrived example.

In OpenCM, you begin a divergent line of development using the
@command{create branch} command:
@example
$ @value{OPENCMD} create branch sample mybranch
@end example
@noindent
This command creates a new line of development in the repository called
@file{mybranch} that is derived from the @file{sample} branch. You can
now check out @file{mybranch} in a new workspace directory and
continue your work.

@note{This command is presently misimplemented. It is currently a
repository manipulation command, when it @i{should} be a workspace
command that does not require a new checkout. There needs to be a way to
``fork'' an existing line of development without checking anything out,
but it shouldn't be called @command{create branch}. We need to fix this
for the 0.1 release.}

Having checked out the new branch, you can proceed with changes to
it. Let's add the well-known missing period in hello.c:
@example
$ @value{OPENCMD} status
[  M      ]      66 ./hello.c
$ @value{OPENCMD} commit -m 'Brian cannot spell.'
@end example

Now we can go back to our workspace for the @file{sample} line of
development. You may need to check it out again. You can now type:

@example
$ @value{OPENCMD} merge mybranch
Keeping "./goodbye.c" -- unchanged from common in mergespace
Updating "./hello.c".
Removing "./hello.c"
Renaming ".opencm/scratch/mergeoutput-1" => "./hello.c"
Merge is complete. Please run 'commit' to save any changes.
@end example
@noindent
This will merge the changes made on the @file{mybranch} line of
development into the @file{sample} line of development. You should be
able to see the effects using the @command{@value{OPENCMD} status} command:
@example
$ @value{OPENCMD} status
@end example
@noindent
You can now commit this change integration using the @command{@value{OPENCMD}
commit} command.

Unlike CVS, which doesn't really know what commits are, OpenCM remembers
the merge operations you have done. If you are working on a long-running
effort that you intend to merge, it is likely that the baseline will
move several times before you are ready to do your final integration. If
this is so, you can merge the baseline into your working branch any
number of times to minimize the size of the changes, and then merge your
work back into the baseline at the end of your efforts.

@section Tagging

As we've learned, each new branch, or line of development, can be mapped
to a human-readable name in a user's OpenCM directory.  However, the
human-readable name of a branch, by default, always refers to the latest
version of that branch. Frequently, it's useful to keep track of one
specific version of a branch. OpenCM allows you to tag specific branch
versions with a unique name, so they're easier to manipulate.  For
example, you may want to tag a version of development that represents
what was shipped to a customer.  Such a tag would allow you to always
view the exact state of your development at the time it was shipped.
You can always specify a specific version of a branch by appending a
forward slash and the version number to a branch specification, but a
tag allows you to identify the version using a unique name.  

@c @i{vandy:  now that i think about it, can't we do the exact same}
@c @i{  thing with 'bind'?  tag marks the mutable as frozen, but that}
@c @i{  doesn't really buy us anything:  you can't mod an older version}
@c @i{  of a branch anyway.  do we really need a separate command for this?}

@node Collaborating
@chapter Using OpenCM in Multiperson Teams
@cindex Collaborating

Now that you have the basics of using OpenCM, we can turn to using
OpenCM in team situations.

@section Users and Groups

OpenCM enforces access controls on every repository object. Each object
has an authorized writer and an authorized reader. The authorized
reader/writer can refer to either a user or a group. In this section, we
will show how to create a new group and make the @file{sample} project
accessable to this group.

The first step is to create a group that will control our project:
@example
$ @value{OPENCMD} create group mygroup
Group name: @kbd{shared project group}
@end example
@noindent
By default, the creating user is automatically added to any group they
create, and becomes the authorized reader and writer for that group.

Since this project is to be collaborative, we will want this group to
control both reading and  writing for our project. We also want to let
anyone in this group control access to the group:
@example
$ @value{OPENCMD} set group sample mygroup w
$ @value{OPENCMD} set group mygroup mygroup rw
@end example
@noindent
The second command is a bit tricky: it means that anybody who is already
in @file{mygroup} can add or remove people from @file{mygroup}. This
authority should definitely be treated with care.

If we wanted to make this a publicly readable project, we would set its
reader group to everyone:
@example
$ @value{OPENCMD} set group sample everyone r
@end example
@noindent
Now that we have done this, anybody who knows the name of this group can
add it to their workspace and use it.

Groups are recursive: they can contain other groups. Group membership is
transitive.

@section Binding Objects
Suppose that I have created a line of development and added you to the
write group for it. How do you gain access to is so that you can work
with it?

The answer is that you need to know the object's URI. The object URI is
a cryptographic name that is universally unique. The URI of an object
can be discovered by using the @command{@value{OPENCMD} show} command on the
object:
@example
$ @value{OPENCMD} show sample
URI:          opencm://Amw2iBkmqxZBgmsWYrAFe1wDQrKTDC/tGgt8XvIthbquj6BudgpYL2IhWKgoR
Sequence No:  4
.....
@end example
@noindent
Any user who knows this URI can bind this object into their own workspace:
@example
$ @value{OPENCMD} bind opencm-sample opencm://Amw2iBkmqxZBgmsWYrAFe1wDQrKTDC/tGgt8XvIthbquj6BudgpYL2IhWKgoR
@end example

Binding an object means that you have created a directory entry for
it. It does not necessarily mean that you can access to the
object. Access is still controlled by the read and write groups for the
object.

In practice, it is inconvenient to bind objects one at a time in this
way. A more convenient solution is to create a shared directory for the
project and construct a shared binding for the directory. Once the
directory is shared, all objects within it can be seen by all
parties. It is still necessary to set the access rights on the object
to allow the desired access.

@section Updating Your Workspace

Now that two or more users can check out an object and work on it,
it becomes possible for modifications to overlap. You and I may both
check out a branch. Suppose that I commit my changes before you do. You
may want to incorporate these changes into your workspace and continue
working. It is necessary that you do this before you commit so that work
will not be lost.

To integrate changes made by another person into your workspace, use:
@example
$ @value{OPENCMD} update
@end example
@noindent
This command performs a three-way merge. It updates the baseline version
used in your workspace to be the latest version on the branch, and it
attempts to re-merge your modifications into the new version.

Usually, updating eagerly is the best thing to do. This way your
workspace never gets too far out of date.  Sometimes a change is large
and you may wish to defer the update. This is also a reasonable strategy
for development. Be aware, however, that OpenCM will not let you commit
your changes unless your workspace is up to date.


@node CVS Quickstart
@chapter CVS Quickstart
@cindex CVS Quickstart

This chapter is written for users who already know CVS. It describes how
to import an existing CVS @emph{workspace} into OpenCM. The goal is to
give CVS users a way to learn the workings of OpenCM with low initial
overhead, so that you can make an informed decision about whether to
import an entire CVS repository.

@menu
* OpenCM Commands::  Overview of OpenCM commands
* Importing::        Importing a CVS workspace
@end menu

@node OpenCM Commands
@section OpenCM Command Summary
@cindex OpenCM Command Summary
@note{Use the command-line @code{opencm help} feature to see details on
any of the commands.}
@itemize @bullet
@item
@command{add file} @cmdarg{file} ... Marks one or more space-delimited
local files as new files in the current Workspace.  File contents aren't
uploaded to repository until the @code{commit} command is executed.

@item
@command{add member} @cmdarg{group} @cmdarg{member} Adds the user or group specified by
@cmdarg{member} to the existing @cmdarg{group}.

@item
@command{adduser} @cmdarg{certfile} @cmdarg{r|w|rw} Registers a user on
a repository with the specified repository access (@cmdarg{r} is
read-only and @cmdarg{w} is write-access).  You must specify the path to
the user's certificate file as @cmdarg{certfile} and all certificates
must contain a valid email address.
@end itemize

@node Importing
@section Importing a CVS workspace
@cindex Importing a CVS workspace

@node Getting Started
@chapter Getting Started
@cindex Getting Started

@menu
* Creating a Project:: Creating your first new project.
* Working with Files:: Adding, removing, and renaming files in a project.
* Committing::         Making your changes permanent.
* Updates::            Tracking other people's changes.
@end menu

@node Creating a Project
@section Creating a Project
@cindex Creating a Project

@node Working with Files
@section Working with Files
@cindex Working with Files

@node Committing
@section Committing
@cindex Committing

@node Updates
@section Updates
@cindex Updates

@include manual/cmd-ref.texi

@node Upgrading
@chapter Handling Repository Upgrades
@cindex Handling Repository Upgrades

Most releases of OpenCM are simple. The only change they make to
existing repositories is to upgrade the version number. OpenCM will
automatically perform simple upgrades like this the first time it is
run on a given repository, without asking you for permission.

On rare occasions, however, it is necessary to upgrade or convert the
repository in a significant way. This may occur because of a change in
the repository schema, or because of a change in the supported
repository types. For example, we did this type of upgrade when we
dropped the old SXD version 0 repository type.

When we write upgrade procedures, we typically build them to be done
``in place,'' converting each object and then deleting the old object
as soon as it is fully converted. We do this because repositories can
be very large (ours is currently 1.6 gigabytes), and an in-place
conversion avoids the need to consume very large amounts of disk space
-- which can cause conversion to fail if the disk space runs
out. Also, upgrades can take a while on a large repository, and we
don't want users to wonder why OpenCM seems to be doing nothing.

We are careful, but no matter how careful we may be there is no such
thing as a perfect upgrade process. Therefore, this type of
``invasive'' upgrade is @emph{never} done automatically. If a
potentially destructive upgrade to the repository is needed, OpenCM
will complain and exit. To get the upgrade to happen, you should run
@example
$ @value{OPENCMD} upgrade --repos file:/path/to/directory ls
@end example
@noindent

OpenCM repository files have an owning ``user'' in the eyes of the
native operating system.  If you are running the upgrade on a personal
repository, you should run it as whatever user you would normally
use. Typically this will be yourself. If you are running the upgrade
on a server repository, you should run this as user @cmdarg{opencm},
or whatever user owns your repository files according to your
operating system.

It is @emph{strongly} recommended that you make a backup of your
repository directory before doing any upgrade of this kind. In at
least one of the OpenCM alphas, we got the upgrade wrong and were very
glad to have a backup ourselves!

@node Futures
@chapter Futures and Things To Do
@cindex Future of OpenCM

@node Holding Buffer
@chapter Holding Buffer
@cindex Holding Buffer

As a system designed for archival purposes, OpenCM never deletes data
on the repository.  Thus, it treats all stored data as either 
@emph{frozen} or @emph{mutable}.  The content of any archived 
object is frozen and 
if an archived object is allowed to be modified, its frozen content is
referenced by an additional @emph{mutable} object that chains 
together the history of modifications to the underlying content.  
The state of any @emph{mutable} object is determined by a version 
index directly in the @emph{mutable} and a sequence number in the 
revision record of that @emph{mutable}.  Thus, a 
trail of versions can be established for any @emph{mutable} data 
by referencing these version and sequence numbers.  The 
repository itself has no other knowledge of the stored data.  

========================
Command line options:

long opts:
@itemize
@item
@kbd{--repository} specifies the repository URI on which the given command
should operate.  This takes precedence over the repository specified in
the current Workspace as well as the setting of the @env{OPENCM_REPOSITORY}
environment variable. 

@item
@kbd{--configdir} specifies the path to the user's OpenCM configuration
directory.  This overrides @file{$HOME/.opencm}.

@item
@kbd{--keytype} specifies the keytype argument to the 
@command{openssl req} command when generating new keys. OpenCM currently
only supports rsa keys.

@item
@kbd{--messagefile} specifies path to a file whose contents are used
as the message passed to the client command.  

@item
@kbd{--name} specifies one-line synopsis text used for creating branches
and groups.

@item
@kbd{--flush-io} calls the @code{setlinebuf} system call on @code{stdout}
and @code{stdin}
@end itemize

short opts:
@itemize
@item
@kbd{-u} specifies name of PEM file (without suffix) to use as the 
user's certificate.  File must exist in the configuration directory.

@item
@kbd{-m} alternate method of specifying the contents of a message passed
to the create commands.

@item
@kbd{-e} specifies the editor to use for prompting user for text.  Overrides
the setting of the @env{OPENCM_EDITOR} environment variable.

@item
@kbd{-v} sets verbose mode

@item
@kbd{-l} sets long listing mode

@end itemize

@ifnothtml
@contents
@end ifnothtml
@bye
