Add branch --set-upstream
[gitweb.git] / builtin-reset.c
index 73e60223db844ee2445aff0b2253f0f21e8a5bef..0f5022eed24f980f6fedee49f8602fefa6fe85e4 100644 (file)
@@ -18,6 +18,8 @@
 #include "tree.h"
 #include "branch.h"
 #include "parse-options.h"
+#include "unpack-trees.h"
+#include "cache-tree.h"
 
 static const char * const git_reset_usage[] = {
        "git reset [--mixed | --soft | --hard | --merge] [-q] [<commit>]",
@@ -54,27 +56,44 @@ static inline int is_merge(void)
 
 static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)
 {
-       int i = 0;
-       const char *args[6];
+       int nr = 1;
+       int newfd;
+       struct tree_desc desc[2];
+       struct unpack_trees_options opts;
+       struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
 
-       args[i++] = "read-tree";
+       memset(&opts, 0, sizeof(opts));
+       opts.head_idx = 1;
+       opts.src_index = &the_index;
+       opts.dst_index = &the_index;
+       opts.fn = oneway_merge;
+       opts.merge = 1;
        if (!quiet)
-               args[i++] = "-v";
+               opts.verbose_update = 1;
        switch (reset_type) {
        case MERGE:
-               args[i++] = "-u";
-               args[i++] = "-m";
+               opts.update = 1;
                break;
        case HARD:
-               args[i++] = "-u";
+               opts.update = 1;
                /* fallthrough */
        default:
-               args[i++] = "--reset";
+               opts.reset = 1;
        }
-       args[i++] = sha1_to_hex(sha1);
-       args[i] = NULL;
 
-       return run_command_v_opt(args, RUN_GIT_CMD);
+       newfd = hold_locked_index(lock, 1);
+
+       read_cache_unmerged();
+
+       if (!fill_tree_descriptor(desc + nr - 1, sha1))
+               return error("Failed to find tree of %s.", sha1_to_hex(sha1));
+       if (unpack_trees(nr, desc, &opts))
+               return -1;
+       if (write_cache(newfd, active_cache, active_nr) ||
+           commit_locked_index(lock))
+               return error("Could not write new index file.");
+
+       return 0;
 }
 
 static void print_new_head_line(struct commit *commit)
@@ -202,6 +221,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
        struct commit *commit;
        char *reflog_action, msg[1024];
        const struct option options[] = {
+               OPT__QUIET(&quiet),
                OPT_SET_INT(0, "mixed", &reset_type,
                                                "reset HEAD and index", MIXED),
                OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT),
@@ -209,8 +229,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                                "reset HEAD, index and working tree", HARD),
                OPT_SET_INT(0, "merge", &reset_type,
                                "reset HEAD, index and working tree", MERGE),
-               OPT_BOOLEAN('q', NULL, &quiet,
-                               "disable showing new HEAD in hard reset and progress message"),
                OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
                OPT_END()
        };
@@ -286,8 +304,12 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
        if (reset_type == NONE)
                reset_type = MIXED; /* by default */
 
-       if (reset_type == HARD && is_bare_repository())
-               die("hard reset makes no sense in a bare repository");
+       if (reset_type == HARD || reset_type == MERGE)
+               setup_work_tree();
+
+       if (reset_type == MIXED && is_bare_repository())
+               die("%s reset is not allowed in a bare repository",
+                   reset_type_names[reset_type]);
 
        /* Soft reset does not touch the index file nor the working tree
         * at all, but requires them in a good order.  Other resets reset