gitignore.txt: use backticks instead of double quotes
[git/debian.git] / resolve-undo.c
blob70a6db526d240da717aa7b926e10bbcddbe845a3
1 #include "cache.h"
2 #include "dir.h"
3 #include "hash.h"
4 #include "resolve-undo.h"
5 #include "string-list.h"
7 /* The only error case is to run out of memory in string-list */
8 void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
10 struct string_list_item *lost;
11 struct resolve_undo_info *ui;
12 struct string_list *resolve_undo;
13 int stage = ce_stage(ce);
15 if (!stage)
16 return;
18 if (!istate->resolve_undo) {
19 CALLOC_ARRAY(resolve_undo, 1);
20 resolve_undo->strdup_strings = 1;
21 istate->resolve_undo = resolve_undo;
23 resolve_undo = istate->resolve_undo;
24 lost = string_list_insert(resolve_undo, ce->name);
25 if (!lost->util)
26 lost->util = xcalloc(1, sizeof(*ui));
27 ui = lost->util;
28 oidcpy(&ui->oid[stage - 1], &ce->oid);
29 ui->mode[stage - 1] = ce->ce_mode;
32 void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo)
34 struct string_list_item *item;
35 for_each_string_list_item(item, resolve_undo) {
36 struct resolve_undo_info *ui = item->util;
37 int i;
39 if (!ui)
40 continue;
41 strbuf_addstr(sb, item->string);
42 strbuf_addch(sb, 0);
43 for (i = 0; i < 3; i++)
44 strbuf_addf(sb, "%o%c", ui->mode[i], 0);
45 for (i = 0; i < 3; i++) {
46 if (!ui->mode[i])
47 continue;
48 strbuf_add(sb, ui->oid[i].hash, the_hash_algo->rawsz);
53 struct string_list *resolve_undo_read(const char *data, unsigned long size)
55 struct string_list *resolve_undo;
56 size_t len;
57 char *endptr;
58 int i;
59 const unsigned rawsz = the_hash_algo->rawsz;
61 CALLOC_ARRAY(resolve_undo, 1);
62 resolve_undo->strdup_strings = 1;
64 while (size) {
65 struct string_list_item *lost;
66 struct resolve_undo_info *ui;
68 len = strlen(data) + 1;
69 if (size <= len)
70 goto error;
71 lost = string_list_insert(resolve_undo, data);
72 if (!lost->util)
73 lost->util = xcalloc(1, sizeof(*ui));
74 ui = lost->util;
75 size -= len;
76 data += len;
78 for (i = 0; i < 3; i++) {
79 ui->mode[i] = strtoul(data, &endptr, 8);
80 if (!endptr || endptr == data || *endptr)
81 goto error;
82 len = (endptr + 1) - (char*)data;
83 if (size <= len)
84 goto error;
85 size -= len;
86 data += len;
89 for (i = 0; i < 3; i++) {
90 if (!ui->mode[i])
91 continue;
92 if (size < rawsz)
93 goto error;
94 oidread(&ui->oid[i], (const unsigned char *)data);
95 size -= rawsz;
96 data += rawsz;
99 return resolve_undo;
101 error:
102 string_list_clear(resolve_undo, 1);
103 error("Index records invalid resolve-undo information");
104 return NULL;
107 void resolve_undo_clear_index(struct index_state *istate)
109 struct string_list *resolve_undo = istate->resolve_undo;
110 if (!resolve_undo)
111 return;
112 string_list_clear(resolve_undo, 1);
113 free(resolve_undo);
114 istate->resolve_undo = NULL;
115 istate->cache_changed |= RESOLVE_UNDO_CHANGED;
118 int unmerge_index_entry_at(struct index_state *istate, int pos)
120 const struct cache_entry *ce;
121 struct string_list_item *item;
122 struct resolve_undo_info *ru;
123 int i, err = 0, matched;
124 char *name;
126 if (!istate->resolve_undo)
127 return pos;
129 ce = istate->cache[pos];
130 if (ce_stage(ce)) {
131 /* already unmerged */
132 while ((pos < istate->cache_nr) &&
133 ! strcmp(istate->cache[pos]->name, ce->name))
134 pos++;
135 return pos - 1; /* return the last entry processed */
137 item = string_list_lookup(istate->resolve_undo, ce->name);
138 if (!item)
139 return pos;
140 ru = item->util;
141 if (!ru)
142 return pos;
143 matched = ce->ce_flags & CE_MATCHED;
144 name = xstrdup(ce->name);
145 remove_index_entry_at(istate, pos);
146 for (i = 0; i < 3; i++) {
147 struct cache_entry *nce;
148 if (!ru->mode[i])
149 continue;
150 nce = make_cache_entry(istate,
151 ru->mode[i],
152 &ru->oid[i],
153 name, i + 1, 0);
154 if (matched)
155 nce->ce_flags |= CE_MATCHED;
156 if (add_index_entry(istate, nce, ADD_CACHE_OK_TO_ADD)) {
157 err = 1;
158 error("cannot unmerge '%s'", name);
161 free(name);
162 if (err)
163 return pos;
164 free(ru);
165 item->util = NULL;
166 return unmerge_index_entry_at(istate, pos);
169 void unmerge_marked_index(struct index_state *istate)
171 int i;
173 if (!istate->resolve_undo)
174 return;
176 /* TODO: audit for interaction with sparse-index. */
177 ensure_full_index(istate);
178 for (i = 0; i < istate->cache_nr; i++) {
179 const struct cache_entry *ce = istate->cache[i];
180 if (ce->ce_flags & CE_MATCHED)
181 i = unmerge_index_entry_at(istate, i);
185 void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
187 int i;
189 if (!istate->resolve_undo)
190 return;
192 /* TODO: audit for interaction with sparse-index. */
193 ensure_full_index(istate);
194 for (i = 0; i < istate->cache_nr; i++) {
195 const struct cache_entry *ce = istate->cache[i];
196 if (!ce_path_match(istate, ce, pathspec, NULL))
197 continue;
198 i = unmerge_index_entry_at(istate, i);