Skip to content

Commit 5bdedac

Browse files
committed
checkout: allow "checkout -m path" to unmerge removed paths
"git checkout -m -- path" uses the unmerge_marked_index() API, whose implementation is incapable of unresolving a path that was resolved as removed. Extend the unmerge_index() API function so that we can mark the ce_flags member of the cache entries we add to the index as unmerged, and replace use of unmerge_marked_index() with it. Now, together with its unmerge_index_entry_at() helper function, unmerge_marked_index() function is no longer called by anybody, and can safely be removed. This makes two known test failures in t2070 and t7201 to succeed. Signed-off-by: Junio C Hamano <[email protected]>
1 parent ed3789f commit 5bdedac

File tree

7 files changed

+13
-82
lines changed

7 files changed

+13
-82
lines changed

builtin/checkout.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,8 @@ static int checkout_paths(const struct checkout_opts *opts,
566566

567567
if (opts->source_tree)
568568
read_tree_some(opts->source_tree, &opts->pathspec);
569+
if (opts->merge)
570+
unmerge_index(&the_index, &opts->pathspec, CE_MATCHED);
569571

570572
ps_matched = xcalloc(opts->pathspec.nr, 1);
571573

@@ -589,10 +591,6 @@ static int checkout_paths(const struct checkout_opts *opts,
589591
}
590592
free(ps_matched);
591593

592-
/* "checkout -m path" to recreate conflicted state */
593-
if (opts->merge)
594-
unmerge_marked_index(&the_index);
595-
596594
/* Any unmerged paths? */
597595
for (pos = 0; pos < the_index.cache_nr; pos++) {
598596
const struct cache_entry *ce = the_index.cache[pos];

builtin/update-index.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ static int unresolve_one(const char *path)
646646
item = string_list_lookup(the_index.resolve_undo, path);
647647
if (!item)
648648
return res; /* no resolve-undo record for the path */
649-
res = unmerge_index_entry(&the_index, path, item->util);
649+
res = unmerge_index_entry(&the_index, path, item->util, 0);
650650
FREE_AND_NULL(item->util);
651651
return res;
652652
}

rerere.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ int rerere_forget(struct repository *r, struct pathspec *pathspec)
11121112
* recover the original conflicted state and then
11131113
* find the conflicted paths.
11141114
*/
1115-
unmerge_index(r->index, pathspec);
1115+
unmerge_index(r->index, pathspec, 0);
11161116
find_conflict(r, &conflict);
11171117
for (i = 0; i < conflict.nr; i++) {
11181118
struct string_list_item *it = &conflict.items[i];

resolve-undo.c

Lines changed: 5 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -115,75 +115,8 @@ void resolve_undo_clear_index(struct index_state *istate)
115115
istate->cache_changed |= RESOLVE_UNDO_CHANGED;
116116
}
117117

118-
int unmerge_index_entry_at(struct index_state *istate, int pos)
119-
{
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;
125-
126-
if (!istate->resolve_undo)
127-
return pos;
128-
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 */
136-
}
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);
159-
}
160-
}
161-
free(name);
162-
if (err)
163-
return pos;
164-
free(ru);
165-
item->util = NULL;
166-
return unmerge_index_entry_at(istate, pos);
167-
}
168-
169-
void unmerge_marked_index(struct index_state *istate)
170-
{
171-
int i;
172-
173-
if (!istate->resolve_undo)
174-
return;
175-
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);
182-
}
183-
}
184-
185118
int unmerge_index_entry(struct index_state *istate, const char *path,
186-
struct resolve_undo_info *ru)
119+
struct resolve_undo_info *ru, unsigned ce_flags)
187120
{
188121
int i = index_name_pos(istate, path, strlen(path));
189122

@@ -206,13 +139,15 @@ int unmerge_index_entry(struct index_state *istate, const char *path,
206139
continue;
207140
ce = make_cache_entry(istate, ru->mode[i], &ru->oid[i],
208141
path, i + 1, 0);
142+
ce->ce_flags |= ce_flags;
209143
if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD))
210144
return error("cannot unmerge '%s'", path);
211145
}
212146
return 0;
213147
}
214148

215-
void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
149+
void unmerge_index(struct index_state *istate, const struct pathspec *pathspec,
150+
unsigned ce_flags)
216151
{
217152
struct string_list_item *item;
218153

@@ -231,7 +166,7 @@ void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
231166
item->string, strlen(item->string),
232167
0, NULL, 0))
233168
continue;
234-
unmerge_index_entry(istate, path, ru);
169+
unmerge_index_entry(istate, path, ru, ce_flags);
235170
free(ru);
236171
item->util = NULL;
237172
}

resolve-undo.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ void record_resolve_undo(struct index_state *, struct cache_entry *);
1717
void resolve_undo_write(struct strbuf *, struct string_list *);
1818
struct string_list *resolve_undo_read(const char *, unsigned long);
1919
void resolve_undo_clear_index(struct index_state *);
20-
int unmerge_index_entry_at(struct index_state *, int);
21-
int unmerge_index_entry(struct index_state *, const char *, struct resolve_undo_info *);
22-
void unmerge_index(struct index_state *, const struct pathspec *);
23-
void unmerge_marked_index(struct index_state *);
20+
int unmerge_index_entry(struct index_state *, const char *, struct resolve_undo_info *, unsigned);
21+
void unmerge_index(struct index_state *, const struct pathspec *, unsigned);
2422

2523
#endif

t/t2070-restore.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ test_expect_success 'restore --merge to unresolve after (mistaken) resolution' '
180180
test_cmp expect file
181181
'
182182

183-
test_expect_failure 'restore --merge to unresolve after (mistaken) resolution' '
183+
test_expect_success 'restore --merge to unresolve after (mistaken) resolution' '
184184
O=$(echo original | git hash-object -w --stdin) &&
185185
A=$(echo ourside | git hash-object -w --stdin) &&
186186
B=$(echo theirside | git hash-object -w --stdin) &&

t/t7201-co.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ test_expect_success 'checkout -m works after (mistaken) resolution' '
543543
test_cmp merged file
544544
'
545545

546-
test_expect_failure 'checkout -m works after (mistaken) resolution to remove' '
546+
test_expect_success 'checkout -m works after (mistaken) resolution to remove' '
547547
setup_conflicting_index &&
548548
echo "none of the above" >sample &&
549549
cat sample >fild &&

0 commit comments

Comments
 (0)