86e8547ca25c72f0cce5a4ca2780a3f93dac33ae
   1#include "cache.h"
   2#include "resolve-undo.h"
   3#include "string-list.h"
   4
   5/* The only error case is to run out of memory in string-list */
   6void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
   7{
   8        struct string_list_item *lost;
   9        struct resolve_undo_info *ui;
  10        struct string_list *resolve_undo;
  11        int stage = ce_stage(ce);
  12
  13        if (!stage)
  14                return;
  15
  16        if (!istate->resolve_undo) {
  17                resolve_undo = xcalloc(1, sizeof(*resolve_undo));
  18                resolve_undo->strdup_strings = 1;
  19                istate->resolve_undo = resolve_undo;
  20        }
  21        resolve_undo = istate->resolve_undo;
  22        lost = string_list_insert(ce->name, resolve_undo);
  23        if (!lost->util)
  24                lost->util = xcalloc(1, sizeof(*ui));
  25        ui = lost->util;
  26        hashcpy(ui->sha1[stage - 1], ce->sha1);
  27        ui->mode[stage - 1] = ce->ce_mode;
  28}
  29
  30static int write_one(struct string_list_item *item, void *cbdata)
  31{
  32        struct strbuf *sb = cbdata;
  33        struct resolve_undo_info *ui = item->util;
  34        int i;
  35
  36        if (!ui)
  37                return 0;
  38        strbuf_addstr(sb, item->string);
  39        strbuf_addch(sb, 0);
  40        for (i = 0; i < 3; i++)
  41                strbuf_addf(sb, "%o%c", ui->mode[i], 0);
  42        for (i = 0; i < 3; i++) {
  43                if (!ui->mode[i])
  44                        continue;
  45                strbuf_add(sb, ui->sha1[i], 20);
  46        }
  47        return 0;
  48}
  49
  50void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo)
  51{
  52        for_each_string_list(write_one, resolve_undo, sb);
  53}
  54
  55struct string_list *resolve_undo_read(void *data, unsigned long size)
  56{
  57        struct string_list *resolve_undo;
  58        size_t len;
  59        char *endptr;
  60        int i;
  61
  62        resolve_undo = xcalloc(1, sizeof(*resolve_undo));
  63        resolve_undo->strdup_strings = 1;
  64
  65        while (size) {
  66                struct string_list_item *lost;
  67                struct resolve_undo_info *ui;
  68
  69                len = strlen(data) + 1;
  70                if (size <= len)
  71                        goto error;
  72                lost = string_list_insert(data, resolve_undo);
  73                if (!lost->util)
  74                        lost->util = xcalloc(1, sizeof(*ui));
  75                ui = lost->util;
  76                size -= len;
  77                data += len;
  78
  79                for (i = 0; i < 3; i++) {
  80                        ui->mode[i] = strtoul(data, &endptr, 8);
  81                        if (!endptr || endptr == data || *endptr)
  82                                goto error;
  83                        len = (endptr + 1) - (char*)data;
  84                        if (size <= len)
  85                                goto error;
  86                        size -= len;
  87                        data += len;
  88                }
  89
  90                for (i = 0; i < 3; i++) {
  91                        if (!ui->mode[i])
  92                                continue;
  93                        if (size < 20)
  94                                goto error;
  95                        hashcpy(ui->sha1[i], data);
  96                        size -= 20;
  97                        data += 20;
  98                }
  99        }
 100        return resolve_undo;
 101
 102error:
 103        string_list_clear(resolve_undo, 1);
 104        error("Index records invalid resolve-undo information");
 105        return NULL;
 106}
 107
 108void resolve_undo_clear_index(struct index_state *istate)
 109{
 110        struct string_list *resolve_undo = istate->resolve_undo;
 111        if (!resolve_undo)
 112                return;
 113        string_list_clear(resolve_undo, 1);
 114        free(resolve_undo);
 115        istate->resolve_undo = NULL;
 116        istate->cache_changed = 1;
 117}