summaryrefslogtreecommitdiff
path: root/builtin/checkout.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/checkout.c')
-rw-r--r--builtin/checkout.c63
1 files changed, 38 insertions, 25 deletions
diff --git a/builtin/checkout.c b/builtin/checkout.c
index e9d111b..2d6550b 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -239,6 +239,8 @@ static int checkout_merged(int pos, const struct checkout *state, int *nr_checko
mmbuffer_t result_buf;
struct object_id threeway[3];
unsigned mode = 0;
+ struct ll_merge_options ll_opts;
+ int renormalize = 0;
memset(threeway, 0, sizeof(threeway));
while (pos < active_nr) {
@@ -259,13 +261,12 @@ static int checkout_merged(int pos, const struct checkout *state, int *nr_checko
read_mmblob(&ours, &threeway[1]);
read_mmblob(&theirs, &threeway[2]);
- /*
- * NEEDSWORK: re-create conflicts from merges with
- * merge.renormalize set, too
- */
+ memset(&ll_opts, 0, sizeof(ll_opts));
+ git_config_get_bool("merge.renormalize", &renormalize);
+ ll_opts.renormalize = renormalize;
status = ll_merge(&result_buf, path, &ancestor, "base",
&ours, "ours", &theirs, "theirs",
- state->istate, NULL);
+ state->istate, &ll_opts);
free(ancestor.ptr);
free(ours.ptr);
free(theirs.ptr);
@@ -470,6 +471,21 @@ static int checkout_paths(const struct checkout_opts *opts,
if (opts->patch_mode) {
const char *patch_mode;
+ const char *rev = new_branch_info->name;
+ char rev_oid[GIT_MAX_HEXSZ + 1];
+
+ /*
+ * Since rev can be in the form of `<a>...<b>` (which is not
+ * recognized by diff-index), we will always replace the name
+ * with the hex of the commit (whether it's in `...` form or
+ * not) for the run_add_interactive() machinery to work
+ * properly. However, there is special logic for the HEAD case
+ * so we mustn't replace that. Also, when we were given a
+ * tree-object, new_branch_info->commit would be NULL, but we
+ * do not have to do any replacement, either.
+ */
+ if (rev && new_branch_info->commit && strcmp(rev, "HEAD"))
+ rev = oid_to_hex_r(rev_oid, &new_branch_info->commit->object.oid);
if (opts->checkout_index && opts->checkout_worktree)
patch_mode = "--patch=checkout";
@@ -480,7 +496,7 @@ static int checkout_paths(const struct checkout_opts *opts,
else
BUG("either flag must have been set, worktree=%d, index=%d",
opts->checkout_worktree, opts->checkout_index);
- return run_add_interactive(new_branch_info->name, patch_mode, &opts->pathspec);
+ return run_add_interactive(rev, patch_mode, &opts->pathspec);
}
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@@ -621,9 +637,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
opts.src_index = &the_index;
opts.dst_index = &the_index;
init_checkout_metadata(&opts.meta, info->refname,
- info->commit ? &info->commit->object.oid :
- is_null_oid(&info->oid) ? &tree->object.oid :
- &info->oid,
+ info->commit ? &info->commit->object.oid : &null_oid,
NULL);
parse_tree(tree);
init_tree_desc(&tree_desc, tree->buffer, tree->size);
@@ -652,7 +666,7 @@ static void setup_branch_path(struct branch_info *branch)
* If this is a ref, resolve it; otherwise, look up the OID for our
* expression. Failure here is okay.
*/
- if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname))
+ if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname, 0))
repo_get_oid_committish(the_repository, branch->name, &branch->oid);
strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL);
@@ -773,13 +787,6 @@ static int merge_working_tree(const struct checkout_opts *opts,
*/
add_files_to_cache(NULL, NULL, 0);
- /*
- * NEEDSWORK: carrying over local changes
- * when branches have different end-of-line
- * normalization (or clean+smudge rules) is
- * a pain; plumb in an option to set
- * o.renormalize?
- */
init_merge_options(&o, the_repository);
o.verbosity = 0;
work = write_in_core_index_as_tree(the_repository);
@@ -814,9 +821,6 @@ static int merge_working_tree(const struct checkout_opts *opts,
}
}
- if (!active_cache_tree)
- active_cache_tree = cache_tree();
-
if (!cache_tree_fully_valid(active_cache_tree))
cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
@@ -1037,7 +1041,7 @@ static void orphaned_commit_warning(struct commit *old_commit, struct commit *ne
describe_detached_head(_("Previous HEAD position was"), old_commit);
/* Clean up objects used, as they will be reused. */
- clear_commit_marks_all(ALL_REV_FLAGS);
+ repo_clear_commit_marks(the_repository, ALL_REV_FLAGS);
}
static int switch_branches(const struct checkout_opts *opts,
@@ -1101,11 +1105,16 @@ static int switch_branches(const struct checkout_opts *opts,
static int git_checkout_config(const char *var, const char *value, void *cb)
{
+ struct checkout_opts *opts = cb;
+
if (!strcmp(var, "diff.ignoresubmodules")) {
- struct checkout_opts *opts = cb;
handle_ignore_submodules_arg(&opts->diff_options, value);
return 0;
}
+ if (!strcmp(var, "checkout.guess")) {
+ opts->dwim_new_local_branch = git_config_bool(var, value);
+ return 0;
+ }
if (starts_with(var, "submodule."))
return git_default_submodule_config(var, value, NULL);
@@ -1128,8 +1137,10 @@ static void setup_new_branch_info_and_source_tree(
if (!check_refname_format(new_branch_info->path, 0) &&
!read_ref(new_branch_info->path, &branch_rev))
oidcpy(rev, &branch_rev);
- else
+ else {
+ free((char *)new_branch_info->path);
new_branch_info->path = NULL; /* not an existing branch */
+ }
new_branch_info->commit = lookup_commit_reference_gently(the_repository, rev, 1);
if (!new_branch_info->commit) {
@@ -1351,7 +1362,7 @@ static void die_expecting_a_branch(const struct branch_info *branch_info)
struct object_id oid;
char *to_free;
- if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free) == 1) {
+ if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free, 0) == 1) {
const char *ref = to_free;
if (skip_prefix(ref, "refs/tags/", &ref))
@@ -1689,7 +1700,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
* Try to give more helpful suggestion.
* new_branch && argc > 1 will be caught later.
*/
- if (opts->new_branch && argc == 1)
+ if (opts->new_branch && argc == 1 && !new_branch_info.commit)
die(_("'%s' is not a commit and a branch '%s' cannot be created from it"),
argv[0], opts->new_branch);
@@ -1715,6 +1726,8 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
die(_("--pathspec-file-nul requires --pathspec-from-file"));
}
+ opts->pathspec.recursive = 1;
+
if (opts->pathspec.nr) {
if (1 < !!opts->writeout_stage + !!opts->force + !!opts->merge)
die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\n"