resolve-undo.con commit chainlint: match arbitrary here-docs tags rather than hard-coded names (c2c29cc)
   1#include "cache.h"
   2#include "dir.h"
   3#include "resolve-undo.h"
   4#include "string-list.h"
   5
   6/* The only error case is to run out of memory in string-list */
   7void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
   8{
   9        struct string_list_item *lost;
  10        struct resolve_undo_info *ui;
  11        struct string_list *resolve_undo;
  12        int stage = ce_stage(ce);
  13
  14        if (!stage)
  15                return;
  16
  17        if (!istate->resolve_undo) {
  18                resolve_undo = xcalloc(1, sizeof(*resolve_undo));
  19                resolve_undo->strdup_strings = 1;
  20                istate->resolve_undo = resolve_undo;
  21        }
  22        resolve_undo = istate->resolve_undo;
  23        lost = string_list_insert(resolve_undo, ce->name);
  24        if (!lost->util)
  25                lost->util = xcalloc(1, sizeof(*ui));
  26        ui = lost->util;
  27        oidcpy(&ui->oid[stage - 1], &ce->oid);
  28        ui->mode[stage - 1] = ce->ce_mode;
  29}
  30
  31void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo)
  32{
  33        struct string_list_item *item;
  34        for_each_string_list_item(item, resolve_undo) {
  35                struct resolve_undo_info *ui = item->util;
  36                int i;
  37
  38                if (!ui)
  39                        continue;
  40                strbuf_addstr(sb, item->string);
  41                strbuf_addch(sb, 0);
  42                for (i = 0; i < 3; i++)
  43                        strbuf_addf(sb, "%o%c", ui->mode[i], 0);
  44                for (i = 0; i < 3; i++) {
  45                        if (!ui->mode[i])
  46                                continue;
  47                        strbuf_add(sb, ui->oid[i].hash, the_hash_algo->rawsz);
  48                }
  49        }
  50}
  51
  52struct string_list *resolve_undo_read(const char *data, unsigned long size)
  53{
  54        struct string_list *resolve_undo;
  55        size_t len;
  56        char *endptr;
  57        int i;
  58        const unsigned rawsz = the_hash_algo->rawsz;
  59
  60        resolve_undo = xcalloc(1, sizeof(*resolve_undo));
  61        resolve_undo->strdup_strings = 1;
  62
  63        while (size) {
  64                struct string_list_item *lost;
  65                struct resolve_undo_info *ui;
  66
  67                len = strlen(data) + 1;
  68                if (size <= len)
  69                        goto error;
  70                lost = string_list_insert(resolve_undo, data);
  71                if (!lost->util)
  72                        lost->util = xcalloc(1, sizeof(*ui));
  73                ui = lost->util;
  74                size -= len;
  75                data += len;
  76
  77                for (i = 0; i < 3; i++) {
  78                        ui->mode[i] = strtoul(data, &endptr, 8);
  79                        if (!endptr || endptr == data || *endptr)
  80                                goto error;
  81                        len = (endptr + 1) - (char*)data;
  82                        if (size <= len)
  83                                goto error;
  84                        size -= len;
  85                        data += len;
  86                }
  87
  88                for (i = 0; i < 3; i++) {
  89                        if (!ui->mode[i])
  90                                continue;
  91                        if (size < rawsz)
  92                                goto error;
  93                        oidread(&ui->oid[i], (const unsigned char *)data);
  94                        size -= rawsz;
  95                        data += rawsz;
  96                }
  97        }
  98        return resolve_undo;
  99
 100error:
 101        string_list_clear(resolve_undo, 1);
 102        error("Index records invalid resolve-undo information");
 103        return NULL;
 104}
 105
 106void resolve_undo_clear_index(struct index_state *istate)
 107{
 108        struct string_list *resolve_undo = istate->resolve_undo;
 109        if (!resolve_undo)
 110                return;
 111        string_list_clear(resolve_undo, 1);
 112        free(resolve_undo);
 113        istate->resolve_undo = NULL;
 114        istate->cache_changed |= RESOLVE_UNDO_CHANGED;
 115}
 116
 117int unmerge_index_entry_at(struct index_state *istate, int pos)
 118{
 119        const struct cache_entry *ce;
 120        struct string_list_item *item;
 121        struct resolve_undo_info *ru;
 122        int i, err = 0, matched;
 123        char *name;
 124
 125        if (!istate->resolve_undo)
 126                return pos;
 127
 128        ce = istate->cache[pos];
 129        if (ce_stage(ce)) {
 130                /* already unmerged */
 131                while ((pos < istate->cache_nr) &&
 132                       ! strcmp(istate->cache[pos]->name, ce->name))
 133                        pos++;
 134                return pos - 1; /* return the last entry processed */
 135        }
 136        item = string_list_lookup(istate->resolve_undo, ce->name);
 137        if (!item)
 138                return pos;
 139        ru = item->util;
 140        if (!ru)
 141                return pos;
 142        matched = ce->ce_flags & CE_MATCHED;
 143        name = xstrdup(ce->name);
 144        remove_index_entry_at(istate, pos);
 145        for (i = 0; i < 3; i++) {
 146                struct cache_entry *nce;
 147                if (!ru->mode[i])
 148                        continue;
 149                nce = make_cache_entry(ru->mode[i], ru->oid[i].hash,
 150                                       name, i + 1, 0);
 151                if (matched)
 152                        nce->ce_flags |= CE_MATCHED;
 153                if (add_index_entry(istate, nce, ADD_CACHE_OK_TO_ADD)) {
 154                        err = 1;
 155                        error("cannot unmerge '%s'", name);
 156                }
 157        }
 158        free(name);
 159        if (err)
 160                return pos;
 161        free(ru);
 162        item->util = NULL;
 163        return unmerge_index_entry_at(istate, pos);
 164}
 165
 166void unmerge_marked_index(struct index_state *istate)
 167{
 168        int i;
 169
 170        if (!istate->resolve_undo)
 171                return;
 172
 173        for (i = 0; i < istate->cache_nr; i++) {
 174                const struct cache_entry *ce = istate->cache[i];
 175                if (ce->ce_flags & CE_MATCHED)
 176                        i = unmerge_index_entry_at(istate, i);
 177        }
 178}
 179
 180void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
 181{
 182        int i;
 183
 184        if (!istate->resolve_undo)
 185                return;
 186
 187        for (i = 0; i < istate->cache_nr; i++) {
 188                const struct cache_entry *ce = istate->cache[i];
 189                if (!ce_path_match(ce, pathspec, NULL))
 190                        continue;
 191                i = unmerge_index_entry_at(istate, i);
 192        }
 193}