Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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;
}