histo-revisions v0.0.2
A database that tracks changing revisions of data.
Each revision is accessible through a unique ref which is based on a cryptographic hash of the data's content and history. A ref is similar to a git commit hash.
Each written data object is combined with a link to its ancestors - the combination is called a revision. A revision can be compared to a git commit object.
Revisions look like this:
{
  ancestors: ['someref'],
  data: 'some data'
}The cryptographic hash of the revision is its ref.
##Documentation
- revisions.createDB(opts) -> db
- db.put(data, [ancestorRefs], cb)
- db.get([ref], cb)
- db.head(cb) -> ref
- db.setHead(ref, [previousHead], cb)
- db.remoteHead(remoteName, cb)
- db.setRemoteHead(remoteName, ref, cb)
- db.refDifference(fromRef, toRef, cb)
- db.ancestors(ref, cb)
- db.commonAncestor(ref1, ref2, cb)
- db.createStream(refs) -> stream
- db.writeStream(stream, cb)
- revisions.createSynchronizer(sourceDB, targetDB) -> synchronizer
- synchronizer.run(cb)
- Merging synchronized data
###require('histo-revisions') -> revisions
{
  name: 'your-db-name', // will generate uuid if omitted
  revisionStore: revStore,
  branchStore: branchStore
}With revStore being an object with a content-addressable store interface:
- put(data, cb): should write some data and responds with a unique identifier of the data in the callback
- get(identifier, cb): should respond with the data in the callback
- del(identifier, cb): should delete the data for the specified identifier
branchStore is expected to be a simple key-value store interface:
- put(key, value, cb)
- get(key, cb)
- del(key, cb)
The difference is computed using the graph-difference module.
The common ancestor is computed using the ancestor module.
- name
- head(cb)
- refDifference(fromRef, toRef, cb)
- createStream(refs)->- stream
targetDB requires the following set of functions:
- head(cb)
- remoteHead(remoteName, cb)
- writeStream(stream, cb)
- setRemoteHead(remoteName, ref, cb)
function readRemoteRev(db, remoteName, cb) {
  db.remoteHead(remoteName, function(err, remoteHead) {
    db.get(remoteHead, function(err, remoteData) {
      cb(null, {head: remoteHead, data: remoteData});
    });
  });
}
function readLocalRev(db, cb) {
  db.head(function(err, localHead) {
    db.get(localHead, function(localData) {
      cb(null, {head: localHead, data: remoteData});
    });
  });
}
readRemoteRev(targetDB, 'your-remote-name', function(err, remoteRev) {
  readLocalRev(targetDB, function(err, localRev) {
    var mergedData = yourMergeFunction(remoteRev.data, localRev.data);
    var ancestors = [remoteRev.head, localRev.head];
    targetDB.put(mergedData, ancestors, function(err, mergedRef) {
      targetDB.setHead(mergedRef, localRev.head, function(err) {
        // on err repeat merging with new local head
      });
    });
  });
});##Todo
- list of remotes
- garbage collect history
##Contributors This project was created by Mirko Kiefer (@mirkokiefer).

