/// import type { ContextTimed } from '@matrixai/contexts'; import type { CapabilityList, ObjectId, ObjectIdList } from './types.js'; import type { EncryptedFS } from 'encryptedfs'; import { Buffer } from 'buffer'; /** * Reference discovery * Notes: * * Server SHOULD terminate each non-flush line using LF ("\n") terminator; * client MUST NOT complain if there is no terminator. * * The returned response is a pkt-line stream describing each ref and its current value. * The stream MUST be sorted by name according to the C locale ordering. * * If HEAD is a valid ref, HEAD MUST appear as the first advertised ref. * If HEAD is not a valid ref, HEAD MUST NOT appear in the advertisement list at all, but other refs may still appear. * * The stream MUST include capability declarations behind a NUL on the first ref. * The peeled value of a ref (that is "ref^{}") MUST be immediately after the ref itself, if presented. * A conforming server MUST peel the ref if it’s an annotated tag. * * advertised-refs = (no-refs / list-of-refs) * *shallow * flush-pkt * * no-refs = PKT-LINE(zero-id SP "capabilities^{}" * NUL capability-list LF) * * list-of-refs = first-ref *other-ref * first-ref = PKT-LINE(obj-id SP refname * NUL capability-list LF) * * other-ref = PKT-LINE(other-tip / other-peeled) * other-tip = obj-id SP refname LF * other-peeled = obj-id SP refname "^{}" LF * * shallow = PKT-LINE("shallow" SP obj-id) * * capability-list = capability *(SP capability) * capability = 1*(LC_ALPHA / DIGIT / "-" / "_") * LC_ALPHA = %x61-7A */ /** * this is the main method for generating the smart HTTP response for the reference discovery phase. * The server advertises the available references * * Servers MUST terminate the response with the magic 0000 end pkt-line marker. * * The returned response is a pkt-line stream describing each ref and its known value. The stream SHOULD be sorted by * name according to the C locale ordering. The stream SHOULD include the default ref named HEAD as the first ref. * The stream MUST include capability declarations behind a NUL on the first ref. * * ``` * Smart_reply = PKT-LINE("# service=$servicename" LF) * "0000" * *1("version 1") * ref_list * "0000" * ``` * * `referenceList` is called for generating the `ref_list` stage. */ declare function advertiseRefGenerator({ efs, dir, gitDir, }: { efs: EncryptedFS; dir: string; gitDir: string; }, ctx: ContextTimed): AsyncGenerator; /** * This will take a raw line and encode it as the pkt-line format. * It adds a 4 byte length indicator to the beginning of a line. * If a chanel is specified a chanel byte is appended just after the length indicator. * * ``` * pkt-line = data-pkt / flush-pkt * data-pkt = pkt-len pkt-payload * pkt-len = 4*(HEXDIG) * pkt-payload = (pkt-len - 4)*(OCTET) * ``` */ declare function packetLineBuffer(line: Buffer, channel?: 1 | 2 | 3): Buffer; /** * This parses the clients request into a list of `wants', 'haves', and capabilities. * 'wants' indicate objects that the client found and wants from the reference discovery phase. Generally this will be * list of objects that references point to. It will not include all objects within that reference's branch. * 'haves' indicate objects that the client has and doesn't need sent over by the server. It's used by the sever to * decide which objects to send. * `capabilities` is a list of features the client wants. In our simplified implementation, none of these are really * used since we default to just handling `side-band-64k` for sending data. In the future we'll have to support the * capability for the client to push data. * * Clients MUST NOT reuse or revalidate a cached response. Servers MUST include sufficient Cache-Control headers to * prevent caching of the response. * * Servers SHOULD support all capabilities defined here. * * Clients MUST send at least one "want" command in the request body. Clients MUST NOT reference an id in a "want" * command which did not appear in the response obtained through ref discovery unless the server advertises capability * allow-tip-sha1-in-want or allow-reachable-sha1-in-want. * * ``` * compute_request = want_list * have_list * request_end * request_end = "0000" / "done" * want_list = PKT-LINE(want SP cap_list LF) * *(want_pkt) * want_pkt = PKT-LINE(want LF) * want = "want" SP id * cap_list = capability *(SP capability) * have_list = *PKT-LINE("have" SP id LF) * ``` * * @returns [wants, haves, capabilities] */ declare function parsePackRequest(body: Array): Promise<[ObjectIdList, ObjectIdList, CapabilityList]>; /** * This is the main method for handing the packfile-send stage of the http protocol. * It parses the http body send by the client into a list of `wants` and `haves` using `parsePackRequest`. It then * uses these lists to walk the git datastructures to decide which objects to send back to the client. * It does this by using `listObjects` to get all the relevant objects and `generatePackData` to generate the packfile * part of the response. * * It will respond with the `PKT-LINE(NAK_BUFFER)` and then the `packFile` data chunked into lines for the stream. * */ declare function generatePackRequest({ efs, dir, gitDir, body, }: { efs: EncryptedFS; dir: string; gitDir: string; body: Array; }, ctx: ContextTimed): AsyncGenerator; /** * Called by `generatePackRequest` to generate the `PackFile` data lines as part of the pack response stage. * Uses `isomorphic-git` to generate the `packFile` data using the provided list of `ObjectIds`. * The `packFile` is chunked into the `packetLineBuffer` with the size defined by `chunkSize`. * */ declare function generatePackData({ efs, dir, gitDir, objectIds, chunkSize, }: { efs: EncryptedFS; dir: string; gitDir: string; objectIds: Array; chunkSize?: number; }, ctx: ContextTimed): AsyncGenerator; export { advertiseRefGenerator, packetLineBuffer, parsePackRequest, generatePackRequest, generatePackData, };