Archive Files
Archive File Names
You never explicitly specify the QVCS archive name for QVCS commands. The QVCS archive name is derived from the filename given on the command line. All utilities use the same algorithm to derive the QVCS archive name. They first try to find a matching project in qwin.ini and your user .ini file based on the current directory. The matching algorithm finds the project with a work file location that most closely matches the current directory. Using the settings of that matching project, QVCS then uses that project's settings to locate the QVCS archives that are appropriate for the current directory. The QVCS archive extension is created by taking each letter of the work file extension and turning it into the next letter of the alphabet. For example, the QVCS archive name for foo.abc would be foo.bcd. The actual location of foo.bcd is determined from the project settings of the matching project.
Archive File Format
This information is technical in nature and subject to change without notice. You don't need to understand any of this unless you are planning to write your own code to access a QVCS archive. The structures here describe a QVCS archive without COMPRESSION enabled. For information on the format of archives that have COMPRESSION enabled, please contact tech support.
QVCS archives begin with a header that describes the contents of the archive. This structure is described in 'C++' as:
struct qvcsDifFileHdr | // Header of QVCS logfile |
{ |
| short int iQVCSVersion; | // QVCS Version |
| short int iMajorNumber; | // Major revision number of trunk |
| short int iMinorNumber; | // Minor revision number of trunk |
| short int iAttributes; | // Attributes for this logfile |
| short int iVersionCount; | // Number of version stamps |
| short int iRevisionCount; | // Number of revisions here |
| short int iDefaultDepth; | // Depth of default branch (trunk=0) |
| short int iLockCount; | // Number of locks on the logfile |
| short int iAccessSize; | // Length of Access list string |
| short int iModifierSize; | // Length of Modifier list string |
| short int iCommentSize; | // Length of comment prefix string |
| short int iOwnerSize; | // Length of Owner string |
| short int iDescSize; | // Length of Module desc |
| short int iSupplementalInfo; | // Length of the supplemental info section |
| short int iCheckSum; | // Header checksum word |
}; |
The iQVCSVersion element is 6 for release 3.x of QVCS.
The header checksum is computed by taking the simple arithmetic sum of all elements in the header that precede the checksum structure element.
This header structure is followed by header type information that is of variable length. The first variable length element exists only if the default depth of the QVCS archive isn't 0, meaning that a branch other than the trunk is the default branch for the archive. The other variable length elements follow the structure that defines the default branch. The length of each of these variable length elements is given in the header by the corresponding size structure element.
If it exists, the structure that defines the default branch for the archive is given by:
struct qvcsCommandRevDesc | // Describe a revision |
{ |
| short int iElementCount; | // Number of major/minor pairs here |
| short int iRevisionAttributes; | // A range or not |
| struct qvcsCommandRevNums sRevDesc[20]; |
}; |
where the qvcsCommandRevNums structure is defined as:
struct qvcsCommandRevNums | // revision info |
{ |
| short int iMajorAttributes; | // wildcard, default bits |
| short int iMajorNumber; | |
| short int iMinorAttributes; | |
| short int iMinorNumber; | |
}; |
There are only as many qvcsCommandRevNums structures as needed to describe the default branch.
The other variable length elements appear in the same order in the archive as they appear in the header. For example, immediately following the header (or the default branch description) is the Access List for the archive. The length of the Access List is given by the iAccessSize structure element. Immediately following the Access List information, is the Modifier List information, followed by the Comment Prefix string, etc.
Following the variable length header information, is the label information (if any). The label information is repeated for as many labels as exist (given by the iVersionCount element of the header structure). If the iVersionCount element of the header is 0, then the archive doesn't contain any label information; i.e. the header is followed immediately by the first revision. Each label is described by variable length label structures followed by the variable length label string. The label structure is described in 'C' as:
struct qvcsVersionInfo | // Label information structure |
{ |
| short int iRevisionCount; | // Number of VersionRevInfo's |
| short int iCreatorIndex; | // Index of label's creator |
| short int iVersionSize; | // Length of label string |
}; |
Immediately following the qvcsVersionInfo structure is some number (given by iRevisionCount) of qvcsVersionRevInfo structures. These are defined as:
struct qvcsVersionRevInfo | // Describe a version |
{ |
| short int iMajorNumber; | |
| short int iMinorNumber; | |
}; |
Immediately following these structures which define the revision that a label string is associated with is the NULL terminated string for that label. The iCreatorIndex element gives the index into the archive's modifier list of the individual who defined this label for this archive. The iVersionSize element gives the length of the label string including the NULL termination.
Immediately following all label information is the revision information. Trunk revisions are stored in backward delta format. This means that the first revision found in the QVCS archive is always the newest trunk revision. Previous trunk revisions are stored as backward deltas to that latest revision. This approach makes the retrieval of the most recent trunk revision fairly fast, since it is stored "as is"; i.e. no deltas need to be applied to the revision in order to retrieve it from the archive.
Trunk revisions are stored in newest to oldest order in the archive, i.e. the newest revision appears closer to the start of the archive than older revisions.
Branch revisions are stored in "forward delta" format. This means that newer branch revisions come after older branch revisions in the archive. Consequently, storing and retrieving branch revisions is necessarily slower than trunk revisions.
Each revision is described by a revision header structure that is described in 'C' as:
struct qvcsRevisionInfo | // Revision information structure |
{ |
| short int iMajorNumber; | // The major revision number |
| short int iMinorNumber; | // The minor revision number |
| short int iLockFlag; | // TRUE if this revision is locked |
| short int siChildCount; | // Number of child branches here |
| short int siDepthCount; | // Branch depth of this revision |
| char cTipFlag; | // TRUE if this is a tip revision |
| char cCompressFlag; | // Non-zero indicates compressed |
| char cNewLineFlag; | // TRUE if binary NEWLINE is present |
| char cNewLineChar; | // NEWLINE choice for BINARY file |
| time_t tPutDate; | // Time when revision created |
| time_t tFileDate; | // Time of file that created rev |
| long lRevSize; | // size of revision in logfile |
| short int iLockerIndex; | // locker's index in modifier list |
| short int iCreatorIndex; | // creator's index in modifier list |
| short int iDescSize; | // Length of revision description |
}; |
Immediately following each revision's qvcsRevisionInfo structure, is the revision's description. The length of the description is given by the iDescSize element of the structure. Following this header information is the revision itself.
For the newest revision, the revision information is identical to the latest file inserted into the logfile, except for logfiles that have EXPANDKEYWORDS enabled, in which case, the keywords are contracted before the file is inserted into the logfile.
For revisions older than the newest revision, the revision information consists of an edit script that QVCS applies to the immediately preceding (newer) revision in order to create the revision described by its qvcsRevisionInfo structure. The edit script is variable in length and consists of qvcsEditInfo structures followed by variable length data (for inserts or Replaces).
The qvcsEditInfo structure is described in 'C' as:
struct qvcsEditInfo | // Edit information structure |
{ |
| short int iEditType; | // Edit type (INSERT, DELETE, REPLACE) |
| long lSeekPos; | // Starting offset to make the edit |
| long lByteCount0; | // Bytes to change in first file |
| long lByteCount1; | // Bytes inserted from 2nd file |
}; |
For inserts or replaces, the qvcsEditInfo structure is followed by lByteCount1 bytes of data which is used to alter the original file.
The qvcsEditInfo structures are repeated for as many differences as there are between the two revisions.
|