Merge branch 'jc/fix-add-u-unmerged' into maint
* jc/fix-add-u-unmerged: Fix "add -u" that sometimes fails to resolve unmerged paths Conflicts: builtin/add.c
This commit is contained in:
commit
90e8b9b23d
@ -26,6 +26,27 @@ struct update_callback_data {
|
|||||||
int add_errors;
|
int add_errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int fix_unmerged_status(struct diff_filepair *p,
|
||||||
|
struct update_callback_data *data)
|
||||||
|
{
|
||||||
|
if (p->status != DIFF_STATUS_UNMERGED)
|
||||||
|
return p->status;
|
||||||
|
if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
|
||||||
|
/*
|
||||||
|
* This is not an explicit add request, and the
|
||||||
|
* path is missing from the working tree (deleted)
|
||||||
|
*/
|
||||||
|
return DIFF_STATUS_DELETED;
|
||||||
|
else
|
||||||
|
/*
|
||||||
|
* Either an explicit add request, or path exists
|
||||||
|
* in the working tree. An attempt to explicitly
|
||||||
|
* add a path that does not exist in the working tree
|
||||||
|
* will be caught as an error by the caller immediately.
|
||||||
|
*/
|
||||||
|
return DIFF_STATUS_MODIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
static void update_callback(struct diff_queue_struct *q,
|
static void update_callback(struct diff_queue_struct *q,
|
||||||
struct diff_options *opt, void *cbdata)
|
struct diff_options *opt, void *cbdata)
|
||||||
{
|
{
|
||||||
@ -35,30 +56,9 @@ static void update_callback(struct diff_queue_struct *q,
|
|||||||
for (i = 0; i < q->nr; i++) {
|
for (i = 0; i < q->nr; i++) {
|
||||||
struct diff_filepair *p = q->queue[i];
|
struct diff_filepair *p = q->queue[i];
|
||||||
const char *path = p->one->path;
|
const char *path = p->one->path;
|
||||||
switch (p->status) {
|
switch (fix_unmerged_status(p, data)) {
|
||||||
default:
|
default:
|
||||||
die(_("unexpected diff status %c"), p->status);
|
die(_("unexpected diff status %c"), p->status);
|
||||||
case DIFF_STATUS_UNMERGED:
|
|
||||||
/*
|
|
||||||
* ADD_CACHE_IGNORE_REMOVAL is unset if "git
|
|
||||||
* add -u" is calling us, In such a case, a
|
|
||||||
* missing work tree file needs to be removed
|
|
||||||
* if there is an unmerged entry at stage #2,
|
|
||||||
* but such a diff record is followed by
|
|
||||||
* another with DIFF_STATUS_DELETED (and if
|
|
||||||
* there is no stage #2, we won't see DELETED
|
|
||||||
* nor MODIFIED). We can simply continue
|
|
||||||
* either way.
|
|
||||||
*/
|
|
||||||
if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL))
|
|
||||||
continue;
|
|
||||||
/*
|
|
||||||
* Otherwise, it is "git add path" is asking
|
|
||||||
* to explicitly add it; we fall through. A
|
|
||||||
* missing work tree file is an error and is
|
|
||||||
* caught by add_file_to_index() in such a
|
|
||||||
* case.
|
|
||||||
*/
|
|
||||||
case DIFF_STATUS_MODIFIED:
|
case DIFF_STATUS_MODIFIED:
|
||||||
case DIFF_STATUS_TYPE_CHANGED:
|
case DIFF_STATUS_TYPE_CHANGED:
|
||||||
if (add_file_to_index(&the_index, path, data->flags)) {
|
if (add_file_to_index(&the_index, path, data->flags)) {
|
||||||
@ -91,6 +91,7 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
|
|||||||
data.flags = flags;
|
data.flags = flags;
|
||||||
data.add_errors = 0;
|
data.add_errors = 0;
|
||||||
rev.diffopt.format_callback_data = &data;
|
rev.diffopt.format_callback_data = &data;
|
||||||
|
rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
|
||||||
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
|
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
|
||||||
return !!data.add_errors;
|
return !!data.add_errors;
|
||||||
}
|
}
|
||||||
|
@ -149,31 +149,21 @@ test_expect_success 'add -u resolves unmerged paths' '
|
|||||||
echo 3 >path1 &&
|
echo 3 >path1 &&
|
||||||
echo 2 >path3 &&
|
echo 2 >path3 &&
|
||||||
echo 2 >path5 &&
|
echo 2 >path5 &&
|
||||||
|
|
||||||
|
# Explicit resolving by adding removed paths should fail
|
||||||
|
test_must_fail git add path4 &&
|
||||||
|
test_must_fail git add path6 &&
|
||||||
|
|
||||||
|
# "add -u" should notice removals no matter what stages
|
||||||
|
# the index entries are in.
|
||||||
git add -u &&
|
git add -u &&
|
||||||
git ls-files -s path1 path2 path3 path4 path5 path6 >actual &&
|
git ls-files -s path1 path2 path3 path4 path5 path6 >actual &&
|
||||||
{
|
|
||||||
echo "100644 $three 0 path1"
|
|
||||||
echo "100644 $one 1 path3"
|
|
||||||
echo "100644 $one 1 path4"
|
|
||||||
echo "100644 $one 3 path5"
|
|
||||||
echo "100644 $one 3 path6"
|
|
||||||
} >expect &&
|
|
||||||
test_cmp expect actual &&
|
|
||||||
|
|
||||||
# Bonus tests. Explicit resolving
|
|
||||||
git add path3 path5 &&
|
|
||||||
test_must_fail git add path4 &&
|
|
||||||
test_must_fail git add path6 &&
|
|
||||||
git rm path4 &&
|
|
||||||
git rm path6 &&
|
|
||||||
|
|
||||||
git ls-files -s "path?" >actual &&
|
|
||||||
{
|
{
|
||||||
echo "100644 $three 0 path1"
|
echo "100644 $three 0 path1"
|
||||||
echo "100644 $two 0 path3"
|
echo "100644 $two 0 path3"
|
||||||
echo "100644 $two 0 path5"
|
echo "100644 $two 0 path5"
|
||||||
} >expect
|
} >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '"add -u non-existent" should fail' '
|
test_expect_success '"add -u non-existent" should fail' '
|
||||||
|
Loading…
Reference in New Issue
Block a user