Git fork
at reftables-rust 179 lines 4.3 kB view raw
1#define DISABLE_SIGN_COMPARE_WARNINGS 2 3#include "git-compat-util.h" 4#include "dir.h" 5#include "hash.h" 6#include "read-cache.h" 7#include "resolve-undo.h" 8#include "sparse-index.h" 9#include "string-list.h" 10 11/* The only error case is to run out of memory in string-list */ 12void record_resolve_undo(struct index_state *istate, struct cache_entry *ce) 13{ 14 struct string_list_item *lost; 15 struct resolve_undo_info *ui; 16 struct string_list *resolve_undo; 17 int stage = ce_stage(ce); 18 19 if (!stage) 20 return; 21 22 if (!istate->resolve_undo) { 23 CALLOC_ARRAY(resolve_undo, 1); 24 resolve_undo->strdup_strings = 1; 25 istate->resolve_undo = resolve_undo; 26 } 27 resolve_undo = istate->resolve_undo; 28 lost = string_list_insert(resolve_undo, ce->name); 29 if (!lost->util) 30 lost->util = xcalloc(1, sizeof(*ui)); 31 ui = lost->util; 32 oidcpy(&ui->oid[stage - 1], &ce->oid); 33 ui->mode[stage - 1] = ce->ce_mode; 34} 35 36void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo, 37 const struct git_hash_algo *algop) 38{ 39 struct string_list_item *item; 40 for_each_string_list_item(item, resolve_undo) { 41 struct resolve_undo_info *ui = item->util; 42 int i; 43 44 if (!ui) 45 continue; 46 strbuf_addstr(sb, item->string); 47 strbuf_addch(sb, 0); 48 for (i = 0; i < 3; i++) 49 strbuf_addf(sb, "%o%c", ui->mode[i], 0); 50 for (i = 0; i < 3; i++) { 51 if (!ui->mode[i]) 52 continue; 53 strbuf_add(sb, ui->oid[i].hash, algop->rawsz); 54 } 55 } 56} 57 58struct string_list *resolve_undo_read(const char *data, unsigned long size, 59 const struct git_hash_algo *algop) 60{ 61 struct string_list *resolve_undo; 62 size_t len; 63 char *endptr; 64 int i; 65 const unsigned rawsz = algop->rawsz; 66 67 CALLOC_ARRAY(resolve_undo, 1); 68 resolve_undo->strdup_strings = 1; 69 70 while (size) { 71 struct string_list_item *lost; 72 struct resolve_undo_info *ui; 73 74 len = strlen(data) + 1; 75 if (size <= len) 76 goto error; 77 lost = string_list_insert(resolve_undo, data); 78 if (!lost->util) 79 lost->util = xcalloc(1, sizeof(*ui)); 80 ui = lost->util; 81 size -= len; 82 data += len; 83 84 for (i = 0; i < 3; i++) { 85 ui->mode[i] = strtoul(data, &endptr, 8); 86 if (!endptr || endptr == data || *endptr) 87 goto error; 88 len = (endptr + 1) - (char*)data; 89 if (size <= len) 90 goto error; 91 size -= len; 92 data += len; 93 } 94 95 for (i = 0; i < 3; i++) { 96 if (!ui->mode[i]) 97 continue; 98 if (size < rawsz) 99 goto error; 100 oidread(&ui->oid[i], (const unsigned char *)data, algop); 101 size -= rawsz; 102 data += rawsz; 103 } 104 } 105 return resolve_undo; 106 107error: 108 string_list_clear(resolve_undo, 1); 109 error("Index records invalid resolve-undo information"); 110 return NULL; 111} 112 113void resolve_undo_clear_index(struct index_state *istate) 114{ 115 struct string_list *resolve_undo = istate->resolve_undo; 116 if (!resolve_undo) 117 return; 118 string_list_clear(resolve_undo, 1); 119 free(resolve_undo); 120 istate->resolve_undo = NULL; 121 istate->cache_changed |= RESOLVE_UNDO_CHANGED; 122} 123 124int unmerge_index_entry(struct index_state *istate, const char *path, 125 struct resolve_undo_info *ru, unsigned ce_flags) 126{ 127 int i = index_name_pos(istate, path, strlen(path)); 128 129 if (i < 0) { 130 /* unmerged? */ 131 i = -i - 1; 132 if (i < istate->cache_nr && 133 !strcmp(istate->cache[i]->name, path)) 134 /* yes, it is already unmerged */ 135 return 0; 136 /* fallthru: resolved to removal */ 137 } else { 138 /* merged - remove it to replace it with unmerged entries */ 139 remove_index_entry_at(istate, i); 140 } 141 142 for (i = 0; i < 3; i++) { 143 struct cache_entry *ce; 144 if (!ru->mode[i]) 145 continue; 146 ce = make_cache_entry(istate, ru->mode[i], &ru->oid[i], 147 path, i + 1, 0); 148 ce->ce_flags |= ce_flags; 149 if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD)) 150 return error("cannot unmerge '%s'", path); 151 } 152 return 0; 153} 154 155void unmerge_index(struct index_state *istate, const struct pathspec *pathspec, 156 unsigned ce_flags) 157{ 158 struct string_list_item *item; 159 160 if (!istate->resolve_undo) 161 return; 162 163 /* TODO: audit for interaction with sparse-index. */ 164 ensure_full_index(istate); 165 166 for_each_string_list_item(item, istate->resolve_undo) { 167 const char *path = item->string; 168 struct resolve_undo_info *ru = item->util; 169 if (!item->util) 170 continue; 171 if (!match_pathspec(istate, pathspec, 172 item->string, strlen(item->string), 173 0, NULL, 0)) 174 continue; 175 unmerge_index_entry(istate, path, ru, ce_flags); 176 free(ru); 177 item->util = NULL; 178 } 179}