Camp repository format

This describes the planned camp repository format.

Overall format

The camp repo info is in the _camp subdirectory, which looks like this:

_camp/
    primary/
    secondary/
    settings/

We will now discuss each subdirectory in turn.

Primary

The primary directory contains everything that remote users of this repository need to know, i.e. it contains what you need to know in order to get the repo, pull from it or push or send to it.

_camp/primary/
    format
    inventory
    <files referred to by inventory, possibly in subdirectories>

format contains the version number (in the Data.Version sense) of the primary format. If you don't understand the version then you can't use the repository.

Each line of inventory is of the format

name file offset length

where name is the name of a patch in the repository. The context of this patch is the set of patch names in earlier lines of the file. The representation of the patch is in file, from byte offset to byte offset + length.

Note that the inventory file must be updated atomically, as people doing a get or pull (who may not have perms to lock the repo, or may even by accessing the repo over HTTP) need to get a consistent view of the repo when they download it. It would be possible to avoid having to rewrite the whole inventory file in the common append-only case, by having a repository file that contains the inventory filename and its size. Then appends could be done by appending to the inventory file followed by rewriting the repository file, and other operations (e.g. unpull) would write a new inventory file and then rewrite the repository file. However, for now at least, we keep it simple.

The other files in this directory contain the patches pointed to by the inventory. Some files, or parts of some files, may not be references by the current inventory. However, we cannot remove files when we stop using them, as other people may be in the middle of a get, and thus may have an inventory that refers to them.

This format allows for the simple "each patch in its own file" approach, but this wastes disk space and gives slow access times. Alternatively you can concatenate all of the patches and put them in a single file, with the inventory giving you the offsets at which you can find each patch. Or you can go for some sort of hybrid solution, e.g. splitting patches into files based on what tags they are part of, or making sure that each file is a certain size or contains a certain number of patches.

Secondary

The secondary directory contains other information about the repo, which may be necessary for other commands.

_camp/secondary/
    format
    pristine/
    modification_times

Again there is a version number in format. However, in this case, if you don't understand that version then it is guaranteed to be safe to remove the whole secondary and recreate it, as if you had just done a get of the primary directory.

In the pristine directory is a copy of what the repo looks like after applying all the patches in the inventory. The directory can optionally not have the read permission bit set, so programs cannot easily accidentally descend into it and alter the files there.

The modification_times file is a list of \NUL-separated fields, each of the format maybe_time filename, where maybe_time is the modification time of filename if we believe it is up-to-date in the repository, and the empty string otherwise. This is so that record can be implemented efficiently.

Settings

The settings directory contains user settings, e.g. the default author to use.

Camp file-repository format

Camp also supports a second repository format, where the repository (or, more commonly, a partial repository) is contained in a single file. These repositories, once created, are read-only.

The reason that this is useful is for the "camp send" command. Rather than, as in darcs, having a separate concept of a "patch bundle", and a separate "camp apply" function to apply them, we can just use the "camp pull" command. We get the interactive patch selection etc for free.

The benefits are slightly greater for camp than they would be for darcs, as camp cannot parse a readable patch format. Therefore, it is highly desirable that the command for applying sent patches allows you to look at them first. Of course, the "apply" command could be made to allow this, but reusing the "pull" command which already does is simpler.

An unintended side-effect is that this provides a way to pack an entire repository into a read-only single file repo, by sending to the empty repo. I don't know of a good use for this at the moment, but it sounds like it might be handy.

The repo format is a concatenation of a repo format marker, a sequence of names (required to already exist in the repository you are pulling into), an inventory (with a slightly different line format, as the file containing the patches is the current file, whose name we don't know), and the patches.