]> git.ipfire.org Git - thirdparty/git.git/blobdiff - builtin/checkout.c
Merge branch 'jk/bundle-use-dash-for-stdfiles'
[thirdparty/git.git] / builtin / checkout.c
index 5963e1b74b82f5bd1d572325aed01ff66c587d52..734d730980c18e7fd8e774ac2b720e1e823dc47e 100644 (file)
@@ -9,6 +9,7 @@
 #include "config.h"
 #include "diff.h"
 #include "dir.h"
+#include "hex.h"
 #include "hook.h"
 #include "ll-merge.h"
 #include "lockfile.h"
@@ -29,6 +30,7 @@
 #include "xdiff-interface.h"
 #include "entry.h"
 #include "parallel-checkout.h"
+#include "add-interactive.h"
 
 static const char * const checkout_usage[] = {
        N_("git checkout [<options>] <branch>"),
@@ -74,7 +76,7 @@ struct checkout_opts {
        const char *ignore_unmerged_opt;
        int ignore_unmerged;
        int pathspec_file_nul;
-       const char *pathspec_from_file;
+       char *pathspec_from_file;
 
        const char *new_branch;
        const char *new_branch_force;
@@ -488,18 +490,31 @@ static int checkout_paths(const struct checkout_opts *opts,
                die(_("'%s' must be used when '%s' is not specified"),
                    "--worktree", "--source");
 
-       if (opts->checkout_index && !opts->checkout_worktree &&
-           opts->writeout_stage)
-               die(_("'%s' or '%s' cannot be used with %s"),
-                   "--ours", "--theirs", "--staged");
-
-       if (opts->checkout_index && !opts->checkout_worktree &&
-           opts->merge)
-               die(_("'%s' or '%s' cannot be used with %s"),
-                   "--merge", "--conflict", "--staged");
+       /*
+        * Reject --staged option to the restore command when combined with
+        * merge-related options. Use the accept_ref flag to distinguish it
+        * from the checkout command, which does not accept --staged anyway.
+        *
+        * `restore --ours|--theirs --worktree --staged` could mean resolving
+        * conflicted paths to one side in both the worktree and the index,
+        * but does not currently.
+        *
+        * `restore --merge|--conflict=<style>` already recreates conflicts
+        * in both the worktree and the index, so adding --staged would be
+        * meaningless.
+        */
+       if (!opts->accept_ref && opts->checkout_index) {
+               if (opts->writeout_stage)
+                       die(_("'%s' or '%s' cannot be used with %s"),
+                           "--ours", "--theirs", "--staged");
+
+               if (opts->merge)
+                       die(_("'%s' or '%s' cannot be used with %s"),
+                           "--merge", "--conflict", "--staged");
+       }
 
        if (opts->patch_mode) {
-               const char *patch_mode;
+               enum add_p_mode patch_mode;
                const char *rev = new_branch_info->name;
                char rev_oid[GIT_MAX_HEXSZ + 1];
 
@@ -517,15 +532,16 @@ static int checkout_paths(const struct checkout_opts *opts,
                        rev = oid_to_hex_r(rev_oid, &new_branch_info->commit->object.oid);
 
                if (opts->checkout_index && opts->checkout_worktree)
-                       patch_mode = "--patch=checkout";
+                       patch_mode = ADD_P_CHECKOUT;
                else if (opts->checkout_index && !opts->checkout_worktree)
-                       patch_mode = "--patch=reset";
+                       patch_mode = ADD_P_RESET;
                else if (!opts->checkout_index && opts->checkout_worktree)
-                       patch_mode = "--patch=worktree";
+                       patch_mode = ADD_P_WORKTREE;
                else
                        BUG("either flag must have been set, worktree=%d, index=%d",
                            opts->checkout_worktree, opts->checkout_index);
-               return run_add_interactive(rev, patch_mode, &opts->pathspec);
+               return !!run_add_p(the_repository, patch_mode, rev,
+                                  &opts->pathspec);
        }
 
        repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@@ -1874,6 +1890,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                            options, checkout_usage, &new_branch_info);
        branch_info_release(&new_branch_info);
        clear_pathspec(&opts.pathspec);
+       free(opts.pathspec_from_file);
        FREE_AND_NULL(options);
        return ret;
 }