The fifth batch
[alt-git.git] / resolve-undo.c
blob52c45e5a49463656a48fc036749ee2749debaaac
1 #define DISABLE_SIGN_COMPARE_WARNINGS
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"
11 /* The only error case is to run out of memory in string-list */
12 void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
14 struct string_list_item *lost;
15 struct resolve_undo_info *ui;
16 struct string_list *resolve_undo;
17 int stage = ce_stage(ce);
19 if (!stage)
20 return;
22 if (!istate->resolve_undo) {
23 CALLOC_ARRAY(resolve_undo, 1);
24 resolve_undo->strdup_strings = 1;
25 istate->resolve_undo = resolve_undo;
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;
36 void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo,
37 const struct git_hash_algo *algop)
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;
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);
58 struct string_list *resolve_undo_read(const char *data, unsigned long size,
59 const struct git_hash_algo *algop)
61 struct string_list *resolve_undo;
62 size_t len;
63 char *endptr;
64 int i;
65 const unsigned rawsz = algop->rawsz;
67 CALLOC_ARRAY(resolve_undo, 1);
68 resolve_undo->strdup_strings = 1;
70 while (size) {
71 struct string_list_item *lost;
72 struct resolve_undo_info *ui;
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;
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;
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;
105 return resolve_undo;
107 error:
108 string_list_clear(resolve_undo, 1);
109 error("Index records invalid resolve-undo information");
110 return NULL;
113 void resolve_undo_clear_index(struct index_state *istate)
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;
124 int unmerge_index_entry(struct index_state *istate, const char *path,
125 struct resolve_undo_info *ru, unsigned ce_flags)
127 int i = index_name_pos(istate, path, strlen(path));
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);
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);
152 return 0;
155 void unmerge_index(struct index_state *istate, const struct pathspec *pathspec,
156 unsigned ce_flags)
158 struct string_list_item *item;
160 if (!istate->resolve_undo)
161 return;
163 /* TODO: audit for interaction with sparse-index. */
164 ensure_full_index(istate);
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;