Merge branch 'jk/output-prefix-cleanup'
[git/gitster.git] / resolve-undo.c
blob8c9911affbe409cdc635f7fd1270225c30a51236
1 #define USE_THE_REPOSITORY_VARIABLE
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)
38 struct string_list_item *item;
39 for_each_string_list_item(item, resolve_undo) {
40 struct resolve_undo_info *ui = item->util;
41 int i;
43 if (!ui)
44 continue;
45 strbuf_addstr(sb, item->string);
46 strbuf_addch(sb, 0);
47 for (i = 0; i < 3; i++)
48 strbuf_addf(sb, "%o%c", ui->mode[i], 0);
49 for (i = 0; i < 3; i++) {
50 if (!ui->mode[i])
51 continue;
52 strbuf_add(sb, ui->oid[i].hash, the_hash_algo->rawsz);
57 struct string_list *resolve_undo_read(const char *data, unsigned long size)
59 struct string_list *resolve_undo;
60 size_t len;
61 char *endptr;
62 int i;
63 const unsigned rawsz = the_hash_algo->rawsz;
65 CALLOC_ARRAY(resolve_undo, 1);
66 resolve_undo->strdup_strings = 1;
68 while (size) {
69 struct string_list_item *lost;
70 struct resolve_undo_info *ui;
72 len = strlen(data) + 1;
73 if (size <= len)
74 goto error;
75 lost = string_list_insert(resolve_undo, data);
76 if (!lost->util)
77 lost->util = xcalloc(1, sizeof(*ui));
78 ui = lost->util;
79 size -= len;
80 data += len;
82 for (i = 0; i < 3; i++) {
83 ui->mode[i] = strtoul(data, &endptr, 8);
84 if (!endptr || endptr == data || *endptr)
85 goto error;
86 len = (endptr + 1) - (char*)data;
87 if (size <= len)
88 goto error;
89 size -= len;
90 data += len;
93 for (i = 0; i < 3; i++) {
94 if (!ui->mode[i])
95 continue;
96 if (size < rawsz)
97 goto error;
98 oidread(&ui->oid[i], (const unsigned char *)data,
99 the_repository->hash_algo);
100 size -= rawsz;
101 data += rawsz;
104 return resolve_undo;
106 error:
107 string_list_clear(resolve_undo, 1);
108 error("Index records invalid resolve-undo information");
109 return NULL;
112 void resolve_undo_clear_index(struct index_state *istate)
114 struct string_list *resolve_undo = istate->resolve_undo;
115 if (!resolve_undo)
116 return;
117 string_list_clear(resolve_undo, 1);
118 free(resolve_undo);
119 istate->resolve_undo = NULL;
120 istate->cache_changed |= RESOLVE_UNDO_CHANGED;
123 int unmerge_index_entry(struct index_state *istate, const char *path,
124 struct resolve_undo_info *ru, unsigned ce_flags)
126 int i = index_name_pos(istate, path, strlen(path));
128 if (i < 0) {
129 /* unmerged? */
130 i = -i - 1;
131 if (i < istate->cache_nr &&
132 !strcmp(istate->cache[i]->name, path))
133 /* yes, it is already unmerged */
134 return 0;
135 /* fallthru: resolved to removal */
136 } else {
137 /* merged - remove it to replace it with unmerged entries */
138 remove_index_entry_at(istate, i);
141 for (i = 0; i < 3; i++) {
142 struct cache_entry *ce;
143 if (!ru->mode[i])
144 continue;
145 ce = make_cache_entry(istate, ru->mode[i], &ru->oid[i],
146 path, i + 1, 0);
147 ce->ce_flags |= ce_flags;
148 if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD))
149 return error("cannot unmerge '%s'", path);
151 return 0;
154 void unmerge_index(struct index_state *istate, const struct pathspec *pathspec,
155 unsigned ce_flags)
157 struct string_list_item *item;
159 if (!istate->resolve_undo)
160 return;
162 /* TODO: audit for interaction with sparse-index. */
163 ensure_full_index(istate);
165 for_each_string_list_item(item, istate->resolve_undo) {
166 const char *path = item->string;
167 struct resolve_undo_info *ru = item->util;
168 if (!item->util)
169 continue;
170 if (!match_pathspec(istate, pathspec,
171 item->string, strlen(item->string),
172 0, NULL, 0))
173 continue;
174 unmerge_index_entry(istate, path, ru, ce_flags);
175 free(ru);
176 item->util = NULL;