Merge branch 'jk/config-die-bad-number-noreturn'
[gitweb.git] / builtin / reset.c
index a9913443580846b7c401c8c4517890ad91fe8ded..f4e087596b6337d2306af4cf45119752b4a049ea 100644 (file)
@@ -116,25 +116,34 @@ static void update_index_from_diff(struct diff_queue_struct *q,
                struct diff_options *opt, void *data)
 {
        int i;
+       int intent_to_add = *(int *)data;
 
        for (i = 0; i < q->nr; i++) {
                struct diff_filespec *one = q->queue[i]->one;
-               if (one->mode && !is_null_sha1(one->sha1)) {
-                       struct cache_entry *ce;
-                       ce = make_cache_entry(one->mode, one->sha1, one->path,
-                               0, 0);
-                       if (!ce)
-                               die(_("make_cache_entry failed for path '%s'"),
-                                   one->path);
-                       add_cache_entry(ce, ADD_CACHE_OK_TO_ADD |
-                               ADD_CACHE_OK_TO_REPLACE);
-               } else
+               int is_missing = !(one->mode && !is_null_sha1(one->sha1));
+               struct cache_entry *ce;
+
+               if (is_missing && !intent_to_add) {
                        remove_file_from_cache(one->path);
+                       continue;
+               }
+
+               ce = make_cache_entry(one->mode, one->sha1, one->path,
+                                     0, 0);
+               if (!ce)
+                       die(_("make_cache_entry failed for path '%s'"),
+                           one->path);
+               if (is_missing) {
+                       ce->ce_flags |= CE_INTENT_TO_ADD;
+                       set_object_name_for_intent_to_add_entry(ce);
+               }
+               add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
        }
 }
 
 static int read_from_tree(const struct pathspec *pathspec,
-                         unsigned char *tree_sha1)
+                         unsigned char *tree_sha1,
+                         int intent_to_add)
 {
        struct diff_options opt;
 
@@ -142,6 +151,7 @@ static int read_from_tree(const struct pathspec *pathspec,
        copy_pathspec(&opt.pathspec, pathspec);
        opt.output_format = DIFF_FORMAT_CALLBACK;
        opt.format_callback = update_index_from_diff;
+       opt.format_callback_data = &intent_to_add;
 
        if (do_diff_cache(tree_sha1, &opt))
                return 1;
@@ -258,6 +268,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
        const char *rev;
        unsigned char sha1[20];
        struct pathspec pathspec;
+       int intent_to_add = 0;
        const struct option options[] = {
                OPT__QUIET(&quiet, N_("be quiet, only report errors")),
                OPT_SET_INT(0, "mixed", &reset_type,
@@ -270,6 +281,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                OPT_SET_INT(0, "keep", &reset_type,
                                N_("reset HEAD but keep local changes"), KEEP),
                OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
+               OPT_BOOL('N', "intent-to-add", &intent_to_add,
+                               N_("record only the fact that removed paths will be added later")),
                OPT_END()
        };
 
@@ -327,6 +340,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                die(_("%s reset is not allowed in a bare repository"),
                    _(reset_type_names[reset_type]));
 
+       if (intent_to_add && reset_type != MIXED)
+               die(_("-N can only be used with --mixed"));
+
        /* Soft reset does not touch the index file nor the working tree
         * at all, but requires them in a good order.  Other resets reset
         * the index file to the tree object we are switching to. */
@@ -338,7 +354,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                int newfd = hold_locked_index(lock, 1);
                if (reset_type == MIXED) {
                        int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-                       if (read_from_tree(&pathspec, sha1))
+                       if (read_from_tree(&pathspec, sha1, intent_to_add))
                                return 1;
                        if (get_git_work_tree())
                                refresh_index(&the_index, flags, NULL, NULL,