DNAR format
The DNAR format is specified using Protobuf.
syntax = "proto3";
package dnar;
option go_package = "github.com/adisbladis/deltanar/dnar";
// Protocol specification for the DeltaNAR format
//
// The DeltaNAR protocol:
// 1. A StreamHeader(len(nar))
// 2. Multiple NAR
// 3. A StreamHeader(len(caChunks))
// 4. Multiple CAChunk
// 5. A PathTrailer
// Sent before a stream of other messages indicating how many messages will follow
message StreamHeader {
uint64 length = 1;
}
// A file being used as an input to write another file
message FileDescriptor {
uint32 store_path = 1; // Store path offset in DnarHeader.paths
string path = 2;
}
// A content addressed chunk
message CAChunk {
bytes data = 1;
}
// A file within a NAR
message NarFile {
string path = 1;
message ChunkDescriptor {
oneof chunk_type {
// Read from CA chunk
CAChunk ca = 1;
// Read from file descriptor
FDChunk fd = 2;
// Reconstruct from a delta against an existing base chunk
DeltaChunk delta = 4;
}
message CAChunk {
uint64 index = 1; // CA chunk index in chunk stream to read from
}
message FDChunk {
uint64 index = 1; // File descriptor index in DnarHeader.files to read from
uint64 size = 2;
uint64 offset = 3;
bytes digest = 4; // Chunk digest (verify that existing store contents match)
}
// A chunk that's not present on the target but can be reconstructed from a binary delta.
message DeltaChunk {
uint64 index = 1; // File descriptor index in DnarHeader.files
uint64 size = 2;
uint64 offset = 3;
bytes digest = 4;
uint64 delta_index = 5; // CA chunk index in the chunk stream holding the delta payload
uint64 result_size = 6; // Size of the reconstructed chunk
}
}
oneof file_type {
RegularFile regular = 2;
DirectoryFile directory = 3;
SymlinkFile symlink = 4;
}
message RegularFile {
uint64 size = 1;
repeated ChunkDescriptor chunks = 2;
bool executable = 3;
}
message DirectoryFile {
// If a directory hash was matched copy the directory from here
// Note that unlike the chunk index this is an _int64_ where a -1 signifies
// that the directory does _not_ already exist on the remote.
int64 from = 1;
}
message SymlinkFile {
string target = 1;
}
}
// Top level file header
message PathTrailer {
repeated string paths = 1;
repeated FileDescriptor files = 2;
}
// NAR
message NAR {
// Core data fields
string path = 1;
repeated NarFile files = 2;
// Narinfo metadata (extracted from local store using nix path-info --json)
string narHash = 3;
uint64 narSize = 4;
repeated string references = 5;
}