diff options
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/pack-objects.c | 1 | ||||
-rw-r--r-- | builtin/pull.c | 70 | ||||
-rw-r--r-- | builtin/rev-parse.c | 106 | ||||
-rw-r--r-- | builtin/worktree.c | 2 |
4 files changed, 138 insertions, 41 deletions
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 5617c01b5a..2a00358f34 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1104,7 +1104,6 @@ static void write_pack_file(void) stop_progress(&progress_state); bitmap_writer_show_progress(progress); - bitmap_writer_reuse_bitmaps(&to_pack); bitmap_writer_select_commits(indexed_commits, indexed_commits_nr, -1); bitmap_writer_build(&to_pack); bitmap_writer_finish(written_list, nr_written, diff --git a/builtin/pull.c b/builtin/pull.c index aa56ebcdd0..e8927fc2ff 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -324,7 +324,7 @@ static const char *config_get_ff(void) * looks for the value of "pull.rebase". If both configuration keys do not * exist, returns REBASE_FALSE. */ -static enum rebase_type config_get_rebase(void) +static enum rebase_type config_get_rebase(int *rebase_unspecified) { struct branch *curr_branch = branch_get("HEAD"); const char *value; @@ -344,20 +344,7 @@ static enum rebase_type config_get_rebase(void) if (!git_config_get_value("pull.rebase", &value)) return parse_config_rebase("pull.rebase", value, 1); - if (opt_verbosity >= 0 && !opt_ff) { - advise(_("Pulling without specifying how to reconcile divergent branches is\n" - "discouraged. You can squelch this message by running one of the following\n" - "commands sometime before your next pull:\n" - "\n" - " git config pull.rebase false # merge (the default strategy)\n" - " git config pull.rebase true # rebase\n" - " git config pull.ff only # fast-forward only\n" - "\n" - "You can replace \"git config\" with \"git config --global\" to set a default\n" - "preference for all repositories. You can also pass --rebase, --no-rebase,\n" - "or --ff-only on the command line to override the configured default per\n" - "invocation.\n")); - } + *rebase_unspecified = 1; return REBASE_FALSE; } @@ -924,6 +911,36 @@ static int run_rebase(const struct object_id *newbase, return ret; } +static int get_can_ff(struct object_id *orig_head, struct object_id *orig_merge_head) +{ + int ret; + struct commit_list *list = NULL; + struct commit *merge_head, *head; + + head = lookup_commit_reference(the_repository, orig_head); + commit_list_insert(head, &list); + merge_head = lookup_commit_reference(the_repository, orig_merge_head); + ret = repo_is_descendant_of(the_repository, merge_head, list); + free_commit_list(list); + return ret; +} + +static void show_advice_pull_non_ff(void) +{ + advise(_("Pulling without specifying how to reconcile divergent branches is\n" + "discouraged. You can squelch this message by running one of the following\n" + "commands sometime before your next pull:\n" + "\n" + " git config pull.rebase false # merge (the default strategy)\n" + " git config pull.rebase true # rebase\n" + " git config pull.ff only # fast-forward only\n" + "\n" + "You can replace \"git config\" with \"git config --global\" to set a default\n" + "preference for all repositories. You can also pass --rebase, --no-rebase,\n" + "or --ff-only on the command line to override the configured default per\n" + "invocation.\n")); +} + int cmd_pull(int argc, const char **argv, const char *prefix) { const char *repo, **refspecs; @@ -931,6 +948,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix) struct object_id orig_head, curr_head; struct object_id rebase_fork_point; int autostash; + int rebase_unspecified = 0; + int can_ff; if (!getenv("GIT_REFLOG_ACTION")) set_reflog_message(argc, argv); @@ -952,7 +971,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix) opt_ff = xstrdup_or_null(config_get_ff()); if (opt_rebase < 0) - opt_rebase = config_get_rebase(); + opt_rebase = config_get_rebase(&rebase_unspecified); if (read_cache_unmerged()) die_resolve_conflict("pull"); @@ -1026,6 +1045,13 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (opt_rebase && merge_heads.nr > 1) die(_("Cannot rebase onto multiple branches.")); + can_ff = get_can_ff(&orig_head, &merge_heads.oid[0]); + + if (rebase_unspecified && !opt_ff && !can_ff) { + if (opt_verbosity >= 0) + show_advice_pull_non_ff(); + } + if (opt_rebase) { int ret = 0; int ran_ff = 0; @@ -1040,22 +1066,12 @@ int cmd_pull(int argc, const char **argv, const char *prefix) submodule_touches_in_range(the_repository, &upstream, &curr_head)) die(_("cannot rebase with locally recorded submodule modifications")); if (!autostash) { - struct commit_list *list = NULL; - struct commit *merge_head, *head; - - head = lookup_commit_reference(the_repository, - &orig_head); - commit_list_insert(head, &list); - merge_head = lookup_commit_reference(the_repository, - &merge_heads.oid[0]); - if (repo_is_descendant_of(the_repository, - merge_head, list)) { + if (can_ff) { /* we can fast-forward this without invoking rebase */ opt_ff = "--ff-only"; ran_ff = 1; ret = run_merge(); } - free_commit_list(list); } if (!ran_ff) ret = run_rebase(&newbase, &upstream); diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 69ba7326cf..85bad9052e 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -583,6 +583,75 @@ static void handle_ref_opt(const char *pattern, const char *prefix) clear_ref_exclusion(&ref_excludes); } +enum format_type { + /* We would like a relative path. */ + FORMAT_RELATIVE, + /* We would like a canonical absolute path. */ + FORMAT_CANONICAL, + /* We would like the default behavior. */ + FORMAT_DEFAULT, +}; + +enum default_type { + /* Our default is a relative path. */ + DEFAULT_RELATIVE, + /* Our default is a relative path if there's a shared root. */ + DEFAULT_RELATIVE_IF_SHARED, + /* Our default is a canonical absolute path. */ + DEFAULT_CANONICAL, + /* Our default is not to modify the item. */ + DEFAULT_UNMODIFIED, +}; + +static void print_path(const char *path, const char *prefix, enum format_type format, enum default_type def) +{ + char *cwd = NULL; + /* + * We don't ever produce a relative path if prefix is NULL, so set the + * prefix to the current directory so that we can produce a relative + * path whenever possible. If we're using RELATIVE_IF_SHARED mode, then + * we want an absolute path unless the two share a common prefix, so don't + * set it in that case, since doing so causes a relative path to always + * be produced if possible. + */ + if (!prefix && (format != FORMAT_DEFAULT || def != DEFAULT_RELATIVE_IF_SHARED)) + prefix = cwd = xgetcwd(); + if (format == FORMAT_DEFAULT && def == DEFAULT_UNMODIFIED) { + puts(path); + } else if (format == FORMAT_RELATIVE || + (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE)) { + /* + * In order for relative_path to work as expected, we need to + * make sure that both paths are absolute paths. If we don't, + * we can end up with an unexpected absolute path that the user + * didn't want. + */ + struct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT; + if (!is_absolute_path(path)) { + strbuf_realpath_forgiving(&realbuf, path, 1); + path = realbuf.buf; + } + if (!is_absolute_path(prefix)) { + strbuf_realpath_forgiving(&prefixbuf, prefix, 1); + prefix = prefixbuf.buf; + } + puts(relative_path(path, prefix, &buf)); + strbuf_release(&buf); + strbuf_release(&realbuf); + strbuf_release(&prefixbuf); + } else if (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE_IF_SHARED) { + struct strbuf buf = STRBUF_INIT; + puts(relative_path(path, prefix, &buf)); + strbuf_release(&buf); + } else { + struct strbuf buf = STRBUF_INIT; + strbuf_realpath_forgiving(&buf, path, 1); + puts(buf.buf); + strbuf_release(&buf); + } + free(cwd); +} + int cmd_rev_parse(int argc, const char **argv, const char *prefix) { int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0; @@ -596,6 +665,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) struct strbuf buf = STRBUF_INIT; const int hexsz = the_hash_algo->hexsz; int seen_end_of_options = 0; + enum format_type format = FORMAT_DEFAULT; if (argc > 1 && !strcmp("--parseopt", argv[1])) return cmd_parseopt(argc - 1, argv + 1, prefix); @@ -668,8 +738,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) if (!argv[i + 1]) die("--git-path requires an argument"); strbuf_reset(&buf); - puts(relative_path(git_path("%s", argv[i + 1]), - prefix, &buf)); + print_path(git_path("%s", argv[i + 1]), prefix, + format, + DEFAULT_RELATIVE_IF_SHARED); i++; continue; } @@ -687,6 +758,16 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) show(arg); continue; } + if (opt_with_value(arg, "--path-format", &arg)) { + if (!strcmp(arg, "absolute")) { + format = FORMAT_CANONICAL; + } else if (!strcmp(arg, "relative")) { + format = FORMAT_RELATIVE; + } else { + die("unknown argument to --path-format: %s", arg); + } + continue; + } if (!strcmp(arg, "--default")) { def = argv[++i]; if (!def) @@ -807,7 +888,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) if (!strcmp(arg, "--show-toplevel")) { const char *work_tree = get_git_work_tree(); if (work_tree) - puts(work_tree); + print_path(work_tree, prefix, format, DEFAULT_UNMODIFIED); else die("this operation must be run in a work tree"); continue; @@ -815,7 +896,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) if (!strcmp(arg, "--show-superproject-working-tree")) { struct strbuf superproject = STRBUF_INIT; if (get_superproject_working_tree(&superproject)) - puts(superproject.buf); + print_path(superproject.buf, prefix, format, DEFAULT_UNMODIFIED); strbuf_release(&superproject); continue; } @@ -850,16 +931,18 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) const char *gitdir = getenv(GIT_DIR_ENVIRONMENT); char *cwd; int len; + enum format_type wanted = format; if (arg[2] == 'g') { /* --git-dir */ if (gitdir) { - puts(gitdir); + print_path(gitdir, prefix, format, DEFAULT_UNMODIFIED); continue; } if (!prefix) { - puts(".git"); + print_path(".git", prefix, format, DEFAULT_UNMODIFIED); continue; } } else { /* --absolute-git-dir */ + wanted = FORMAT_CANONICAL; if (!gitdir && !prefix) gitdir = ".git"; if (gitdir) { @@ -872,14 +955,14 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) } cwd = xgetcwd(); len = strlen(cwd); - printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : ""); + strbuf_reset(&buf); + strbuf_addf(&buf, "%s%s.git", cwd, len && cwd[len-1] != '/' ? "/" : ""); free(cwd); + print_path(buf.buf, prefix, wanted, DEFAULT_CANONICAL); continue; } if (!strcmp(arg, "--git-common-dir")) { - strbuf_reset(&buf); - puts(relative_path(get_git_common_dir(), - prefix, &buf)); + print_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED); continue; } if (!strcmp(arg, "--is-inside-git-dir")) { @@ -909,8 +992,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) if (the_index.split_index) { const struct object_id *oid = &the_index.split_index->base_oid; const char *path = git_path("sharedindex.%s", oid_to_hex(oid)); - strbuf_reset(&buf); - puts(relative_path(path, prefix, &buf)); + print_path(path, prefix, format, DEFAULT_RELATIVE); } continue; } diff --git a/builtin/worktree.c b/builtin/worktree.c index 197fd24a55..71287b2da6 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -1052,10 +1052,10 @@ static int repair(int ac, const char **av, const char *prefix) int rc = 0; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); - repair_worktrees(report_repair, &rc); p = ac > 0 ? av : self; for (; *p; p++) repair_worktree_at_path(*p, report_repair, &rc); + repair_worktrees(report_repair, &rc); return rc; } |