aboutsummaryrefslogtreecommitdiff
path: root/builtin/add.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2011-05-13 11:01:15 -0700
committerJunio C Hamano <gitster@pobox.com>2011-05-13 11:01:15 -0700
commitf7d59e256884f63adeed9a1f3376a386a28681ff (patch)
treed79d33ee5fa727db52c2bcba4c5e66841538d102 /builtin/add.c
parent3e1a363b1ff748237f3a6e4f3e2803445f09c54c (diff)
parent75973b2cb58bf2b3038c5c214fc0a1b96d6868fe (diff)
downloadgit-f7d59e256884f63adeed9a1f3376a386a28681ff.tar.gz
git-f7d59e256884f63adeed9a1f3376a386a28681ff.tar.xz
Merge branch 'jc/fix-add-u-unmerged'
* jc/fix-add-u-unmerged: Fix "add -u" that sometimes fails to resolve unmerged paths
Diffstat (limited to 'builtin/add.c')
-rw-r--r--builtin/add.c45
1 files changed, 23 insertions, 22 deletions
diff --git a/builtin/add.c b/builtin/add.c
index d39a6ab93..704141fdd 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -26,6 +26,27 @@ struct update_callback_data {
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,
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++) {
struct diff_filepair *p = q->queue[i];
const char *path = p->one->path;
- switch (p->status) {
+ switch (fix_unmerged_status(p, data)) {
default:
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_TYPE_CHANGED:
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.add_errors = 0;
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);
return !!data.add_errors;
}