* Write-once store of files identified by globally-unique names (e.g. hashes or UUIDs). Simplest option is to just dump them in a directory. Optionally do delta-compression between similar/related files; or build this on top of deltas. * Tree manifests/inventories which say which files should be assembled at particular points to build a tree. These too can be stored indexed by hash. - Reconstruct a revision by pulling out the manifest and then all the individual files. - Manipulate working copy of inventory by add/mv/remove/commands. * Retrieve deltas - Calculate diffs between two file versions, just by getting them from the store. - Retrieve deltas between any two revisions: requires looking for changes to the structure of the tree, and then text changes for anything inside it. - Deltas may be either stored or calculated on demand. They can be put in the store just indexed by the from and to manifest id. - Calculate diff between a previous revision and the working copy. * Commit and retrieve revisions - Revisions hold metadata (date, committer, comment, optional parents, merged patches), and a pointer to the inventory. - Stored in a write-once store. * Branch holds a linear history of revisions. - This is mostly redundant; we could just remember the current base revision and walk backwards from there. But it still seems possibly useful to hold; we can check that the two are always consistent. (This suggests that we actually *could* do ``switch`` if we really wanted to, by replacing the revision history and head revision. But I don't think it's a good idea.) - Can add a new revision to the end. - By indexing into this can translate between 0-based revision numbers and revision ids. - By walking through and looking at revision dates can find revisions in a particular date range. * Calculations on branch histories: - Find if one branch is a prefix of another. - Find the latest common ancestor of another. * Three-way merge between revisions - Resolve shape of directory - Then resolve textual conflicts * Pull/push changes when they perfectly match - Possible when the destination is a prefix of the source - Just move all revisions, manifests and texts across, and * Merge all changes from one branch into another * Signatures applied to revisions - There is a separable module for checking a signature: this is passed the claimed author, changeset, date. This needs to fetch an appropriate key, decide if it is trusted to correspond to that author, is not revoked, etc. - If it is unknown, untrusted, revoked, etc, that is reported. Depending on a paranoia level it may cause the operation to abort.