resolve-undo.con commit Merge branch 'jk/cached-commit-buffer' into maint (393eee1)
   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        hashcpy(ui->sha1[stage - 1], ce->oid.hash);
  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->sha1[i], 20);
  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
  59        resolve_undo = xcalloc(1, sizeof(*resolve_undo));
  60        resolve_undo->strdup_strings = 1;
  61
  62        while (size) {
  63                struct string_list_item *lost;
  64                struct resolve_undo_info *ui;
  65
  66                len = strlen(data) + 1;
  67                if (size <= len)
  68                        goto error;
  69                lost = string_list_insert(resolve_undo, data);
  70                if (!lost->util)
  71                        lost->util = xcalloc(1, sizeof(*ui));
  72                ui = lost->util;
  73                size -= len;
  74                data += len;
  75
  76                for (i = 0; i < 3; i++) {
  77                        ui->mode[i] = strtoul(data, &endptr, 8);
  78                        if (!endptr || endptr == data || *endptr)
  79                                goto error;
  80                        len = (endptr + 1) - (char*)data;
  81                        if (size <= len)
  82                                goto error;
  83                        size -= len;
  84                        data += len;
  85                }
  86
  87                for (i = 0; i < 3; i++) {
  88                        if (!ui->mode[i])
  89                                continue;
  90                        if (size < 20)
  91                                goto error;
  92                        hashcpy(ui->sha1[i], (const unsigned char *)data);
  93                        size -= 20;
  94                        data += 20;
  95                }
  96        }
  97        return resolve_undo;
  98
  99error:
 100        string_list_clear(resolve_undo, 1);
 101        error("Index records invalid resolve-undo information");
 102        return NULL;
 103}
 104
 105void resolve_undo_clear_index(struct index_state *istate)
 106{
 107        struct string_list *resolve_undo = istate->resolve_undo;
 108        if (!resolve_undo)
 109                return;
 110        string_list_clear(resolve_undo, 1);
 111        free(resolve_undo);
 112        istate->resolve_undo = NULL;
 113        istate->cache_changed |= RESOLVE_UNDO_CHANGED;
 114}
 115
 116int unmerge_index_entry_at(struct index_state *istate, int pos)
 117{
 118        const struct cache_entry *ce;
 119        struct string_list_item *item;
 120        struct resolve_undo_info *ru;
 121        int i, err = 0, matched;
 122        char *name;
 123
 124        if (!istate->resolve_undo)
 125                return pos;
 126
 127        ce = istate->cache[pos];
 128        if (ce_stage(ce)) {
 129                /* already unmerged */
 130                while ((pos < istate->cache_nr) &&
 131                       ! strcmp(istate->cache[pos]->name, ce->name))
 132                        pos++;
 133                return pos - 1; /* return the last entry processed */
 134        }
 135        item = string_list_lookup(istate->resolve_undo, ce->name);
 136        if (!item)
 137                return pos;
 138        ru = item->util;
 139        if (!ru)
 140                return pos;
 141        matched = ce->ce_flags & CE_MATCHED;
 142        name = xstrdup(ce->name);
 143        remove_index_entry_at(istate, pos);
 144        for (i = 0; i < 3; i++) {
 145                struct cache_entry *nce;
 146                if (!ru->mode[i])
 147                        continue;
 148                nce = make_cache_entry(ru->mode[i], ru->sha1[i],
 149                                       name, i + 1, 0);
 150                if (matched)
 151                        nce->ce_flags |= CE_MATCHED;
 152                if (add_index_entry(istate, nce, ADD_CACHE_OK_TO_ADD)) {
 153                        err = 1;
 154                        error("cannot unmerge '%s'", name);
 155                }
 156        }
 157        free(name);
 158        if (err)
 159                return pos;
 160        free(ru);
 161        item->util = NULL;
 162        return unmerge_index_entry_at(istate, pos);
 163}
 164
 165void unmerge_marked_index(struct index_state *istate)
 166{
 167        int i;
 168
 169        if (!istate->resolve_undo)
 170                return;
 171
 172        for (i = 0; i < istate->cache_nr; i++) {
 173                const struct cache_entry *ce = istate->cache[i];
 174                if (ce->ce_flags & CE_MATCHED)
 175                        i = unmerge_index_entry_at(istate, i);
 176        }
 177}
 178
 179void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
 180{
 181        int i;
 182
 183        if (!istate->resolve_undo)
 184                return;
 185
 186        for (i = 0; i < istate->cache_nr; i++) {
 187                const struct cache_entry *ce = istate->cache[i];
 188                if (!ce_path_match(ce, pathspec, NULL))
 189                        continue;
 190                i = unmerge_index_entry_at(istate, i);
 191        }
 192}