change: initial work on decoding hunks

laumann
Oct 7, 2022, 2:34 PM
JAGXXSR7DR5FG77VKBF62BW7Q3JMVHCLHF4VB2PSLIZF4RLE553QC

Dependencies

  • [2] FMYCPGKD change: extract hash list decoding into reused function
  • [3] LMUBFPDX build.ninja: group build targets by vendor/non-vendor
  • [4] YG4DZB3A add representation of hash, decode dependencies
  • [5] ZYOEB24J add build.ninja, adjust Makefile
  • [6] 4RYULBDD bincode: introduce a bincode_state struct
  • [7] Y26WT3ZF change: decode message, description and timestamp
  • [8] QYRJIOYP change: separate decoding and printing of hashed struct
  • [9] IS5A7VT6 change: print hashes
  • [10] LVX6U4EK change: decode metadata bytes
  • [11] XTKRT6OQ format the codebase
  • [*] PEUS54XQ
  • [*] Q7TKZCJP Add initial support for reading the offsets from a (fixed) change
  • [*] OBKF6SII change: decompress the hashed section too

Change contents

  • file addition: vertex.h (----------)
    [13.1]
    #ifndef ANI_VERTEX_H
    #define ANI_VERTEX_H
    /**
    * Position of a byte within a change.
    */
    typedef uint64_t change_position;
    #define CHANGE_POSITION_ROOT ((change_position)0)
    #define CHANGE_POSITION_BOTTOM ((change_position)1)
    /**
    * A byte identifier, a change together with a position
    *
    * Variants observed:
    * - Hash
    * - Option<Hash>
    * - ChangeId
    */
    struct position {};
    /**
    * A node in the repository graph, made of a change internal identifier, and a
    * line identifier in that change.
    */
    struct vertex {
    void *change;
    change_position start, end; /* line identifier */
    };
    #endif
  • file addition: hunk.h (----------)
    [13.1]
    #ifndef ANI_HUNK_H
    #define ANI_HUNK_H
    struct local {
    char *path;
    };
    enum basehunk_type {
    FILE_MOVE,
    FILE_DEL,
    FILE_UNDEL,
    FILE_ADD,
    SOLVE_NAME_CONFLICT,
    UNSOLVE_NAME_CONFLICT,
    EDIT,
    REPLACEMENT,
    SOLVE_ORDER_CONFLICT,
    UNSOLVE_ORDER_CONFLICT,
    RESURRECT_ZOMBIES,
    ADD_ROOT,
    DEL_ROOT,
    };
    struct file_move {
    char *path;
    };
    struct edit {
    uint64_t atom;
    };
    struct replacement {
    uint64_t atom;
    uint64_t replacement;
    struct local local;
    };
    struct basehunk {
    enum basehunk_type hunk_type;
    union {
    struct file_move file_move;
    struct edit edit;
    struct replacement replacement;
    } hunk;
    };
    const char *hunk_basehunk_type_str(enum basehunk_type);
    #endif
  • file addition: hunk.c (----------)
    [13.1]
    #include <stdint.h>
    #include <stdlib.h>
    #include "hunk.h"
    const char *
    hunk_basehunk_type_str(enum basehunk_type hunk_type)
    {
    switch (hunk_type) {
    case FILE_MOVE:
    return "file move";
    case FILE_DEL:
    return "file del";
    case FILE_UNDEL:
    return "file undel";
    case FILE_ADD:
    return "file add";
    case SOLVE_NAME_CONFLICT:
    return "solve name conflict";
    case UNSOLVE_NAME_CONFLICT:
    return "unsolve name conflict";
    case EDIT:
    return "edit";
    case REPLACEMENT:
    return "replacement";
    case SOLVE_ORDER_CONFLICT:
    return "solve order conflict";
    case UNSOLVE_ORDER_CONFLICT:
    return "unsolve order conflict";
    case RESURRECT_ZOMBIES:
    return "resurrect zombies";
    case ADD_ROOT:
    return "add root";
    case DEL_ROOT:
    return "del root";
    default:
    abort();
    }
    }
  • edit in change.c at line 17
    [4.618]
    [15.0]
    #include "atom.h"
    #include "vertex.h"
    #include "hunk.h"
  • edit in change.c at line 182
    [2.583]
    [2.583]
    break;
    default:
    abort();
    }
    }
    }
    void
    change_decode_position(struct bincode_state *binstat)
    {
    uint64_t change_position; /* FIXME this should be its own type */
    if (bincode_getu8(binstat)) {
    struct hash hash;
    hash.variant = (uint8_t)bincode_getu32(binstat);
    switch (hash.variant) {
    case HASH_NONE:
    break;
    case HASH_BLAKE3:
    bincode_getbytes(
    binstat, (uint8_t *)hash.bytes, BLAKE3_BYTES
    );
    break;
    default:
    abort();
    }
    hash_print(&hash);
    }
    change_position = bincode_getu64(binstat);
    printf("ChangePosition(%lu)\n", change_position);
    }
    void
    change_decode_newedge(struct bincode_state *binstat)
    {
    uint8_t previous, flag;
    dump_buf("newedge", binstat->buf, binstat->avail);
    previous = bincode_getu8(binstat);
    flag = bincode_getu8(binstat);
    printf("previous = %u, flag = %u\n", previous, flag);
    /* TODO: It might be nice to be able to dump the flags? */
    /* from: Position<Change = Option<Hash>> */
    change_decode_position(binstat);
    /* to: V(Some(HASH)[range?]) */
    /* introduced_by: Option<Hash> */
    }
    void
    change_decode_atom(struct bincode_state *binstat)
    {
    uint64_t edges_len;
    int i;
    switch (bincode_getu32(binstat)) {
    case 0: /* NewVertex<Option<Hash>> */
    /* TODO */
    break;
    case 1:
    /* A list of edges */
    edges_len = bincode_getu64(binstat);
    printf("EdgeMap (%lu elements)\n", edges_len);
    for (i = 0; i < edges_len; i++) {
    change_decode_newedge(binstat);
    break; /* FIXME remove this */
    }
    /* A Position<Change = Option<Hash>> */
    break;
    default:
    abort();
    }
    }
    /**
    * Decode the hunks in a change
    */
    void
    change_decode_hunks(struct bincode_state *binstat)
    {
    uint64_t len;
    int i;
    len = bincode_getu64(binstat);
    for (i = 0; i < len; i++) {
    enum basehunk_type hunk_type = bincode_getu32(binstat);
    printf("%d. %s\n", i + 1, hunk_basehunk_type_str(hunk_type));
    switch (hunk_type) {
    case EDIT:
    printf("Edit. change: Atom, local: Local, encoding: Option<Encoding>\n"
    );
    change_decode_atom(binstat); /* the change field */
    /* change_decode_local */
    /* change_decode_encoding (maybe) */
    break;
    case REPLACEMENT:
    printf("Replacement. change: Atom, replacement: Atom, local: Local, encoding: Option<Encoding>\n"
    );
  • edit in change.c at line 285
    [2.604]
    [2.604]
    fprintf(stderr, "not yet implemented: %s\n",
    hunk_basehunk_type_str(hunk_type));
  • edit in change.c at line 289
    [2.620]
    [2.620]
    break; /* FIXME: Remove once full Hunk parsing is implemented */
  • replacement in change.c at line 391
    [4.76][4.76:128]()
    uint8_t *bytes = bincode_getbytes(&binstat, len);
    [4.76]
    [4.128]
    uint8_t *bytes = xmalloc(len);
    bincode_getbytes(&binstat, bytes, len);
  • edit in change.c at line 399
    [4.278]
    [4.278]
    change_decode_hunks(&binstat);
  • edit in build.ninja at line 24
    [3.114]
    [4.420]
    build hunk.o: cc hunk.c
  • replacement in build.ninja at line 35
    [4.998][3.115:192]()
    build ani: link ani.o init.o change.o bincode.o scaffold.o hash.o base32.o $
    [4.998]
    [3.192]
    build ani: link ani.o init.o change.o bincode.o scaffold.o hash.o base32.o hunk.o $
  • replacement in bincode.h at line 45
    [4.1120][4.304:363]()
    uint8_t *bincode_getbytes(struct bincode_state *, size_t);
    [4.1120]
    [4.2543]
    void bincode_getbytes(struct bincode_state *, uint8_t *, size_t);
  • replacement in bincode.c at line 82
    [4.367][4.367:377](),[4.377][4.2713:2767]()
    uint8_t *
    bincode_getbytes(struct bincode_state *s, size_t len)
    [4.367]
    [4.430]
    void
    bincode_getbytes(struct bincode_state *s, uint8_t *dest, size_t len)
  • replacement in bincode.c at line 85
    [4.432][4.432:497]()
    uint8_t *ret;
    ret = xmalloc(len);
    memcpy(ret, s->buf, len);
    [4.432]
    [4.497]
    memcpy(dest, s->buf, len);
  • edit in bincode.c at line 88
    [4.531][4.531:545]()
    return ret;
  • file addition: atom.h (----------)
    [13.1]
    #ifndef ANI_ATOM_H
    #define ANI_ATOM_H
    #define EDGE_FLAG_BLOCK 1
    #define EDGE_FLAG_PSEUDO 4
    #define EDGE_FLAG_FOLDER 16
    #define EDGE_FLAG_PARENT 32
    #define EDGE_FLAG_DELETED 128
    enum atom_type {
    NEW_VERTEX,
    EDGE_MAP
    };
    struct new_vertex {
    struct hash up_context; /* FIXME Option<Hash> */
    struct hash down_context;
    uint8_t flag; /* EDGE_FLAG_* */
    uint64_t start; /* start, end: ChangePosition = L64 */
    uint64_t end;
    /* FIXME inode: Position<Option<Hash>> = struct { change: Option<Hash>, pos: } */
    };
    struct atom {
    enum atom_type atom_type;
    union {
    struct new_vertex new_vertex;
    } atom;
    };
    #endif