This is the design documentation for the SVMS (Source Version Management System).
This document contains the design notes for SVMS. These design notes are broken into the following sections:
The design goals and rational for SVMS are kept in separate documents.
Before digging into the design issues of SVMS, it is worth discussing "Why write any design notes in the first place?" There are lots of reasons for not writing any design notes:
Before diving into design issues, I want make my opinions about SCCS, RCS, CVS, SunPro/SunSoft Code Manager perfectly clear. I think all five of these programs are quite good. Indeed, I find the functionality provided by Code Manager to be sufficiently compelling to my day-to-day coding activities, that I feel compelled to duplicate those capabilities for Linux. In the design below, there are comments about design flaws and/or bugs in the above mentioned programs; this is only to be expected of programs whose inception started in the late 1970's and early 1980's. Since I feel compelled to replace some of the functionality of the above mentioned programs, I think it is appropriate for me to attempt to avoid some of the mistakes of the past and try to improve things as I go along. So please interpret any critical comments these programs as constructive comments rather than non-constructive ones.
The next section of this document provides a glossary of SVMS terms and their corresponding definitions.
There is enough terminology and jargon associated with SVMS that it is worth providing the a glossary of terms and there definitions. These terms and definitions are listed alphabetically below:
v.
.
Other words and phrases to add to the glossary are:
The next section (finally) delves into the overall design issues for SVMS.
An SVMS project area, or project for short,
is directory tree that contains a directory named
SVMS
, where a directory tree is defined
as all of the files within a given directory and its
sub-directories. When a project area is created, it
is given a reasonably short project nickname
(e.g. gramlich-fix and gramlich-new-feature.) If two
project areas are given the same project nickname,
it is not possible to readily move files between them;
instead, it will be necessary to give one of the
projects a new project nickname. Giving a project a
new project nickname is a very expensive operation that
requires rewriting almost every history file within a
project directory tree. Thus, it behooves people to
choose project nicknames that are unlikely to ever
collide.
Probably the most important design point for SVMS
is that an older version of a project area can be
recreated in its entirety just by knowing the project
nickname and the older version timestamp. At any
given timestamp, the same file in different project
areas can have differing contents; indeed, it will
be quite common for a new file to exist in only one
project area when it is first created before it
propagates to other project areas. An important
side-effect of the timestamp design point is that
history files are never moved, renamed, or
deleted; this is quite different from SunSoft's Code
Manager product which requires that SCCS s.
files to be renamed on a regular basis. The SVMS history
file format is able to keep track of multiple versions
of a file on a per project and per timestamp basis.
Given the importance of timestamps in recreating older versions of project areas, it is important that a consistent version of time be kept for each project. SVMS is designed to work with NFS. Since the system clock on a user's local machine can be quite different from the system clock on the remote NFS server, SVMS will always use timestamps derived from files (i.e. the NFS server system clock.) Huge projects can be spread across multiple file systems served by different NFS servers, but SVMS will always attempt to detect if any significant clock skew has occurred between the systems; if so, SVMS will mandate that the various system clocks be brought back into synchronization.
When SVMS transfers files between project areas, care is taken to ensure that the current relative timestamp order is preserved. This can be critical for not breaking programs that depend upon relative file ages (like make.)
The timestamp design point permits lazy bringovers, since all that must be recorded for a lazy bringover is the parent project root directory and the bringover timestamp. For a project that has been brought over in a lazy fashion, history files are copied into the project only as they are modified. For large projects, lazy bringovers save a great deal of disk space and time. Recursive lazy bringovers are permitted.
In many development shops, desk top machine backup is not provided. This causes many people to develop their code on remote file systems via NFS that have slower access performance, but are backed up on a regular basis. SVMS provides a means of allowing all development to proceed on a significantly faster local disk. On a regular basis (e.g. logout, nightly, etc.), the user can cause the contents of all open files and/or changed history files to be backed up to another machine. This can save quite a bit of day-to-day programmer time and network bandwidth.
SVMS permits files to be in one of five states:
When a file is in the deleted state, there is no version of the file in the regular project directories; however, the history file continues to exist. Note that UNIX hard links, named pipes, and special devices are not directly supported by SVMS.
The basic type of a file name can evolve as a project evolves. For example, early in a project a given file name might refer to a single binary file and later in the same project, the file name might refer to a directory. SVMS history file format supports the ability for file names to change their basic type over time.
The SVMS history file format directly supports the concept of a deleted file in order to avoid a serious design flaw associated with SunPro/SunSoft Code Manager. The problem with SunPro/SunSoft Code Manager is that there is no reliable way delete files from one workspace and to reliably propagate that deletion to other workspaces. Whenever someone attempts to delete an SCCS history file (i.e. an s. file) in their workspace, very frequently, the next bringover/putback operation with another workspace that still has the SCCS history file will cause the file to reappear. Thus, experienced users of SunPro/SunSoft Code Manager no longer attempt to delete SCCS history files; instead, they rename the history files to a directory that exclusively contains deleted files (a.k.a DELETED.) It is really unfortunate that SunPro/SunSoft Code Manager forces people to rename SCCS history files, since that precludes providing automatic support for restoring previous versions of the workspace; instead, users have to anticipate that they will want a particular prior version of the workspace, record a snapshot file, and keep track of the snapshot file. All the hairy code required to support SCCS history file renaming in SunPro/SunSoft Code Manager is avoided in SVMS by directly supporting deleted files in SVMS history files.
In addition to deleted files, SVMS supports the concept of directories in history files in order to avoid another less serious design defect in SunPro/SunSoft Code Manager concerning the deletion of directories. In Code Manager, the only way to delete a directory from a workspace is to rename all of the SCCS history files to another location and propagate the renames to other workspaces; while this does not directly cause the directory to be deleted in the other workspaces, the next time a workspace is built from scratch, the directory will no longer be present. In SVMS, directories are both explicitly added to a project and explicitly deleted from a project area. When one project area is merged with another project area, the appropriate directory creations and deletions occur automatically. For safety purposes, SVMS will not delete a directory unless its contents are empty. Thus, a bringover/putback of a deleted directory will very frequently generate an SVMS error mandating that the user manually clear the directory to be deleted and retry the operation.
One of the goals of SVMS is to have bringovers and putbacks take time proportional to the differences between the two workspaces rather than requiring a complete workspace comparison. The way this goal is met is by computing a signature for each history file. All of the signatures for all of the source files are assembled into a directory signature file. The directory signature files are rolled up to the project root. By comparing signatures, it is possible to rapidly identify the differences between any two project workspace.
For text and binary files, the executable bits are
preserved in the history files. This allows the
direct storage of binary executable and executable
shell scripts in history files without having to
do any mucking around inside of a Makefile
.
{Actually, at the moment, there only seem to be two kinds of symbolic links -- Good and other.} Symbolic links merit further discussion. There are three kinds of symbolic links:
All forms of symbolic links can be stored in a history file, but the OK and Bad forms require a little extra effort to override error messages.
SVMS is a little different from SCCS and RCS when it comes to editing files. Both RCS and SCCS have the concept of a file being checked-in or checked-out. SVMS is a little different in that files are either open (read-write) or closed (read-only). When a file is closed, care is taken to just change the mode bits (access control bits) for the file from read-write to read-only. Since the file contents are not modified when it is closed, make will not perform a whole bunch of unnecessary rebuilding when a file closed. From a design point of view, what this means is that any new identification strings are inserted into a file when it is opened; this means that when a file is subsequently closed, none of the file contents need to be changed. A further implication of this design decision is that when a SVMS history file is closed, its modification time is set back to one second prior to the last modification time of the source file; this means that make will not do a gratuitous update of the source file because the history file timestamp is more recent than source file timestamp. {By the way, I am nervous about about resetting the history timestamp; this is generally considered to be an impolite thing to do.}
SVMS supports identification strings. The goal is to support free format strings the way that SCCS supports them. Given the desire of not modifying the file contents when it is closed, SVMS has to go through a bunch of contortions to keep track of what is really going on. Here are the identification strings that can be inserted.
In order to fully support parallel development, the SVMS history files need to be able to represent development branches. This is accomplished by naming historys with a unique project identifier and a history number that is unique for the project. This design decision allows for the easy merging of historys during a project merge operation.
It is an SVMS goal to support the development of software distributed around the Internet. In order to support this goal, the access to a parent project can be performed via the HTTP protocol. While protocols other than HTTP could be considered (e.g. TCP/NFS), HTTP is far more likely to work through most corporate firewalls than some of the other probably superior protocols (like TCP/NFS). The SVMS system is designed to be able to perform a bringover exclusively via HTTP GET operations. This will be most efficient if HTTP 1.1 is implemented at the remote site and connection multiplexing (i.e. reusing the same TCP connection for multiple GET's) implemented all the way from end-to-end. There will be an explicit way to specify a corporate proxy server for HTTP access. There will be two forms of HTTP putback supported -- a pullback executed at the parent site running the HTTP server or a putback via a HTTP POST operation initiated at the child site.
The way an HTTP post is performed to do a putback is to put all of the changes into a tar file, unpack the tar file at the server, and run a local putback command. Any error messages are echoed back as part of the POST output. This is very similar to the media putback described below.
It is a goal of SVMS to allow history files to
be either encrypted and/or compressed. Both
encryption and compression technology have a
number of legal issues. For this reason, SMVS
does not implement any specific algorithm to
support either encryption or compression; instead,
a more general mechanism is provided that allows
someone to plug in a generic program in. Thus,
if you have an appropriate license to the latest
LZW compression algorithm, you are free to use it;
alternatively, you are welcome to use the
gzip/gunzip
algorithms that appear
to be legally unencumbered. Similarly, if you
can find an encryption algorithm that can be
used without violating export controls (in the
USA, it is fairly common to get an export license
for 40-bit RC4), you can plug that in as well.
If you can not find a legal encryption algorithm
whose security you are comfortable with, you will
have to live without.
One of the SVMS goals is to allow secure bringovers
and putbacks via the unsecured public internet.
This is accomplished by simply encrypting the
SVMS directory tree using some legal encryption
algorithm and then making the encrypted SVMS
directory tree accessible via an HTTP server.
An HTTP server is just as happy to deliver
encrypted bits as unencrypted bits. The files
are encrypted using a password that is exchanged
via some other channel (e.g. snail-mail, E-mail,
FAX, a telephone call, a face-to-face meeting,
public key cryptography, etc.) In order to
keep the password slightly secure, SVMS will
prompt for a password and then pass the password
to the encryption/decryption algorithm via
standard input; the alternative of passing the
password in via a command line option, is not as
secure, since the ps
command snoops
and displays command line options. Most HTTP
servers will return a directory listing if there
is no index.html
file present
in a directory. In order to prevent people from
deducing information about a project from the
directory structure, an encrypted project will
have an empty index.html
file present
in each d.
directory.
One of the goals is to allow bringovers and putbacks via physical media transfer such as a floppy disk or magnetic tape (i.e. sneaker net.) The sub-goals of media transfer mode are:
Media mode is accomplished as follows:
For a media bringover, the following steps occur:
For a media putback, the following steps occur:
The bringover and putback commands are basically the same command with a few minor differences in behavior:
The way that a putback is normally performed is that the use does a bringover first, compiles and tests everything, and then does a putback. If two people are trying to do a putback at the same time, one of the people is going to get their changes in before the other and the other person will have to do an additional bringover before doing their putback.
For a bringover, the source project is the parent and the target project is the child. Conversely, for a putback, the source project is the child and the target project project is the parent. The way a workspace merge works is as follows:
p.listing
files and looking for
files that have different hash values.
b.
file is created to record when the file showed
up in the child project. For a putback, a delta
is entered into the updated parent history file
to record when it arrived in the parent; this
delta will have both a regular and a merge
ancestor. All putback deltas in all of the
updated history files are given exactly the
same timestamp so that conceptually show up at
exactly the same time in the parent project.
A conflict is resolved as follows:
b.
file associated with conflict is absorbed as part
of the resolution process.
Each conflicting history file from the parent is stored
in the SVMS directory tree in as a c.
file
stored in the same directory with the same base name.
For example, if main.c
has a conflict,
in the same directory as h.main.c
the
conflicting history file from the parent would be
stored in c.main.c
.
The next important area to discuss is the organization
of the SVMS
directory.
SVMS
Directory Design
For SVMS, a project is contained in a single
directory tree whose root is called the project
root. The project root is identified to the rest
of the SVMS system by installing a directory called
SVMS
in the project root directory.
The SVMS
directory contains a
mirror image of the all the files and directories
in a project. The various files in a SVMS
directory are tagged with prefix characters. Prefixes
are used so that there is no danger of accidental
collision in the future. The prefix tags are:
b.
file_name b.
file_name is a
bringover file in tagged file format.
The b.
file format is
discussed in greater detail in the
bringover file format section
below.
c.
conflict_file_name c.
conflict_file_name
is a conflict file. It is simpley a
history file from the parent that
has not been resolved.
d.
directory_name d.
directory_name
is a sub-directory. For every
d.
sub-directory, there is
a corresponding h.
history
file.
h.
file_name h.
file_name is a
history file in tagged file format.
The h.
file format is is
discsussed in greate detail in the
history file format section below.
l.
file_name l.
file_name is a
lock file in tagged file format.
The l.
file format
is discussed in greate detail in the
lock file format section below.
p.listing
p.listing
file is an
alphabetical listing of all h.
files in a directory. In addition, if there
are any d.
sub-directories or
b.
bringover files,
that information is recorded in the
p.listing
file as well.
The p.listing
file format
is discussed in greater detail in the
p.listing
file format
section below.
The top level SVMS
directory contains
some additional files that are preceded by a
p.
prefix:
p.notify
p.project
p.project
file format is
discussed in greater detail in the
p.project
file format
section below.
p.releases
Many of the files are in a format called tagged file format. Tagged file format is discussed next.
A tagged file is a human readable ASCII file that basically consists of a bunch of tagged lines. Each line starts with a tag character, zero, one or more values, followed by the appropriate new-line sequence for the file system.
The data types that can occur on a tagged line are:
There are two `standard' header lines and they are:
H
"type" major minor E
Whenever SVMS encounters a tagged data file with a major version number that is does not match the expected major version number, everything screeches to halt. Whenever SVMS encounters a tagged data file with a minor version number that is less than the expected one, everything halts with a fatal error message. Whenever SVMS encounters a tagged data file with a minor version number that is greater than the expected one, SVMS goes into a mode where it silently skips over lines that are tagged with a letter that is not expected.
Whenever it is time update the revision numbers
on the tagged file format files there is a special
SVMS command, called svms regen
, that
will visit all of the SVMS files in a project and
update any that are out of date to be to the
latest revision number.
Whenever it is time to update a file in tagged file format, the new file is carefully written out in its entirety into a temporary file in the same directory. After the file is closed, it is renamed to overwrite the previous file contents. This ensures that a system crash will never result in an incomplete tagged file format file.
Now it is time to talk about the design of history file format.
A history file is a file in tagged file format that contains a bunch of versions and deltas. A version corresponds to a particular instance of a source file. A version does not have any timestamp, project, or ancestor information. A delta specifies a particular version and adds in project, timestamp, and ancestor information. Thus, a history file consists of one or more version segments, where each version segment is referred to by one or more delta segments. In general, whenever a file is propagated to another project, a simple delta is generated to record when the delta showed up in the project (there is one exception.) Whenever a file is modified within a project, a new version is generated.
The entire history of a file is kept in its
h.
history file and any associated
b.
bringover file. Bringover files are
discussed in greater detail in the section on
bringover file format. Basically, a bringover file
can contain some extra deltas that indicate when a
particular file migrated from the parent project to the
child project. At various times, a file's
b.
bringover file is merged into the file's
h.
history file and the b.
bringover file is deleted. In summary, the entire history
of a file can be thought of as the union of its
h.
history file and its b.
bringover file.
To simplify development, history files are going to be
stored in a human readable text format (i.e. tagged file
format.) While this means that history files will not
be as compact as possible, the current low cost of disk
space does not warrant getting maximum compression.
If necessary, a publicly available compression program
like gzip/gunzip
can be used to get
additional compression.
History file design is meant to be logically thought of as an append only file format. In fact, a whole new history file is created and then renamed into place in order to ensure file consistency. Project merges are the only exception to the append only rule\ and are discussed below.
A history file contains the following tagged lines:
H "SVMS_History_File"
major minor N
"basename" "timestamp" V
offset "type" "nickname"
"nickname_timestamp" executable
"version_timestamp" Binary
Deleted
Directory
Link
Text
L
line_count T
, B
, and R
records that follow.
T
"line_string" B
"binary_string" R
"count ranges..." |
'
or `@
', Version specifies
a version number, Offset specifies a
a line offset withing a version, and Span
specifies then number of consecutive lines to
use. None of this will make any sense until an
example is explained below.
C
range D
range X
delta_offset version_offset
"delta_type" "project_name" "project_timestamp"
"delta_timestamp" delta_number "user_name"
{other type specific fields} "Deleted"
"Directory"
"File"
"Link"
The following addition fields are present for files:
T
, this delta has
an ancestor and its offset
follows immediately in the
ancestor_offset field;
otherwise, there is no
ancestor_offset field.
In general, every delta except
the first one in a history file
has an ancestor.
T
.
T
, this delta is the
result of a merge of two previous
deltas. The first delta is specified
by the ancestor_offset and
the second delta is specifed by
the immediately following
merge_offset field;
otherwise, there is no
merge_offset field.
In general, merge deltas occur
as a result of a bringover operation.
T
.
The following additional field is present for symbolic links:
Each version segment has a unique name that consists a project nickname and history number. Each time a new version segment is created, it uses the project nickname of the current project to identify the version segment. The new history number is equal to the greatest history number in the history file plus one. Version segments are kept in a history file sorted by timestamp followed by project nickname. It is this sorting rule that causes the append only rule to be broken when projects are merged; any intermediate versions from other projects are merged into place properly in the history file to maintain the sort order.
A bringover file (i.e. b.
file) provides some
additional information that belongs in the history file
(i.e. h.
file), but has not been merged into
the history yet. A bringover file basically records
whenever a version of a file has migrated from the parent
project to the child project. Whenever multiple versions
of a file have been brought over from the parent project
to the child project via multiple bringover commands, for
each bringover, there will be a corresponding record in
the bringover file.
The reason for having a bringover file is a little subtle. Basically, I want a bringover followed by a putback to result in only the files that changed being putback. If I record when the file shows up in a project as a delta in the appropriate history file, its contents will change and a the next putback will have to merge the changed contents back up to the parent project; this would occur for every file in the project (not what I had in mind!) So, instead, I record when the bringover occured is a small separate file called the bringover file that does not effect the contents of the history file.
The next question is `why not store the timestamp
in the p.listing
file and forget about a
separate b.
file?' The answer to this
question is because I want to be able to regenerate
p.listing
files by inspection of the
the SVMS directory tree. That way p.listing
files can be damaged (a not unthinkable occurance)
and still have a viable recovery technique.
When do b.
files get deleted?
Basically, b.
files get deleted whenever
the associated history file contents are augmented.
This can occur when a file opened and closed for
editing, or whenever a merge occurs, etc. Also,
there will be an operation (probably
"svms parent -e
" and/or
"svms parent -u
" that allows the project
owner to manually force all bringover files to be
merged into their associated history files. The reason
for forcing the bringover files to be eliminated is
to ensure that complete `snapshots' of the child project
exist in the parent project. If the parent and child
projects exist on different machines, this is a very
effective form of backup.
A bringover b.
is a tagged file containing
the following records:
H "SVMS Bringover"
major minor F
"file_name" count B
parent_history_hash
"parent_project_name" "parent_project_timestamp"
parent_delta_number "parent_delta_timestamp"
"child_project_name" "child_project_timestamp"
child_delta_number "child_delta_timetamp"
"parent_delta_timestamp" h.
history file.
E
A l.
lock file is used to indicate
when a file is open (i.e. writable) for editing.
It basically just contains as timestamp for when
the open operation occured and the name of the
person who did the opening.
A lock file consists of the following records:
H "SVMS Lock File"
major minor U
"file_name" "user_name"
"open_timestamp" E
An example l.
lock file looks as follows:
H "SVMS Lock File" 1 0 U "Makefile" "Wayne Gramlich" "1997/01/04@22:14:13GMT" E
p.listing
File Format
A p.listing
file is basically a directory
listing. The purpose of a p.listing
file
is three-fold:
p.listing
file supports
bringover/putback operations via HTTP. HTTP has
no well defined directory format. By storing a
directory format in a well defined file format,
it is possible to fetch the information via HTTP.
p.listing
file supports the
rapid determination of differences between
projects. This is accomplished by computing
a hash value associated with each history file
and sub-directory. Whenever the hash value is
different between two projects, there is work
to be done by the bringover/putback command.
p.listing
file supports lazy
bringover by marking an entry as being lazy.
If the lazy flag is present, it means that
the actual history file is located in the parent
chain somewhere. This can save an enormous
amount of disk space.
A p.listing
file contains the following
tagged lines:
H "SVMS Listing"
major minor C
count F
"file_name" "file_type"
history_hash history_present bringover_hash
conflict_hash lock_hash directory_hash
[ bringover_total conflict_total
directory_total history_total lock_total ] h.
file_name
history file. It may have one of
the following values:
"Derived"
"Directory"
"Deleted"
"File"
"Link"
h.
file_name
history file contents. If there is no
history file present, history_hash
will be the hash value of the appropriate
history file from the parent chain.
T
if there is a history file present;
otherwise, it is F
and the
history file is somewhere in the parent
chain.
b.
file_name
bringover file contents. When a
b.
file_name file
exists, it indicates that the corresponding
h.
file_name
eventually needs to have a bringover delta
inserted into it. If bringover_hash
is zero, there is no
b.
file_name.
c.
file_name
conflict file. A
c.
file_name
file is a history file from the parent that
needs to be merged into the corresponding
h.
file_name history
file. If conflict_hash is zero,
there is no
c.
file_name conflict
file.
l.
file_name
lock file contents. When a
l.
file_name file
exists, it indicates that the corresponding
h.
file_name is open
for editing. If lock_hash is zero,
there is no l.
file_name
lock file.
p.listing
file in
the d.
file_name
sub-directory. If directory_hash
is non-zero, the bringover_count,
conflict_count,
directory_count,
history_count,
lock_count fields will
immediately follow. If there is no
d.
file_name
sub-directory, directory_hash
will be zero.
b.
bringover files in the
b.
file_name
sub-directory tree.
c.
bringover files in the
c.
file_name
sub-directory tree.
d.
conflict files in the
d.
file_name
sub-directory tree.
h.
lock files in the
h.
file_name
sub-directory tree.
l.
lock files in the
l.
file_name
sub-directory tree.
S
bringover_count conflict_count
directory_count history_count lock_count E
record.
The summary record has the following fields:
b.
files in the directory
only.
c.
files in the directory
only.
d.
files in the directory
only.
h.
files in the directory
only.
l.
files in the directory
only.
T
bringover_total conflict_total
directory_total history_total lock_total E
record. The contents
of the total record are reflected one level up
in the corresponding file record in the parent
p.listing
file. The total record
has the following fields:
b.
files in the directory
tree.
c.
files in the directory
tree.
d.
files in the directory
tree.
h.
files in the directory
tree.
l.
files in the directory
tree.
E
An example p.listing
file looks as follows:
H "SVMS Listing" 1. 3. C 3 F "include" "Directory" #123. #0. #0. #0. #234. 0. 0. 0. 3. 1. F "src" "Directory" #345" #0. #0. #0. #456. 0. 0. 2. 4. 2. F "Makefile" "Text" #567. #0. #0. #0. #0. S 0. 0. 2. 3. 0. T 0. 0. 4. 10. 3. E
{Talk about why the p.listing file contains then infomation that it does.}
p.project
File Format
{p.project file format goes here.}
I am not a big fan of make; however, until I get around to replacing make with something better, I have to live with make's peculiarities. The make integration described below is not intended to be elegant; instead, the integration is intended to be just sufficient to get the job done.
There is a problem that I call the `cold start problem'
where make does not interact well with a
project management system. It is desirable to be able
to go into empty project sub-directory and fire off
make and have everything be properly checked
out and built. Unless care is taken to properly design
the the Makefile
, it is rarely the case
that a cold start will succeed.
There are some sub-problems with the `cold start problem':
Makefile
via an include
directive. However,
the make program will fail if these
makefile fragments are not present when
make is run.
SVMS uses the same basic strategy to solve the first
two cold start sub-problems -- namely, a makefile
fragment it generated that lists the necessary
dependencies. The user then just includes the makefile
fragment at the beginning of the Makefile
and the regular dependency tracking code inside of
make does the rest. The solution to the
Makefile fragment dependency problem is to automatically
(via magic) generate the Makefile fragment at directory
creation time.
The svms makefile
command is used to make
a makefile fragment. The basic file format looks as
follows:
SVMS=svms PROJECT_DIR=../../.. SVMS_DIR=$(PROJECT_DIR)/SVMS DELTA_DIR=$SVMS_DIR/d.a/d.b/d.c # Source file dependencies: file1: $(DELTA_DIR)/f.file1 .../fileA.h .../fileB.h ... .../fileC.h $(SVMS) get $@ file2: $(DELTA_DIR)/f.file2 .../fileD.h .../fileE.h ... .../fileF.h $(SVMS) get $@ ... fileN: $(DELTA_DIR)/f.fileN .../fileX.h .../fileY.h ... .../fileZ.h $(SVMS) get $@ # Implicit dependencies: .../fileA.h: $(SVMS_DIR)/.../f.fileA.h $(SVMS) get -R $@ .../fileB.h: $(SVMS_DIR)/.../f.fileB.h $(SVMS) get -R $@ ... .../fileZ.h: $(SVMS_DIR)/.../f.fileZ.h $(SVMS) get -R $@
Since SVMS history format is being designed from the ground
up to directly support projects, it has a place to store
the implicit dependency file list each time a source file
is checked in. {These records need to be defined.} The
implicit dependencies are determined by examining
.make.state
, if it is present, and by running
makedepend otherwise.
Finally, the svms get
command will attempt
to preserve the relative order of modification timestamps
so that make does not get terribly confused.
That is about it for the design of SVMS. It certainly meets the primary requirement of working on Linux.
Below are my notes on improving the command line syntax for SVMS.
Project Commands svms new [-R] {path} svms parent {path} svms signature svms bringover {slice}... svms putback {slice}... Example "sneaker-net" bringover: # On child machine: rm -rf /tmp/sneaker svms create -R /tmp/sneaker sneaker cd /tmp/sneaker; svms parent -d /tmp/sneaker -s /tmp/signature cd {child}; svms bringover -??? cd /tmp; tar cvf /dev/rst4 signature # On parent machine: rm -rf /tmp/sneaker svms create -R /tmp/sneaker sneaker cd /tmp/sneaker; svms parent -d {parent} -s /tmp/signature cd /tmp/sneaker; svms bringover :/... cd /tmp/sneaker; tar cvf /tmp/sneaker.tar . # On child machine: cd /tmp/sneaker; tar xvf /dev/rst4 cd {child}; svms bringover :/... Example "sneaker-net" putback: ... Example "HTTP" bringover: svms parent -h http://host_url/path/ -p http://proxy_url:8080/ svms bringover {slice}... Example "NFS" bringover svms parent -d /net/foo.org/path/ -e svms bringover File Commands: svms create {file}... [-c {file} | -C previous | -C pipe | -C empty | -C prompt*] [-d {file} | -D previous* | -D pipe | -D empty | -D prompt] [-i {file} | -I previous | -I pipe | -I empty | -I file*] [-m binary | -m text | -m link | -m guess*] [-f] [-t {timestamp} | -T now*] [-u {user} | -U current*] [-f] [-k] {file}... svms close {...} svms open [-c {file} | -C pipe | -C none*] [-d {file} | -D pipe | -D none*] [-o {file} | -O pipe | -O file*] [-v {number} | -V latest*] [-n {nickname} | -N current* | -N parent] [-k] {file}... svms get svms delete file... svms undo file... svms rename [] old_file new_file svms copy [] old_file new_file svms history file... svms diff file... Options: -f Force acceptance of symbolic link. -k Do not substitute SVMS variables. -m binary Force all files into binary mode. -m text Force all files into text mode. -m link Force all files into symbolic link mode. -m guess Guess what type of file it is. -n {nickname} Project nickname -v {number} Obtain version number {number}. Directory Commands: svms mkdir [-xxx] directory... svms rmdir [-xxx] directory... Other commands: svms tell {slice}... svms generate [-m html | -m text] {slice}...