diff options
Diffstat (limited to 'builtin')
113 files changed, 1351 insertions, 1413 deletions
diff --git a/builtin/add.c b/builtin/add.c index 76cc026a68..4b0dd798df 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -4,10 +4,9 @@ * Copyright (C) 2006 Linus Torvalds */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "advice.h" #include "config.h" -#include "builtin.h" #include "lockfile.h" #include "editor.h" #include "dir.h" @@ -17,8 +16,12 @@ #include "cache-tree.h" #include "run-command.h" #include "parse-options.h" +#include "path.h" +#include "preload-index.h" #include "diff.h" #include "diffcore.h" +#include "read-cache.h" +#include "repository.h" #include "revision.h" #include "bulk-checkin.h" #include "strvec.h" @@ -36,11 +39,6 @@ static int pathspec_file_nul; static int include_sparse; static const char *pathspec_from_file; -struct update_callback_data { - int flags; - int add_errors; -}; - static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only) { int i, ret = 0; @@ -69,95 +67,6 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only) return ret; } -static int fix_unmerged_status(struct diff_filepair *p, - struct update_callback_data *data) -{ - if (p->status != DIFF_STATUS_UNMERGED) - return p->status; - if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode) - /* - * This is not an explicit add request, and the - * path is missing from the working tree (deleted) - */ - return DIFF_STATUS_DELETED; - else - /* - * Either an explicit add request, or path exists - * in the working tree. An attempt to explicitly - * add a path that does not exist in the working tree - * will be caught as an error by the caller immediately. - */ - return DIFF_STATUS_MODIFIED; -} - -static void update_callback(struct diff_queue_struct *q, - struct diff_options *opt UNUSED, void *cbdata) -{ - int i; - struct update_callback_data *data = cbdata; - - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - const char *path = p->one->path; - - if (!include_sparse && !path_in_sparse_checkout(path, &the_index)) - continue; - - switch (fix_unmerged_status(p, data)) { - default: - die(_("unexpected diff status %c"), p->status); - case DIFF_STATUS_MODIFIED: - case DIFF_STATUS_TYPE_CHANGED: - if (add_file_to_index(&the_index, path, data->flags)) { - if (!(data->flags & ADD_CACHE_IGNORE_ERRORS)) - die(_("updating files failed")); - data->add_errors++; - } - break; - case DIFF_STATUS_DELETED: - if (data->flags & ADD_CACHE_IGNORE_REMOVAL) - break; - if (!(data->flags & ADD_CACHE_PRETEND)) - remove_file_from_index(&the_index, path); - if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE)) - printf(_("remove '%s'\n"), path); - break; - } - } -} - -int add_files_to_cache(const char *prefix, - const struct pathspec *pathspec, int flags) -{ - struct update_callback_data data; - struct rev_info rev; - - memset(&data, 0, sizeof(data)); - data.flags = flags; - - repo_init_revisions(the_repository, &rev, prefix); - setup_revisions(0, NULL, &rev, NULL); - if (pathspec) - copy_pathspec(&rev.prune_data, pathspec); - rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; - rev.diffopt.format_callback = update_callback; - rev.diffopt.format_callback_data = &data; - rev.diffopt.flags.override_submodule_config = 1; - rev.max_count = 0; /* do not compare unmerged paths with stage #2 */ - - /* - * Use an ODB transaction to optimize adding multiple objects. - * This function is invoked from commands other than 'add', which - * may not have their own transaction active. - */ - begin_odb_transaction(); - run_diff_files(&rev, DIFF_RACY_IS_MODIFIED); - end_odb_transaction(); - - release_revisions(&rev); - return !!data.add_errors; -} - static int renormalize_tracked_files(const struct pathspec *pathspec, int flags) { int i, retval = 0; @@ -357,7 +266,8 @@ static struct option builtin_add_options[] = { OPT_END(), }; -static int add_config(const char *var, const char *value, void *cb) +static int add_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "add.ignoreerrors") || !strcmp(var, "add.ignore-errors")) { @@ -365,7 +275,10 @@ static int add_config(const char *var, const char *value, void *cb) return 0; } - return git_default_config(var, value, cb); + if (git_color_config(var, value, cb) < 0) + return -1; + + return git_default_config(var, value, ctx, cb); } static const char embedded_advice[] = N_( @@ -640,7 +553,9 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (add_renormalize) exit_status |= renormalize_tracked_files(&pathspec, flags); else - exit_status |= add_files_to_cache(prefix, &pathspec, flags); + exit_status |= add_files_to_cache(the_repository, prefix, + &pathspec, include_sparse, + flags); if (add_new_files) exit_status |= add_files(&dir, flags); diff --git a/builtin/am.c b/builtin/am.c index 5c83f2e003..5fab159599 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -4,11 +4,10 @@ * Based on git-am.sh by Junio C Hamano. */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "abspath.h" #include "advice.h" #include "config.h" -#include "builtin.h" #include "editor.h" #include "environment.h" #include "exec-cmd.h" @@ -29,6 +28,7 @@ #include "unpack-trees.h" #include "branch.h" #include "object-name.h" +#include "preload-index.h" #include "sequencer.h" #include "revision.h" #include "merge-recursive.h" @@ -41,6 +41,7 @@ #include "string-list.h" #include "packfile.h" #include "pager.h" +#include "path.h" #include "repository.h" #include "pretty.h" #include "wrapper.h" @@ -1283,7 +1284,7 @@ static int parse_mail(struct am_state *state, const char *mail) strbuf_addstr(&msg, "\n\n"); strbuf_addbuf(&msg, &mi.log_message); - strbuf_stripspace(&msg, 0); + strbuf_stripspace(&msg, '\0'); assert(!state->author_name); state->author_name = strbuf_detach(&author_name, NULL); diff --git a/builtin/apply.c b/builtin/apply.c index e3ff02a09e..c18b7ea5d3 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -1,4 +1,3 @@ -#include "cache.h" #include "builtin.h" #include "gettext.h" #include "parse-options.h" diff --git a/builtin/archive.c b/builtin/archive.c index b0eaa3c14a..90761fdfee 100644 --- a/builtin/archive.c +++ b/builtin/archive.c @@ -2,7 +2,6 @@ * Copyright (c) 2006 Franck Bui-Huu * Copyright (c) 2006 Rene Scharfe */ -#include "cache.h" #include "builtin.h" #include "archive.h" #include "gettext.h" diff --git a/builtin/bisect.c b/builtin/bisect.c index 4812450c39..6478df3489 100644 --- a/builtin/bisect.c +++ b/builtin/bisect.c @@ -1,5 +1,4 @@ #include "builtin.h" -#include "cache.h" #include "copy.h" #include "environment.h" #include "gettext.h" @@ -12,6 +11,7 @@ #include "strvec.h" #include "run-command.h" #include "oid-array.h" +#include "path.h" #include "prompt.h" #include "quote.h" #include "revision.h" diff --git a/builtin/blame.c b/builtin/blame.c index 2df6039a6e..f9d316a7bf 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -29,7 +29,7 @@ #include "dir.h" #include "progress.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "pager.h" #include "blame.h" #include "refs.h" @@ -694,7 +694,8 @@ static const char *add_prefix(const char *prefix, const char *path) return prefix_path(prefix, prefix ? strlen(prefix) : 0, path); } -static int git_blame_config(const char *var, const char *value, void *cb) +static int git_blame_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "blame.showroot")) { show_root = git_config_bool(var, value); @@ -767,7 +768,7 @@ static int git_blame_config(const char *var, const char *value, void *cb) if (userdiff_config(var, value) < 0) return -1; - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } static int blame_copy_callback(const struct option *option, const char *arg, int unset) diff --git a/builtin/branch.c b/builtin/branch.c index e6c2655af6..e8ff3ecc07 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -5,20 +5,20 @@ * Based on git-branch.sh by Junio C Hamano. */ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "color.h" #include "editor.h" #include "environment.h" #include "refs.h" #include "commit.h" -#include "builtin.h" #include "gettext.h" #include "object-name.h" #include "remote.h" #include "parse-options.h" #include "branch.h" #include "diff.h" +#include "path.h" #include "revision.h" #include "string-list.h" #include "column.h" @@ -83,7 +83,8 @@ static unsigned int colopts; define_list_config_array(color_branch_slots); -static int git_branch_config(const char *var, const char *value, void *cb) +static int git_branch_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { const char *slot_name; @@ -117,7 +118,10 @@ static int git_branch_config(const char *var, const char *value, void *cb) return 0; } - return git_color_default_config(var, value, cb); + if (git_color_config(var, value, cb) < 0) + return -1; + + return git_default_config(var, value, ctx, cb); } static const char *branch_get_color(enum color_branch ix) @@ -366,17 +370,8 @@ static const char *quote_literal_for_format(const char *s) static struct strbuf buf = STRBUF_INIT; strbuf_reset(&buf); - while (*s) { - const char *ep = strchrnul(s, '%'); - if (s < ep) - strbuf_add(&buf, s, ep - s); - if (*ep == '%') { - strbuf_addstr(&buf, "%%"); - s = ep + 1; - } else { - s = ep; - } - } + while (strbuf_expand_step(&buf, &s)) + strbuf_addstr(&buf, "%%"); return buf.buf; } @@ -674,7 +669,7 @@ static int edit_branch_description(const char *branch_name) exists = !read_branch_desc(&buf, branch_name); if (!buf.len || buf.buf[buf.len-1] != '\n') strbuf_addch(&buf, '\n'); - strbuf_commented_addf(&buf, + strbuf_commented_addf(&buf, comment_line_char, _("Please edit the description for the branch\n" " %s\n" "Lines starting with '%c' will be stripped.\n"), @@ -685,7 +680,7 @@ static int edit_branch_description(const char *branch_name) strbuf_release(&buf); return -1; } - strbuf_stripspace(&buf, 1); + strbuf_stripspace(&buf, comment_line_char); strbuf_addf(&name, "branch.%s.description", branch_name); if (buf.len || exists) @@ -832,6 +827,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (list) setup_auto_pager("branch", 1); + UNLEAK(sorting_options); + if (delete) { if (!argc) die(_("branch name required")); diff --git a/builtin/bundle.c b/builtin/bundle.c index 44113389d7..3f63631c03 100644 --- a/builtin/bundle.c +++ b/builtin/bundle.c @@ -6,7 +6,6 @@ #include "parse-options.h" #include "pkt-line.h" #include "repository.h" -#include "cache.h" #include "bundle.h" /* diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 0bafc14e6c..c9c93b80fc 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -4,11 +4,10 @@ * Copyright (C) Linus Torvalds, 2005 */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "alloc.h" #include "config.h" #include "convert.h" -#include "builtin.h" #include "diff.h" #include "environment.h" #include "gettext.h" @@ -22,7 +21,7 @@ #include "packfile.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "replace-object.h" #include "promisor-remote.h" #include "mailmap.h" @@ -42,7 +41,8 @@ struct batch_options { int all_objects; int unordered; int transform_mode; /* may be 'w' or 'c' for --filters or --textconv */ - int nul_terminated; + char input_delim; + char output_delim; const char *format; }; @@ -309,10 +309,8 @@ static int is_atom(const char *atom, const char *s, int slen) } static void expand_atom(struct strbuf *sb, const char *atom, int len, - void *vdata) + struct expand_data *data) { - struct expand_data *data = vdata; - if (is_atom("objectname", atom, len)) { if (!data->mark_query) strbuf_addstr(sb, oid_to_hex(&data->oid)); @@ -346,19 +344,21 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len, die("unknown format element: %.*s", len, atom); } -static size_t expand_format(struct strbuf *sb, const char *start, void *data) +static void expand_format(struct strbuf *sb, const char *start, + struct expand_data *data) { - const char *end; - - if (*start != '(') - return 0; - end = strchr(start + 1, ')'); - if (!end) - die("format element '%s' does not end in ')'", start); - - expand_atom(sb, start + 1, end - start - 1, data); - - return end - start + 1; + while (strbuf_expand_step(sb, &start)) { + const char *end; + + if (skip_prefix(start, "%", &start) || *start != '(') + strbuf_addch(sb, '%'); + else if (!(end = strchr(start + 1, ')'))) + die("format element '%s' does not end in ')'", start); + else { + expand_atom(sb, start + 1, end - start - 1, data); + start = end + 1; + } + } } static void batch_write(struct batch_options *opt, const void *data, int len) @@ -437,11 +437,12 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d } } -static void print_default_format(struct strbuf *scratch, struct expand_data *data) +static void print_default_format(struct strbuf *scratch, struct expand_data *data, + struct batch_options *opt) { - strbuf_addf(scratch, "%s %s %"PRIuMAX"\n", oid_to_hex(&data->oid), + strbuf_addf(scratch, "%s %s %"PRIuMAX"%c", oid_to_hex(&data->oid), type_name(data->type), - (uintmax_t)data->size); + (uintmax_t)data->size, opt->output_delim); } /* @@ -470,8 +471,8 @@ static void batch_object_write(const char *obj_name, &data->oid, &data->info, OBJECT_INFO_LOOKUP_REPLACE); if (ret < 0) { - printf("%s missing\n", - obj_name ? obj_name : oid_to_hex(&data->oid)); + printf("%s missing%c", + obj_name ? obj_name : oid_to_hex(&data->oid), opt->output_delim); fflush(stdout); return; } @@ -492,17 +493,17 @@ static void batch_object_write(const char *obj_name, strbuf_reset(scratch); if (!opt->format) { - print_default_format(scratch, data); + print_default_format(scratch, data, opt); } else { - strbuf_expand(scratch, opt->format, expand_format, data); - strbuf_addch(scratch, '\n'); + expand_format(scratch, opt->format, data); + strbuf_addch(scratch, opt->output_delim); } batch_write(opt, scratch->buf, scratch->len); if (opt->batch_mode == BATCH_MODE_CONTENTS) { print_object_or_die(opt, data); - batch_write(opt, "\n", 1); + batch_write(opt, &opt->output_delim, 1); } } @@ -520,22 +521,25 @@ static void batch_one_object(const char *obj_name, if (result != FOUND) { switch (result) { case MISSING_OBJECT: - printf("%s missing\n", obj_name); + printf("%s missing%c", obj_name, opt->output_delim); break; case SHORT_NAME_AMBIGUOUS: - printf("%s ambiguous\n", obj_name); + printf("%s ambiguous%c", obj_name, opt->output_delim); break; case DANGLING_SYMLINK: - printf("dangling %"PRIuMAX"\n%s\n", - (uintmax_t)strlen(obj_name), obj_name); + printf("dangling %"PRIuMAX"%c%s%c", + (uintmax_t)strlen(obj_name), + opt->output_delim, obj_name, opt->output_delim); break; case SYMLINK_LOOP: - printf("loop %"PRIuMAX"\n%s\n", - (uintmax_t)strlen(obj_name), obj_name); + printf("loop %"PRIuMAX"%c%s%c", + (uintmax_t)strlen(obj_name), + opt->output_delim, obj_name, opt->output_delim); break; case NOT_DIR: - printf("notdir %"PRIuMAX"\n%s\n", - (uintmax_t)strlen(obj_name), obj_name); + printf("notdir %"PRIuMAX"%c%s%c", + (uintmax_t)strlen(obj_name), + opt->output_delim, obj_name, opt->output_delim); break; default: BUG("unknown get_sha1_with_context result %d\n", @@ -547,9 +551,9 @@ static void batch_one_object(const char *obj_name, } if (ctx.mode == 0) { - printf("symlink %"PRIuMAX"\n%s\n", + printf("symlink %"PRIuMAX"%c%s%c", (uintmax_t)ctx.symlink_path.len, - ctx.symlink_path.buf); + opt->output_delim, ctx.symlink_path.buf, opt->output_delim); fflush(stdout); return; } @@ -694,20 +698,12 @@ static void batch_objects_command(struct batch_options *opt, struct queued_cmd *queued_cmd = NULL; size_t alloc = 0, nr = 0; - while (1) { - int i, ret; + while (strbuf_getdelim_strip_crlf(&input, stdin, opt->input_delim) != EOF) { + int i; const struct parse_cmd *cmd = NULL; const char *p = NULL, *cmd_end; struct queued_cmd call = {0}; - if (opt->nul_terminated) - ret = strbuf_getline_nul(&input, stdin); - else - ret = strbuf_getline(&input, stdin); - - if (ret) - break; - if (!input.len) die(_("empty command in input")); if (isspace(*input.buf)) @@ -777,9 +773,8 @@ static int batch_objects(struct batch_options *opt) */ memset(&data, 0, sizeof(data)); data.mark_query = 1; - strbuf_expand(&output, + expand_format(&output, opt->format ? opt->format : DEFAULT_FORMAT, - expand_format, &data); data.mark_query = 0; strbuf_release(&output); @@ -805,7 +800,7 @@ static int batch_objects(struct batch_options *opt) if (repo_has_promisor_remote(the_repository)) warning("This repository uses promisor remotes. Some objects may not be loaded."); - read_replace_refs = 0; + disable_replace_refs(); cb.opt = opt; cb.expand = &data; @@ -851,16 +846,7 @@ static int batch_objects(struct batch_options *opt) goto cleanup; } - while (1) { - int ret; - if (opt->nul_terminated) - ret = strbuf_getline_nul(&input, stdin); - else - ret = strbuf_getline(&input, stdin); - - if (ret == EOF) - break; - + while (strbuf_getdelim_strip_crlf(&input, stdin, opt->input_delim) != EOF) { if (data.split_on_whitespace) { /* * Split at first whitespace, tying off the beginning @@ -885,12 +871,13 @@ static int batch_objects(struct batch_options *opt) return retval; } -static int git_cat_file_config(const char *var, const char *value, void *cb) +static int git_cat_file_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (userdiff_config(var, value) < 0) return -1; - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } static int batch_option_callback(const struct option *opt, @@ -929,6 +916,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) const char *exp_type = NULL, *obj_name = NULL; struct batch_options batch = {0}; int unknown_type = 0; + int input_nul_terminated = 0; + int nul_terminated = 0; const char * const usage[] = { N_("git cat-file <type> <object>"), @@ -936,7 +925,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) N_("git cat-file (-t | -s) [--allow-unknown-type] <object>"), N_("git cat-file (--batch | --batch-check | --batch-command) [--batch-all-objects]\n" " [--buffer] [--follow-symlinks] [--unordered]\n" - " [--textconv | --filters] [-z]"), + " [--textconv | --filters] [-Z]"), N_("git cat-file (--textconv | --filters)\n" " [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"), NULL @@ -965,7 +954,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) N_("like --batch, but don't emit <contents>"), PARSE_OPT_OPTARG | PARSE_OPT_NONEG, batch_option_callback), - OPT_BOOL('z', NULL, &batch.nul_terminated, N_("stdin is NUL-terminated")), + OPT_BOOL_F('z', NULL, &input_nul_terminated, N_("stdin is NUL-terminated"), + PARSE_OPT_HIDDEN), + OPT_BOOL('Z', NULL, &nul_terminated, N_("stdin and stdout is NUL-terminated")), OPT_CALLBACK_F(0, "batch-command", &batch, N_("format"), N_("read commands from stdin"), PARSE_OPT_OPTARG | PARSE_OPT_NONEG, @@ -1024,9 +1015,18 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) else if (batch.all_objects) usage_msg_optf(_("'%s' requires a batch mode"), usage, options, "--batch-all-objects"); - else if (batch.nul_terminated) + else if (input_nul_terminated) usage_msg_optf(_("'%s' requires a batch mode"), usage, options, "-z"); + else if (nul_terminated) + usage_msg_optf(_("'%s' requires a batch mode"), usage, options, + "-Z"); + + batch.input_delim = batch.output_delim = '\n'; + if (input_nul_terminated) + batch.input_delim = '\0'; + if (nul_terminated) + batch.input_delim = batch.output_delim = '\0'; /* Batch defaults */ if (batch.buffer_output < 0) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index e27b86d150..b22ff748c3 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -1,6 +1,5 @@ #define USE_THE_INDEX_VARIABLE #include "builtin.h" -#include "cache.h" #include "config.h" #include "attr.h" #include "environment.h" diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index e4b78782a3..906cd96753 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -1,6 +1,5 @@ #define USE_THE_INDEX_VARIABLE #include "builtin.h" -#include "cache.h" #include "config.h" #include "dir.h" #include "gettext.h" diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c index 002d2941e9..b8a05b8e07 100644 --- a/builtin/check-mailmap.c +++ b/builtin/check-mailmap.c @@ -4,6 +4,7 @@ #include "ident.h" #include "mailmap.h" #include "parse-options.h" +#include "strbuf.h" #include "string-list.h" #include "write-or-die.h" diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index 57f0505070..5eb6bdc3f6 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -2,9 +2,8 @@ * GIT - The information manager from hell */ -#include "cache.h" -#include "refs.h" #include "builtin.h" +#include "refs.h" #include "setup.h" #include "strbuf.h" diff --git a/builtin/checkout--worker.c b/builtin/checkout--worker.c index 2120dd1d30..c655dc4b13 100644 --- a/builtin/checkout--worker.c +++ b/builtin/checkout--worker.c @@ -6,6 +6,7 @@ #include "parallel-checkout.h" #include "parse-options.h" #include "pkt-line.h" +#include "read-cache-ll.h" static void packet_to_pc_item(const char *buffer, int len, struct parallel_checkout_item *pc_item) diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 9375a05539..f62f13f2b5 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -16,7 +16,9 @@ #include "parse-options.h" #include "entry.h" #include "parallel-checkout.h" +#include "read-cache-ll.h" #include "setup.h" +#include "sparse-index.h" #define CHECKOUT_ALL 4 static int nul_term_line; diff --git a/builtin/checkout.c b/builtin/checkout.c index 715eeb5048..2ff9625644 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -13,13 +13,16 @@ #include "gettext.h" #include "hex.h" #include "hook.h" -#include "ll-merge.h" +#include "merge-ll.h" #include "lockfile.h" #include "mem-pool.h" #include "merge-recursive.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "parse-options.h" +#include "path.h" +#include "preload-index.h" +#include "read-cache.h" #include "refs.h" #include "remote.h" #include "resolve-undo.h" @@ -861,7 +864,7 @@ static int merge_working_tree(const struct checkout_opts *opts, * entries in the index. */ - add_files_to_cache(NULL, NULL, 0); + add_files_to_cache(the_repository, NULL, NULL, 0, 0); init_merge_options(&o, the_repository); o.verbosity = 0; work = write_in_core_index_as_tree(the_repository); @@ -1186,7 +1189,8 @@ static int switch_branches(const struct checkout_opts *opts, return ret || writeout_error; } -static int git_checkout_config(const char *var, const char *value, void *cb) +static int git_checkout_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { struct checkout_opts *opts = cb; @@ -1202,7 +1206,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb) if (starts_with(var, "submodule.")) return git_default_submodule_config(var, value, NULL); - return git_xmerge_config(var, value, NULL); + return git_xmerge_config(var, value, ctx, NULL); } static void setup_new_branch_info_and_source_tree( @@ -1689,8 +1693,13 @@ static int checkout_main(int argc, const char **argv, const char *prefix, } if (opts->conflict_style) { + struct key_value_info kvi = KVI_INIT; + struct config_context ctx = { + .kvi = &kvi, + }; opts->merge = 1; /* implied */ - git_xmerge_config("merge.conflictstyle", opts->conflict_style, NULL); + git_xmerge_config("merge.conflictstyle", opts->conflict_style, + &ctx, NULL); } if (opts->force) { opts->discard_changes = 1; diff --git a/builtin/clean.c b/builtin/clean.c index 78852d28ce..49c224e626 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -9,11 +9,12 @@ #define USE_THE_INDEX_VARIABLE #include "builtin.h" #include "abspath.h" -#include "cache.h" #include "config.h" #include "dir.h" #include "gettext.h" #include "parse-options.h" +#include "path.h" +#include "read-cache-ll.h" #include "repository.h" #include "setup.h" #include "string-list.h" @@ -103,7 +104,8 @@ struct menu_stuff { define_list_config_array(color_interactive_slots); -static int git_clean_config(const char *var, const char *value, void *cb) +static int git_clean_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { const char *slot_name; @@ -130,8 +132,10 @@ static int git_clean_config(const char *var, const char *value, void *cb) return 0; } - /* inspect the color.ui config variable and others */ - return git_color_default_config(var, value, cb); + if (git_color_config(var, value, cb) < 0) + return -1; + + return git_default_config(var, value, ctx, cb); } static const char *clean_get_color(enum color_clean ix) diff --git a/builtin/clone.c b/builtin/clone.c index 15f9912b4c..da35f1a6b4 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -23,7 +23,7 @@ #include "refs.h" #include "refspec.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "tree.h" #include "tree-walk.h" #include "unpack-trees.h" @@ -39,6 +39,7 @@ #include "setup.h" #include "connected.h" #include "packfile.h" +#include "path.h" #include "pkt-line.h" #include "list-objects-filter-options.h" #include "hook.h" @@ -790,7 +791,8 @@ static int checkout(int submodule_progress, int filter_submodules) return err; } -static int git_clone_config(const char *k, const char *v, void *cb) +static int git_clone_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { if (!strcmp(k, "clone.defaultremotename")) { free(remote_name); @@ -801,17 +803,19 @@ static int git_clone_config(const char *k, const char *v, void *cb) if (!strcmp(k, "clone.filtersubmodules")) config_filter_submodules = git_config_bool(k, v); - return git_default_config(k, v, cb); + return git_default_config(k, v, ctx, cb); } -static int write_one_config(const char *key, const char *value, void *data) +static int write_one_config(const char *key, const char *value, + const struct config_context *ctx, + void *data) { /* * give git_clone_config a chance to write config values back to the * environment, since git_config_set_multivar_gently only deals with * config-file writes */ - int apply_failed = git_clone_config(key, value, data); + int apply_failed = git_clone_config(key, value, ctx, data); if (apply_failed) return apply_failed; @@ -930,6 +934,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) int submodule_progress; int filter_submodules = 0; int hash_algo; + const int do_not_override_repo_unix_permissions = -1; struct transport_ls_refs_options transport_ls_refs_options = TRANSPORT_LS_REFS_OPTIONS_INIT; @@ -1097,7 +1102,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL, - INIT_DB_QUIET); + do_not_override_repo_unix_permissions, INIT_DB_QUIET); if (real_git_dir) { free((char *)git_dir); diff --git a/builtin/column.c b/builtin/column.c index de623a16c2..a83be8bc99 100644 --- a/builtin/column.c +++ b/builtin/column.c @@ -1,5 +1,4 @@ #include "builtin.h" -#include "cache.h" #include "config.h" #include "gettext.h" #include "strbuf.h" @@ -13,7 +12,8 @@ static const char * const builtin_column_usage[] = { }; static unsigned int colopts; -static int column_config(const char *var, const char *value, void *cb) +static int column_config(const char *var, const char *value, + const struct config_context *ctx UNUSED, void *cb) { return git_column_config(var, value, cb, &colopts); } diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index a3d00fa232..c88389df24 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -1,4 +1,5 @@ #include "builtin.h" +#include "commit.h" #include "config.h" #include "dir.h" #include "environment.h" @@ -8,7 +9,7 @@ #include "parse-options.h" #include "repository.h" #include "commit-graph.h" -#include "object-store.h" +#include "object-store-ll.h" #include "progress.h" #include "replace-object.h" #include "tag.h" @@ -186,10 +187,11 @@ static int write_option_max_new_filters(const struct option *opt, } static int git_commit_graph_write_config(const char *var, const char *value, + const struct config_context *ctx, void *cb UNUSED) { if (!strcmp(var, "commitgraph.maxnewfilters")) - write_opts.max_new_filters = git_config_int(var, value); + write_opts.max_new_filters = git_config_int(var, value, ctx->kvi); /* * No need to fall-back to 'git_default_config', since this was already * called in 'cmd_commit_graph()'. @@ -324,7 +326,7 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix) git_config(git_default_config, NULL); - read_replace_refs = 0; + disable_replace_refs(); save_commit_buffer = 0; argc = parse_options(argc, argv, prefix, options, diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index d1d251c3de..02625e7176 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -3,16 +3,15 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "gettext.h" #include "hex.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "repository.h" #include "commit.h" #include "tree.h" -#include "builtin.h" #include "utf8.h" #include "gpg-interface.h" #include "parse-options.h" diff --git a/builtin/commit.c b/builtin/commit.c index e67c4be221..7da5f92448 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -6,7 +6,7 @@ */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "advice.h" #include "config.h" #include "lockfile.h" @@ -15,7 +15,6 @@ #include "dir.h" #include "editor.h" #include "environment.h" -#include "builtin.h" #include "diff.h" #include "diffcore.h" #include "commit.h" @@ -30,6 +29,9 @@ #include "utf8.h" #include "object-name.h" #include "parse-options.h" +#include "path.h" +#include "preload-index.h" +#include "read-cache.h" #include "string-list.h" #include "rerere.h" #include "unpack-trees.h" @@ -38,6 +40,7 @@ #include "gpg-interface.h" #include "column.h" #include "sequencer.h" +#include "sparse-index.h" #include "mailmap.h" #include "help.h" #include "commit-reach.h" @@ -447,7 +450,8 @@ static const char *prepare_index(const char **argv, const char *prefix, if (all || (also && pathspec.nr)) { repo_hold_locked_index(the_repository, &index_lock, LOCK_DIE_ON_ERROR); - add_files_to_cache(also ? prefix : NULL, &pathspec, 0); + add_files_to_cache(the_repository, also ? prefix : NULL, + &pathspec, 0, 0); refresh_cache_or_die(refresh_flags); cache_tree_update(&the_index, WRITE_TREE_SILENT); if (write_locked_index(&the_index, &index_lock, 0)) @@ -763,7 +767,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct commit *c; c = lookup_commit_reference_by_name(squash_message); if (!c) - die(_("could not lookup commit %s"), squash_message); + die(_("could not lookup commit '%s'"), squash_message); ctx.output_encoding = get_commit_output_encoding(); repo_format_commit_message(the_repository, c, "squash! %s\n\n", &sb, @@ -798,7 +802,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, char *fmt; commit = lookup_commit_reference_by_name(fixup_commit); if (!commit) - die(_("could not lookup commit %s"), fixup_commit); + die(_("could not lookup commit '%s'"), fixup_commit); ctx.output_encoding = get_commit_output_encoding(); fmt = xstrfmt("%s! %%s\n\n", fixup_prefix); repo_format_commit_message(the_repository, commit, fmt, &sb, @@ -893,7 +897,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, s->hints = 0; if (clean_message_contents) - strbuf_stripspace(&sb, 0); + strbuf_stripspace(&sb, '\0'); if (signoff) append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0); @@ -998,11 +1002,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct object_id oid; const char *parent = "HEAD"; - if (!the_index.cache_nr) { - discard_index(&the_index); - if (repo_read_index(the_repository) < 0) - die(_("Cannot read index")); - } + if (!the_index.initialized && repo_read_index(the_repository) < 0) + die(_("Cannot read index")); if (amend) parent = "HEAD^1"; @@ -1043,7 +1044,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct child_process run_trailer = CHILD_PROCESS_INIT; strvec_pushl(&run_trailer.args, "interpret-trailers", - "--in-place", git_path_commit_editmsg(), NULL); + "--in-place", "--no-divider", + git_path_commit_editmsg(), NULL); strvec_pushv(&run_trailer.args, trailer_args.v); run_trailer.git_cmd = 1; if (run_command(&run_trailer)) @@ -1189,7 +1191,7 @@ static const char *read_commit_message(const char *name) commit = lookup_commit_reference_by_name(name); if (!commit) - die(_("could not lookup commit %s"), name); + die(_("could not lookup commit '%s'"), name); out_enc = get_commit_output_encoding(); return repo_logmsg_reencode(the_repository, commit, NULL, out_enc); } @@ -1405,7 +1407,8 @@ static int parse_status_slot(const char *slot) return LOOKUP_CONFIG(color_status_slots, slot); } -static int git_status_config(const char *k, const char *v, void *cb) +static int git_status_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { struct wt_status *s = cb; const char *slot_name; @@ -1414,7 +1417,8 @@ static int git_status_config(const char *k, const char *v, void *cb) return git_column_config(k, v, "status", &s->colopts); if (!strcmp(k, "status.submodulesummary")) { int is_bool; - s->submodule_summary = git_config_bool_or_int(k, v, &is_bool); + s->submodule_summary = git_config_bool_or_int(k, v, ctx->kvi, + &is_bool); if (is_bool && s->submodule_summary) s->submodule_summary = -1; return 0; @@ -1474,11 +1478,11 @@ static int git_status_config(const char *k, const char *v, void *cb) } if (!strcmp(k, "diff.renamelimit")) { if (s->rename_limit == -1) - s->rename_limit = git_config_int(k, v); + s->rename_limit = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "status.renamelimit")) { - s->rename_limit = git_config_int(k, v); + s->rename_limit = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "diff.renames")) { @@ -1490,7 +1494,7 @@ static int git_status_config(const char *k, const char *v, void *cb) s->detect_rename = git_config_rename(k, v); return 0; } - return git_diff_ui_config(k, v, NULL); + return git_diff_ui_config(k, v, ctx, NULL); } int cmd_status(int argc, const char **argv, const char *prefix) @@ -1605,7 +1609,8 @@ int cmd_status(int argc, const char **argv, const char *prefix) return 0; } -static int git_commit_config(const char *k, const char *v, void *cb) +static int git_commit_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { struct wt_status *s = cb; @@ -1623,11 +1628,12 @@ static int git_commit_config(const char *k, const char *v, void *cb) } if (!strcmp(k, "commit.verbose")) { int is_bool; - config_commit_verbose = git_config_bool_or_int(k, v, &is_bool); + config_commit_verbose = git_config_bool_or_int(k, v, ctx->kvi, + &is_bool); return 0; } - return git_status_config(k, v, s); + return git_status_config(k, v, ctx, s); } int cmd_commit(int argc, const char **argv, const char *prefix) diff --git a/builtin/config.c b/builtin/config.c index ff2fe8ef12..1c75cbc43d 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -5,6 +5,7 @@ #include "color.h" #include "editor.h" #include "environment.h" +#include "repository.h" #include "gettext.h" #include "ident.h" #include "parse-options.h" @@ -12,6 +13,7 @@ #include "path.h" #include "quote.h" #include "setup.h" +#include "strbuf.h" #include "worktree.h" #include "wrapper.h" @@ -193,37 +195,42 @@ static void check_argc(int argc, int min, int max) usage_builtin_config(); } -static void show_config_origin(struct strbuf *buf) +static void show_config_origin(const struct key_value_info *kvi, + struct strbuf *buf) { const char term = end_nul ? '\0' : '\t'; - strbuf_addstr(buf, current_config_origin_type()); + strbuf_addstr(buf, config_origin_type_name(kvi->origin_type)); strbuf_addch(buf, ':'); if (end_nul) - strbuf_addstr(buf, current_config_name()); + strbuf_addstr(buf, kvi->filename ? kvi->filename : ""); else - quote_c_style(current_config_name(), buf, NULL, 0); + quote_c_style(kvi->filename ? kvi->filename : "", buf, NULL, 0); strbuf_addch(buf, term); } -static void show_config_scope(struct strbuf *buf) +static void show_config_scope(const struct key_value_info *kvi, + struct strbuf *buf) { const char term = end_nul ? '\0' : '\t'; - const char *scope = config_scope_name(current_config_scope()); + const char *scope = config_scope_name(kvi->scope); strbuf_addstr(buf, N_(scope)); strbuf_addch(buf, term); } static int show_all_config(const char *key_, const char *value_, + const struct config_context *ctx, void *cb UNUSED) { + const struct key_value_info *kvi = ctx->kvi; + if (show_origin || show_scope) { struct strbuf buf = STRBUF_INIT; if (show_scope) - show_config_scope(&buf); + show_config_scope(kvi, &buf); if (show_origin) - show_config_origin(&buf); + show_config_origin(kvi, &buf); /* Use fwrite as "buf" can contain \0's if "end_null" is set. */ fwrite(buf.buf, 1, buf.len, stdout); strbuf_release(&buf); @@ -241,12 +248,13 @@ struct strbuf_list { int alloc; }; -static int format_config(struct strbuf *buf, const char *key_, const char *value_) +static int format_config(struct strbuf *buf, const char *key_, + const char *value_, const struct key_value_info *kvi) { if (show_scope) - show_config_scope(buf); + show_config_scope(kvi, buf); if (show_origin) - show_config_origin(buf); + show_config_origin(kvi, buf); if (show_keys) strbuf_addstr(buf, key_); if (!omit_values) { @@ -255,13 +263,14 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value if (type == TYPE_INT) strbuf_addf(buf, "%"PRId64, - git_config_int64(key_, value_ ? value_ : "")); + git_config_int64(key_, value_ ? value_ : "", kvi)); else if (type == TYPE_BOOL) strbuf_addstr(buf, git_config_bool(key_, value_) ? "true" : "false"); else if (type == TYPE_BOOL_OR_INT) { int is_bool, v; - v = git_config_bool_or_int(key_, value_, &is_bool); + v = git_config_bool_or_int(key_, value_, kvi, + &is_bool); if (is_bool) strbuf_addstr(buf, v ? "true" : "false"); else @@ -300,9 +309,11 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value return 0; } -static int collect_config(const char *key_, const char *value_, void *cb) +static int collect_config(const char *key_, const char *value_, + const struct config_context *ctx, void *cb) { struct strbuf_list *values = cb; + const struct key_value_info *kvi = ctx->kvi; if (!use_key_regexp && strcmp(key_, key)) return 0; @@ -317,7 +328,7 @@ static int collect_config(const char *key_, const char *value_, void *cb) ALLOC_GROW(values->items, values->nr + 1, values->alloc); strbuf_init(&values->items[values->nr], 0); - return format_config(&values->items[values->nr++], key_, value_); + return format_config(&values->items[values->nr++], key_, value_, kvi); } static int get_value(const char *key_, const char *regex_, unsigned flags) @@ -375,14 +386,18 @@ static int get_value(const char *key_, const char *regex_, unsigned flags) } config_with_options(collect_config, &values, - &given_config_source, &config_options); + &given_config_source, the_repository, + &config_options); if (!values.nr && default_value) { + struct key_value_info kvi = KVI_INIT; struct strbuf *item; + + kvi_from_param(&kvi); ALLOC_GROW(values.items, values.nr + 1, values.alloc); item = &values.items[values.nr++]; strbuf_init(item, 0); - if (format_config(item, key_, default_value) < 0) + if (format_config(item, key_, default_value, &kvi) < 0) die(_("failed to format default config value: %s"), default_value); } @@ -411,7 +426,8 @@ free_strings: return ret; } -static char *normalize_value(const char *key, const char *value) +static char *normalize_value(const char *key, const char *value, + struct key_value_info *kvi) { if (!value) return NULL; @@ -426,12 +442,12 @@ static char *normalize_value(const char *key, const char *value) */ return xstrdup(value); if (type == TYPE_INT) - return xstrfmt("%"PRId64, git_config_int64(key, value)); + return xstrfmt("%"PRId64, git_config_int64(key, value, kvi)); if (type == TYPE_BOOL) return xstrdup(git_config_bool(key, value) ? "true" : "false"); if (type == TYPE_BOOL_OR_INT) { int is_bool, v; - v = git_config_bool_or_int(key, value, &is_bool); + v = git_config_bool_or_int(key, value, kvi, &is_bool); if (!is_bool) return xstrfmt("%d", v); else @@ -468,6 +484,7 @@ static const char *get_colorbool_slot; static char parsed_color[COLOR_MAXLEN]; static int git_get_color_config(const char *var, const char *value, + const struct config_context *ctx UNUSED, void *cb UNUSED) { if (!strcmp(var, get_color_slot)) { @@ -486,7 +503,8 @@ static void get_color(const char *var, const char *def_color) get_color_found = 0; parsed_color[0] = '\0'; config_with_options(git_get_color_config, NULL, - &given_config_source, &config_options); + &given_config_source, the_repository, + &config_options); if (!get_color_found && def_color) { if (color_parse(def_color, parsed_color) < 0) @@ -500,6 +518,7 @@ static int get_colorbool_found; static int get_diff_color_found; static int get_color_ui_found; static int git_get_colorbool_config(const char *var, const char *value, + const struct config_context *ctx UNUSED, void *data UNUSED) { if (!strcmp(var, get_colorbool_slot)) @@ -518,7 +537,8 @@ static int get_colorbool(const char *var, int print) get_diff_color_found = -1; get_color_ui_found = -1; config_with_options(git_get_colorbool_config, NULL, - &given_config_source, &config_options); + &given_config_source, the_repository, + &config_options); if (get_colorbool_found < 0) { if (!strcmp(get_colorbool_slot, "color.diff")) @@ -555,13 +575,17 @@ static void check_write(void) struct urlmatch_current_candidate_value { char value_is_null; struct strbuf value; + struct key_value_info kvi; }; -static int urlmatch_collect_fn(const char *var, const char *value, void *cb) +static int urlmatch_collect_fn(const char *var, const char *value, + const struct config_context *ctx, + void *cb) { struct string_list *values = cb; struct string_list_item *item = string_list_insert(values, var); struct urlmatch_current_candidate_value *matched = item->util; + const struct key_value_info *kvi = ctx->kvi; if (!matched) { matched = xmalloc(sizeof(*matched)); @@ -570,6 +594,7 @@ static int urlmatch_collect_fn(const char *var, const char *value, void *cb) } else { strbuf_reset(&matched->value); } + matched->kvi = *kvi; if (value) { strbuf_addstr(&matched->value, value); @@ -607,7 +632,8 @@ static int get_urlmatch(const char *var, const char *url) } config_with_options(urlmatch_config_entry, &config, - &given_config_source, &config_options); + &given_config_source, the_repository, + &config_options); ret = !values.nr; @@ -616,7 +642,8 @@ static int get_urlmatch(const char *var, const char *url) struct strbuf buf = STRBUF_INIT; format_config(&buf, item->string, - matched->value_is_null ? NULL : matched->value.buf); + matched->value_is_null ? NULL : matched->value.buf, + &matched->kvi); fwrite(buf.buf, 1, buf.len, stdout); strbuf_release(&buf); @@ -650,6 +677,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) char *value = NULL; int flags = 0; int ret = 0; + struct key_value_info default_kvi = KVI_INIT; given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT)); @@ -713,7 +741,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) given_config_source.scope = CONFIG_SCOPE_LOCAL; } else if (use_worktree_config) { struct worktree **worktrees = get_worktrees(); - if (repository_format_worktree_config) + if (the_repository->repository_format_worktree_config) given_config_source.file = git_pathdup("config.worktree"); else if (worktrees[0] && worktrees[1]) die(_("--worktree cannot be used with multiple " @@ -827,7 +855,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) if (actions == ACTION_LIST) { check_argc(argc, 0, 0); if (config_with_options(show_all_config, NULL, - &given_config_source, + &given_config_source, the_repository, &config_options) < 0) { if (given_config_source.file) die_errno(_("unable to read config file '%s'"), @@ -867,7 +895,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (actions == ACTION_SET) { check_write(); check_argc(argc, 2, 2); - value = normalize_value(argv[0], argv[1]); + value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value); if (ret == CONFIG_NOTHING_SET) error(_("cannot overwrite multiple values with a single value\n" @@ -876,7 +904,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (actions == ACTION_SET_ALL) { check_write(); check_argc(argc, 2, 3); - value = normalize_value(argv[0], argv[1]); + value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, argv[2], flags); @@ -884,7 +912,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (actions == ACTION_ADD) { check_write(); check_argc(argc, 2, 2); - value = normalize_value(argv[0], argv[1]); + value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, CONFIG_REGEX_NONE, @@ -893,7 +921,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (actions == ACTION_REPLACE_ALL) { check_write(); check_argc(argc, 2, 3); - value = normalize_value(argv[0], argv[1]); + value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, argv[2], flags | CONFIG_FLAGS_MULTI_REPLACE); diff --git a/builtin/count-objects.c b/builtin/count-objects.c index f3d8f1bcbb..97cdfb0ac5 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -4,17 +4,17 @@ * Copyright (c) 2006 Junio C Hamano */ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "dir.h" #include "environment.h" #include "gettext.h" +#include "path.h" #include "repository.h" -#include "builtin.h" #include "parse-options.h" #include "quote.h" #include "packfile.h" -#include "object-store.h" +#include "object-store-ll.h" static unsigned long garbage; static off_t size_garbage; diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c index 756c5f02ae..dc1cf2d25f 100644 --- a/builtin/credential-cache--daemon.c +++ b/builtin/credential-cache--daemon.c @@ -38,19 +38,22 @@ static struct credential_cache_entry *lookup_credential(const struct credential int i; for (i = 0; i < entries_nr; i++) { struct credential *e = &entries[i].item; - if (credential_match(c, e)) + if (credential_match(c, e, 0)) return &entries[i]; } return NULL; } -static void remove_credential(const struct credential *c) +static void remove_credential(const struct credential *c, int match_password) { struct credential_cache_entry *e; - e = lookup_credential(c); - if (e) - e->expiration = 0; + int i; + for (i = 0; i < entries_nr; i++) { + e = &entries[i]; + if (credential_match(c, &e->item, match_password)) + e->expiration = 0; + } } static timestamp_t check_expirations(void) @@ -151,14 +154,14 @@ static void serve_one_client(FILE *in, FILE *out) exit(0); } else if (!strcmp(action.buf, "erase")) - remove_credential(&c); + remove_credential(&c, 1); else if (!strcmp(action.buf, "store")) { if (timeout < 0) warning("cache client didn't specify a timeout"); else if (!c.username || !c.password) warning("cache client gave us a partial credential"); else { - remove_credential(&c); + remove_credential(&c, 0); cache_credential(&c, timeout); } } diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c index 0ffacfdd83..ff3a47badb 100644 --- a/builtin/credential-cache.c +++ b/builtin/credential-cache.c @@ -2,6 +2,7 @@ #include "gettext.h" #include "parse-options.h" #include "path.h" +#include "strbuf.h" #include "wrapper.h" #include "write-or-die.h" diff --git a/builtin/credential-store.c b/builtin/credential-store.c index 30c6ccf56c..4a492411bb 100644 --- a/builtin/credential-store.c +++ b/builtin/credential-store.c @@ -13,7 +13,8 @@ static struct lock_file credential_lock; static int parse_credential_file(const char *fn, struct credential *c, void (*match_cb)(struct credential *), - void (*other_cb)(struct strbuf *)) + void (*other_cb)(struct strbuf *), + int match_password) { FILE *fh; struct strbuf line = STRBUF_INIT; @@ -30,7 +31,7 @@ static int parse_credential_file(const char *fn, while (strbuf_getline_lf(&line, fh) != EOF) { if (!credential_from_url_gently(&entry, line.buf, 1) && entry.username && entry.password && - credential_match(c, &entry)) { + credential_match(c, &entry, match_password)) { found_credential = 1; if (match_cb) { match_cb(&entry); @@ -60,7 +61,7 @@ static void print_line(struct strbuf *buf) } static void rewrite_credential_file(const char *fn, struct credential *c, - struct strbuf *extra) + struct strbuf *extra, int match_password) { int timeout_ms = 1000; @@ -69,11 +70,30 @@ static void rewrite_credential_file(const char *fn, struct credential *c, die_errno(_("unable to get credential storage lock in %d ms"), timeout_ms); if (extra) print_line(extra); - parse_credential_file(fn, c, NULL, print_line); + parse_credential_file(fn, c, NULL, print_line, match_password); if (commit_lock_file(&credential_lock) < 0) die_errno("unable to write credential store"); } +static int is_rfc3986_unreserved(char ch) +{ + return isalnum(ch) || + ch == '-' || ch == '_' || ch == '.' || ch == '~'; +} + +static int is_rfc3986_reserved_or_unreserved(char ch) +{ + if (is_rfc3986_unreserved(ch)) + return 1; + switch (ch) { + case '!': case '*': case '\'': case '(': case ')': case ';': + case ':': case '@': case '&': case '=': case '+': case '$': + case ',': case '/': case '?': case '#': case '[': case ']': + return 1; + } + return 0; +} + static void store_credential_file(const char *fn, struct credential *c) { struct strbuf buf = STRBUF_INIT; @@ -91,7 +111,7 @@ static void store_credential_file(const char *fn, struct credential *c) is_rfc3986_reserved_or_unreserved); } - rewrite_credential_file(fn, c, &buf); + rewrite_credential_file(fn, c, &buf, 0); strbuf_release(&buf); } @@ -138,7 +158,7 @@ static void remove_credential(const struct string_list *fns, struct credential * return; for_each_string_list_item(fn, fns) if (!access(fn->string, F_OK)) - rewrite_credential_file(fn->string, c, NULL); + rewrite_credential_file(fn->string, c, NULL, 1); } static void lookup_credential(const struct string_list *fns, struct credential *c) @@ -146,7 +166,7 @@ static void lookup_credential(const struct string_list *fns, struct credential * struct string_list_item *fn; for_each_string_list_item(fn, fns) - if (parse_credential_file(fn->string, c, print_entry, NULL)) + if (parse_credential_file(fn->string, c, print_entry, NULL, 0)) return; /* Found credential */ } diff --git a/builtin/describe.c b/builtin/describe.c index 55b4baaa22..7ce23e1b8e 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -1,5 +1,5 @@ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "config.h" #include "environment.h" #include "gettext.h" @@ -9,19 +9,20 @@ #include "tag.h" #include "blob.h" #include "refs.h" -#include "builtin.h" #include "exec-cmd.h" #include "object-name.h" #include "parse-options.h" +#include "read-cache-ll.h" #include "revision.h" #include "diff.h" #include "hashmap.h" #include "setup.h" #include "strvec.h" #include "run-command.h" -#include "object-store.h" +#include "object-store-ll.h" #include "list-objects.h" #include "commit-slab.h" +#include "wildmatch.h" #define MAX_TAGS (FLAG_BITS - 1) diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 360464e6ef..50330b8dd2 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -3,13 +3,14 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "diff.h" #include "diff-merges.h" #include "commit.h" +#include "preload-index.h" +#include "repository.h" #include "revision.h" -#include "builtin.h" #include "submodule.h" static const char diff_files_usage[] = diff --git a/builtin/diff-index.c b/builtin/diff-index.c index b9a19bb7d3..9db7139b83 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -1,11 +1,13 @@ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "diff.h" #include "diff-merges.h" #include "commit.h" +#include "preload-index.h" +#include "repository.h" #include "revision.h" -#include "builtin.h" #include "setup.h" +#include "sparse-index.h" #include "submodule.h" static const char diff_cache_usage[] = diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 0b02c62b85..d62caa6c8b 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -1,14 +1,15 @@ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "config.h" #include "diff.h" #include "commit.h" #include "gettext.h" #include "hex.h" #include "log-tree.h" -#include "builtin.h" #include "submodule.h" +#include "read-cache-ll.h" #include "repository.h" +#include "revision.h" #include "tree.h" static struct rev_info log_tree_opt; @@ -122,6 +123,10 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) usage(diff_tree_usage); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ + + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + repo_init_revisions(the_repository, opt, prefix); if (repo_read_index(the_repository) < 0) die(_("index file corrupt")); diff --git a/builtin/diff.c b/builtin/diff.c index 7b64659fe7..b19530c996 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -4,7 +4,7 @@ * Copyright (c) 2006 Junio C Hamano */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "config.h" #include "ewah/ewok.h" #include "lockfile.h" @@ -16,9 +16,10 @@ #include "diff.h" #include "diff-merges.h" #include "diffcore.h" +#include "preload-index.h" +#include "read-cache-ll.h" #include "revision.h" #include "log-tree.h" -#include "builtin.h" #include "setup.h" #include "submodule.h" #include "oid-array.h" diff --git a/builtin/difftool.c b/builtin/difftool.c index 0049342f5c..24d88f88ba 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -12,22 +12,23 @@ * Copyright (C) 2016 Johannes Schindelin */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "abspath.h" #include "config.h" #include "copy.h" -#include "builtin.h" #include "run-command.h" #include "environment.h" #include "exec-cmd.h" #include "gettext.h" #include "hex.h" #include "parse-options.h" +#include "read-cache-ll.h" +#include "sparse-index.h" #include "strvec.h" #include "strbuf.h" #include "lockfile.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "dir.h" #include "entry.h" #include "setup.h" @@ -40,14 +41,15 @@ static const char *const builtin_difftool_usage[] = { NULL }; -static int difftool_config(const char *var, const char *value, void *cb) +static int difftool_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "difftool.trustexitcode")) { trust_exit_code = git_config_bool(var, value); return 0; } - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } static int print_tool_help(void) diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 9a95f6a1a8..56dc69fac1 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -4,14 +4,13 @@ * Copyright (C) 2007 Johannes E. Schindelin */ #include "builtin.h" -#include "cache.h" #include "config.h" #include "gettext.h" #include "hex.h" #include "refs.h" #include "refspec.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "commit.h" #include "object.h" #include "tag.h" diff --git a/builtin/fast-import.c b/builtin/fast-import.c index bbd9b2b3e7..2ee19c7373 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -1,6 +1,5 @@ #include "builtin.h" #include "abspath.h" -#include "cache.h" #include "environment.h" #include "gettext.h" #include "hex.h" @@ -13,6 +12,7 @@ #include "commit.h" #include "delta.h" #include "pack.h" +#include "path.h" #include "refs.h" #include "csum-file.h" #include "quote.h" @@ -21,7 +21,7 @@ #include "packfile.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "mem-pool.h" #include "commit-reach.h" #include "khash.h" diff --git a/builtin/fetch.c b/builtin/fetch.c index 849a9be421..a01ecad574 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1,7 +1,7 @@ /* * "git fetch" */ -#include "cache.h" +#include "builtin.h" #include "advice.h" #include "config.h" #include "gettext.h" @@ -11,11 +11,10 @@ #include "refs.h" #include "refspec.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "oidset.h" #include "oid-array.h" #include "commit.h" -#include "builtin.h" #include "string-list.h" #include "remote.h" #include "transport.h" @@ -29,6 +28,7 @@ #include "utf8.h" #include "packfile.h" #include "pager.h" +#include "path.h" #include "pkt-line.h" #include "list-objects-filter-options.h" #include "commit-reach.h" @@ -58,7 +58,6 @@ enum { }; enum display_format { - DISPLAY_FORMAT_UNKNOWN = 0, DISPLAY_FORMAT_FULL, DISPLAY_FORMAT_COMPACT, DISPLAY_FORMAT_PORCELAIN, @@ -74,14 +73,11 @@ struct display_state { int url_len, shown_url; }; -static int fetch_prune_config = -1; /* unspecified */ -static int fetch_show_forced_updates = 1; static uint64_t forced_updates_ms = 0; static int prefetch = 0; static int prune = -1; /* unspecified */ #define PRUNE_BY_DEFAULT 0 /* do we prune by default? */ -static int fetch_prune_tags_config = -1; /* unspecified */ static int prune_tags = -1; /* unspecified */ #define PRUNE_TAGS_BY_DEFAULT 0 /* do we prune tags by default? */ @@ -90,8 +86,6 @@ static int write_fetch_head = 1; static int verbosity, deepen_relative, set_upstream, refetch; static int progress = -1; static int tags = TAGS_DEFAULT, update_shallow, deepen; -static int submodule_fetch_jobs_config = -1; -static int fetch_parallel_config = 1; static int atomic_fetch; static enum transport_family family; static const char *depth; @@ -101,7 +95,6 @@ static struct string_list deepen_not = STRING_LIST_INIT_NODUP; static struct strbuf default_rla = STRBUF_INIT; static struct transport *gtransport; static struct transport *gsecondary; -static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; static struct refspec refmap = REFSPEC_INIT_FETCH; static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT; static struct string_list server_options = STRING_LIST_INIT_DUP; @@ -109,47 +102,54 @@ static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP; struct fetch_config { enum display_format display_format; + int prune; + int prune_tags; + int show_forced_updates; + int recurse_submodules; + int parallel; + int submodule_fetch_jobs; }; -static int git_fetch_config(const char *k, const char *v, void *cb) +static int git_fetch_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { struct fetch_config *fetch_config = cb; if (!strcmp(k, "fetch.prune")) { - fetch_prune_config = git_config_bool(k, v); + fetch_config->prune = git_config_bool(k, v); return 0; } if (!strcmp(k, "fetch.prunetags")) { - fetch_prune_tags_config = git_config_bool(k, v); + fetch_config->prune_tags = git_config_bool(k, v); return 0; } if (!strcmp(k, "fetch.showforcedupdates")) { - fetch_show_forced_updates = git_config_bool(k, v); + fetch_config->show_forced_updates = git_config_bool(k, v); return 0; } if (!strcmp(k, "submodule.recurse")) { int r = git_config_bool(k, v) ? RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF; - recurse_submodules = r; + fetch_config->recurse_submodules = r; } if (!strcmp(k, "submodule.fetchjobs")) { - submodule_fetch_jobs_config = parse_submodule_fetchjobs(k, v); + fetch_config->submodule_fetch_jobs = parse_submodule_fetchjobs(k, v, ctx->kvi); return 0; } else if (!strcmp(k, "fetch.recursesubmodules")) { - recurse_submodules = parse_fetch_recurse_submodules_arg(k, v); + fetch_config->recurse_submodules = parse_fetch_recurse_submodules_arg(k, v); return 0; } if (!strcmp(k, "fetch.parallel")) { - fetch_parallel_config = git_config_int(k, v); - if (fetch_parallel_config < 0) + fetch_config->parallel = git_config_int(k, v, ctx->kvi); + if (fetch_config->parallel < 0) die(_("fetch.parallel cannot be negative")); - if (!fetch_parallel_config) - fetch_parallel_config = online_cpus(); + if (!fetch_config->parallel) + fetch_config->parallel = online_cpus(); return 0; } @@ -165,7 +165,7 @@ static int git_fetch_config(const char *k, const char *v, void *cb) "fetch.output", v); } - return git_default_config(k, v, cb); + return git_default_config(k, v, ctx, cb); } static int parse_refmap_arg(const struct option *opt, const char *arg, int unset) @@ -892,7 +892,8 @@ static int update_local_ref(struct ref *ref, struct ref_transaction *transaction, struct display_state *display_state, const struct ref *remote_ref, - int summary_width) + int summary_width, + const struct fetch_config *config) { struct commit *current = NULL, *updated; int fast_forward = 0; @@ -954,11 +955,10 @@ static int update_local_ref(struct ref *ref, * Base this on the remote's ref name, as it's * more likely to follow a standard layout. */ - const char *name = remote_ref ? remote_ref->name : ""; - if (starts_with(name, "refs/tags/")) { + if (starts_with(remote_ref->name, "refs/tags/")) { msg = "storing tag"; what = _("[new tag]"); - } else if (starts_with(name, "refs/heads/")) { + } else if (starts_with(remote_ref->name, "refs/heads/")) { msg = "storing head"; what = _("[new branch]"); } else { @@ -974,7 +974,7 @@ static int update_local_ref(struct ref *ref, return r; } - if (fetch_show_forced_updates) { + if (config->show_forced_updates) { uint64_t t_before = getnanotime(); fast_forward = repo_in_merge_bases(the_repository, current, updated); @@ -1127,7 +1127,8 @@ static int store_updated_refs(struct display_state *display_state, const char *remote_name, int connectivity_checked, struct ref_transaction *transaction, struct ref *ref_map, - struct fetch_head *fetch_head) + struct fetch_head *fetch_head, + const struct fetch_config *config) { int rc = 0; struct strbuf note = STRBUF_INIT; @@ -1210,7 +1211,7 @@ static int store_updated_refs(struct display_state *display_state, ref->force = rm->peer_ref->force; } - if (recurse_submodules != RECURSE_SUBMODULES_OFF && + if (config->recurse_submodules != RECURSE_SUBMODULES_OFF && (!rm->peer_ref || !oideq(&ref->old_oid, &ref->new_oid))) { check_for_new_submodule_commits(&rm->old_oid); } @@ -1243,7 +1244,7 @@ static int store_updated_refs(struct display_state *display_state, if (ref) { rc |= update_local_ref(ref, transaction, display_state, - rm, summary_width); + rm, summary_width, config); free(ref); } else if (write_fetch_head || dry_run) { /* @@ -1267,7 +1268,7 @@ static int store_updated_refs(struct display_state *display_state, "branches"), remote_name); if (advice_enabled(ADVICE_FETCH_SHOW_FORCED_UPDATES)) { - if (!fetch_show_forced_updates) { + if (!config->show_forced_updates) { warning(_(warn_show_forced_updates)); } else if (forced_updates_ms > FORCED_UPDATES_DELAY_WARNING_IN_MS) { warning(_(warn_time_show_forced_updates), @@ -1328,7 +1329,8 @@ static int fetch_and_consume_refs(struct display_state *display_state, struct transport *transport, struct ref_transaction *transaction, struct ref *ref_map, - struct fetch_head *fetch_head) + struct fetch_head *fetch_head, + const struct fetch_config *config) { int connectivity_checked = 1; int ret; @@ -1351,7 +1353,7 @@ static int fetch_and_consume_refs(struct display_state *display_state, trace2_region_enter("fetch", "consume_refs", the_repository); ret = store_updated_refs(display_state, transport->remote->name, connectivity_checked, transaction, ref_map, - fetch_head); + fetch_head, config); trace2_region_leave("fetch", "consume_refs", the_repository); out: @@ -1522,7 +1524,8 @@ static int backfill_tags(struct display_state *display_state, struct transport *transport, struct ref_transaction *transaction, struct ref *ref_map, - struct fetch_head *fetch_head) + struct fetch_head *fetch_head, + const struct fetch_config *config) { int retcode, cannot_reuse; @@ -1543,7 +1546,8 @@ static int backfill_tags(struct display_state *display_state, transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL); transport_set_option(transport, TRANS_OPT_DEPTH, "0"); transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL); - retcode = fetch_and_consume_refs(display_state, transport, transaction, ref_map, fetch_head); + retcode = fetch_and_consume_refs(display_state, transport, transaction, ref_map, + fetch_head, config); if (gsecondary) { transport_disconnect(gsecondary); @@ -1555,7 +1559,7 @@ static int backfill_tags(struct display_state *display_state, static int do_fetch(struct transport *transport, struct refspec *rs, - enum display_format display_format) + const struct fetch_config *config) { struct ref_transaction *transaction = NULL; struct ref *ref_map = NULL; @@ -1641,7 +1645,8 @@ static int do_fetch(struct transport *transport, if (retcode) goto cleanup; - display_state_init(&display_state, ref_map, transport->url, display_format); + display_state_init(&display_state, ref_map, transport->url, + config->display_format); if (atomic_fetch) { transaction = ref_transaction_begin(&err); @@ -1669,7 +1674,8 @@ static int do_fetch(struct transport *transport, retcode = 1; } - if (fetch_and_consume_refs(&display_state, transport, transaction, ref_map, &fetch_head)) { + if (fetch_and_consume_refs(&display_state, transport, transaction, ref_map, + &fetch_head, config)) { retcode = 1; goto cleanup; } @@ -1692,7 +1698,7 @@ static int do_fetch(struct transport *transport, * the transaction and don't commit anything. */ if (backfill_tags(&display_state, transport, transaction, tags_ref_map, - &fetch_head)) + &fetch_head, config)) retcode = 1; } @@ -1794,7 +1800,9 @@ struct remote_group_data { struct string_list *list; }; -static int get_remote_group(const char *key, const char *value, void *priv) +static int get_remote_group(const char *key, const char *value, + const struct config_context *ctx UNUSED, + void *priv) { struct remote_group_data *g = priv; @@ -1830,7 +1838,7 @@ static int add_remote_or_group(const char *name, struct string_list *list) } static void add_options_to_argv(struct strvec *argv, - enum display_format format) + const struct fetch_config *config) { if (dry_run) strvec_push(argv, "--dry-run"); @@ -1844,11 +1852,11 @@ static void add_options_to_argv(struct strvec *argv, strvec_push(argv, "--force"); if (keep) strvec_push(argv, "--keep"); - if (recurse_submodules == RECURSE_SUBMODULES_ON) + if (config->recurse_submodules == RECURSE_SUBMODULES_ON) strvec_push(argv, "--recurse-submodules"); - else if (recurse_submodules == RECURSE_SUBMODULES_OFF) + else if (config->recurse_submodules == RECURSE_SUBMODULES_OFF) strvec_push(argv, "--no-recurse-submodules"); - else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) + else if (config->recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) strvec_push(argv, "--recurse-submodules=on-demand"); if (tags == TAGS_SET) strvec_push(argv, "--tags"); @@ -1866,7 +1874,7 @@ static void add_options_to_argv(struct strvec *argv, strvec_push(argv, "--ipv6"); if (!write_fetch_head) strvec_push(argv, "--no-write-fetch-head"); - if (format == DISPLAY_FORMAT_PORCELAIN) + if (config->display_format == DISPLAY_FORMAT_PORCELAIN) strvec_pushf(argv, "--porcelain"); } @@ -1876,7 +1884,7 @@ struct parallel_fetch_state { const char **argv; struct string_list *remotes; int next, result; - enum display_format format; + const struct fetch_config *config; }; static int fetch_next_remote(struct child_process *cp, @@ -1896,7 +1904,7 @@ static int fetch_next_remote(struct child_process *cp, strvec_push(&cp->args, remote); cp->git_cmd = 1; - if (verbosity >= 0 && state->format != DISPLAY_FORMAT_PORCELAIN) + if (verbosity >= 0 && state->config->display_format != DISPLAY_FORMAT_PORCELAIN) printf(_("Fetching %s\n"), remote); return 1; @@ -1929,7 +1937,7 @@ static int fetch_finished(int result, struct strbuf *out, } static int fetch_multiple(struct string_list *list, int max_children, - enum display_format format) + const struct fetch_config *config) { int i, result = 0; struct strvec argv = STRVEC_INIT; @@ -1947,10 +1955,10 @@ static int fetch_multiple(struct string_list *list, int max_children, strvec_pushl(&argv, "-c", "fetch.bundleURI=", "fetch", "--append", "--no-auto-gc", "--no-write-commit-graph", NULL); - add_options_to_argv(&argv, format); + add_options_to_argv(&argv, config); if (max_children != 1 && list->nr != 1) { - struct parallel_fetch_state state = { argv.v, list, 0, 0, format }; + struct parallel_fetch_state state = { argv.v, list, 0, 0, config }; const struct run_process_parallel_opts opts = { .tr2_category = "fetch", .tr2_label = "parallel/fetch", @@ -1974,7 +1982,7 @@ static int fetch_multiple(struct string_list *list, int max_children, strvec_pushv(&cmd.args, argv.v); strvec_push(&cmd.args, name); - if (verbosity >= 0 && format != DISPLAY_FORMAT_PORCELAIN) + if (verbosity >= 0 && config->display_format != DISPLAY_FORMAT_PORCELAIN) printf(_("Fetching %s\n"), name); cmd.git_cmd = 1; if (run_command(&cmd)) { @@ -2030,7 +2038,7 @@ static inline void fetch_one_setup_partial(struct remote *remote) static int fetch_one(struct remote *remote, int argc, const char **argv, int prune_tags_ok, int use_stdin_refspecs, - enum display_format display_format) + const struct fetch_config *config) { struct refspec rs = REFSPEC_INIT_FETCH; int i; @@ -2048,8 +2056,8 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, /* no command line request */ if (0 <= remote->prune) prune = remote->prune; - else if (0 <= fetch_prune_config) - prune = fetch_prune_config; + else if (0 <= config->prune) + prune = config->prune; else prune = PRUNE_BY_DEFAULT; } @@ -2058,8 +2066,8 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, /* no command line request */ if (0 <= remote->prune_tags) prune_tags = remote->prune_tags; - else if (0 <= fetch_prune_tags_config) - prune_tags = fetch_prune_tags_config; + else if (0 <= config->prune_tags) + prune_tags = config->prune_tags; else prune_tags = PRUNE_TAGS_BY_DEFAULT; } @@ -2097,7 +2105,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, sigchain_push_common(unlock_pack_on_signal); atexit(unlock_pack_atexit); sigchain_push(SIGPIPE, SIG_IGN); - exit_code = do_fetch(gtransport, &rs, display_format); + exit_code = do_fetch(gtransport, &rs, config); sigchain_pop(SIGPIPE); refspec_clear(&rs); transport_disconnect(gtransport); @@ -2109,6 +2117,12 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) { struct fetch_config config = { .display_format = DISPLAY_FORMAT_FULL, + .prune = -1, + .prune_tags = -1, + .show_forced_updates = 1, + .recurse_submodules = RECURSE_SUBMODULES_DEFAULT, + .parallel = 1, + .submodule_fetch_jobs = -1, }; const char *submodule_prefix = ""; const char *bundle_uri; @@ -2206,7 +2220,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) N_("run 'maintenance --auto' after fetching")), OPT_BOOL(0, "auto-gc", &enable_auto_gc, N_("run 'maintenance --auto' after fetching")), - OPT_BOOL(0, "show-forced-updates", &fetch_show_forced_updates, + OPT_BOOL(0, "show-forced-updates", &config.show_forced_updates, N_("check for forced-updates on all updated branches")), OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph, N_("write the commit-graph after fetching")), @@ -2237,7 +2251,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) builtin_fetch_options, builtin_fetch_usage, 0); if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT) - recurse_submodules = recurse_submodules_cli; + config.recurse_submodules = recurse_submodules_cli; if (negotiate_only) { switch (recurse_submodules_cli) { @@ -2248,7 +2262,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) * submodules. Skip it by setting recurse_submodules to * RECURSE_SUBMODULES_OFF. */ - recurse_submodules = RECURSE_SUBMODULES_OFF; + config.recurse_submodules = RECURSE_SUBMODULES_OFF; break; default: @@ -2257,11 +2271,11 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } } - if (recurse_submodules != RECURSE_SUBMODULES_OFF) { - int *sfjc = submodule_fetch_jobs_config == -1 - ? &submodule_fetch_jobs_config : NULL; - int *rs = recurse_submodules == RECURSE_SUBMODULES_DEFAULT - ? &recurse_submodules : NULL; + if (config.recurse_submodules != RECURSE_SUBMODULES_OFF) { + int *sfjc = config.submodule_fetch_jobs == -1 + ? &config.submodule_fetch_jobs : NULL; + int *rs = config.recurse_submodules == RECURSE_SUBMODULES_DEFAULT + ? &config.recurse_submodules : NULL; fetch_config_from_gitmodules(sfjc, rs); } @@ -2275,7 +2289,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) * Reference updates in submodules would be ambiguous * in porcelain mode, so we reject this combination. */ - recurse_submodules = RECURSE_SUBMODULES_OFF; + config.recurse_submodules = RECURSE_SUBMODULES_OFF; break; default: @@ -2385,7 +2399,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (filter_options.choice || repo_has_promisor_remote(the_repository)) fetch_one_setup_partial(remote); result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs, - config.display_format); + &config); } else { int max_children = max_jobs; @@ -2402,10 +2416,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) "from one remote")); if (max_children < 0) - max_children = fetch_parallel_config; + max_children = config.parallel; /* TODO should this also die if we have a previous partial-clone? */ - result = fetch_multiple(&list, max_children, config.display_format); + result = fetch_multiple(&list, max_children, &config); } /* @@ -2417,20 +2431,20 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) * the fetched history from each remote, so there is no need * to fetch submodules from here. */ - if (!result && remote && (recurse_submodules != RECURSE_SUBMODULES_OFF)) { + if (!result && remote && (config.recurse_submodules != RECURSE_SUBMODULES_OFF)) { struct strvec options = STRVEC_INIT; int max_children = max_jobs; if (max_children < 0) - max_children = submodule_fetch_jobs_config; + max_children = config.submodule_fetch_jobs; if (max_children < 0) - max_children = fetch_parallel_config; + max_children = config.parallel; - add_options_to_argv(&options, config.display_format); + add_options_to_argv(&options, &config); result = fetch_submodules(the_repository, &options, submodule_prefix, - recurse_submodules, + config.recurse_submodules, recurse_submodules_default, verbosity < 0, max_children); diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 695fc8f4a5..15409337f8 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -1,11 +1,11 @@ #include "builtin.h" -#include "cache.h" #include "config.h" #include "gettext.h" #include "refs.h" #include "object.h" #include "parse-options.h" #include "ref-filter.h" +#include "strbuf.h" #include "strvec.h" #include "commit-reach.h" diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c index 37daf7bec1..28186b30f5 100644 --- a/builtin/for-each-repo.c +++ b/builtin/for-each-repo.c @@ -1,6 +1,5 @@ -#include "cache.h" -#include "config.h" #include "builtin.h" +#include "config.h" #include "gettext.h" #include "parse-options.h" #include "path.h" diff --git a/builtin/fsck.c b/builtin/fsck.c index dcc165bf0c..3aa9c812eb 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -1,5 +1,4 @@ #include "builtin.h" -#include "cache.h" #include "gettext.h" #include "hex.h" #include "repository.h" @@ -21,10 +20,13 @@ #include "packfile.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" +#include "path.h" +#include "read-cache-ll.h" #include "replace-object.h" #include "resolve-undo.h" #include "run-command.h" +#include "sparse-index.h" #include "worktree.h" #include "pack-revindex.h" #include "pack-bitmap.h" @@ -808,7 +810,7 @@ static int fsck_resolve_undo(struct index_state *istate, } static void fsck_index(struct index_state *istate, const char *index_path, - int is_main_index) + int is_current_worktree) { unsigned int i; @@ -830,7 +832,7 @@ static void fsck_index(struct index_state *istate, const char *index_path, obj->flags |= USED; fsck_put_object_name(&fsck_walk_options, &obj->oid, "%s:%s", - is_main_index ? "" : index_path, + is_current_worktree ? "" : index_path, istate->cache[i]->name); mark_object_reachable(obj); } @@ -929,7 +931,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) fetch_if_missing = 0; errors_found = 0; - read_replace_refs = 0; + disable_replace_refs(); save_commit_buffer = 0; argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0); diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index f6dd9a784c..b5796b4a4a 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -5,15 +5,17 @@ #include "environment.h" #include "gettext.h" #include "parse-options.h" -#include "fsmonitor.h" +#include "fsmonitor-ll.h" #include "fsmonitor-ipc.h" #include "fsmonitor-path-utils.h" +#include "fsmonitor-settings.h" #include "compat/fsmonitor/fsm-health.h" #include "compat/fsmonitor/fsm-listen.h" #include "fsmonitor--daemon.h" #include "simple-ipc.h" #include "khash.h" #include "pkt-line.h" +#include "trace.h" #include "trace2.h" static const char * const builtin_fsmonitor__daemon_usage[] = { @@ -37,10 +39,11 @@ static int fsmonitor__start_timeout_sec = 60; #define FSMONITOR__ANNOUNCE_STARTUP "fsmonitor.announcestartup" static int fsmonitor__announce_startup = 0; -static int fsmonitor_config(const char *var, const char *value, void *cb) +static int fsmonitor_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, FSMONITOR__IPC_THREADS)) { - int i = git_config_int(var, value); + int i = git_config_int(var, value, ctx->kvi); if (i < 1) return error(_("value of '%s' out of range: %d"), FSMONITOR__IPC_THREADS, i); @@ -49,7 +52,7 @@ static int fsmonitor_config(const char *var, const char *value, void *cb) } if (!strcmp(var, FSMONITOR__START_TIMEOUT)) { - int i = git_config_int(var, value); + int i = git_config_int(var, value, ctx->kvi); if (i < 0) return error(_("value of '%s' out of range: %d"), FSMONITOR__START_TIMEOUT, i); @@ -59,7 +62,7 @@ static int fsmonitor_config(const char *var, const char *value, void *cb) if (!strcmp(var, FSMONITOR__ANNOUNCE_STARTUP)) { int is_bool; - int i = git_config_bool_or_int(var, value, &is_bool); + int i = git_config_bool_or_int(var, value, ctx->kvi, &is_bool); if (i < 0) return error(_("value of '%s' not bool or int: %d"), var, i); @@ -67,7 +70,7 @@ static int fsmonitor_config(const char *var, const char *value, void *cb) return 0; } - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } /* diff --git a/builtin/gc.c b/builtin/gc.c index f3942188a6..91eec7703a 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -27,9 +27,10 @@ #include "commit-graph.h" #include "packfile.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "pack.h" #include "pack-objects.h" +#include "path.h" #include "blob.h" #include "tree.h" #include "promisor-remote.h" diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c index 564cfcac4f..9303e386cc 100644 --- a/builtin/get-tar-commit-id.c +++ b/builtin/get-tar-commit-id.c @@ -1,10 +1,9 @@ /* * Copyright (c) 2005, 2006 Rene Scharfe */ -#include "cache.h" +#include "builtin.h" #include "commit.h" #include "tar.h" -#include "builtin.h" #include "quote.h" #include "wrapper.h" diff --git a/builtin/grep.c b/builtin/grep.c index b86c754def..22645c6244 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -3,7 +3,7 @@ * * Copyright (c) 2006 Junio C Hamano */ -#include "cache.h" +#include "builtin.h" #include "alloc.h" #include "gettext.h" #include "hex.h" @@ -14,7 +14,6 @@ #include "commit.h" #include "tag.h" #include "tree-walk.h" -#include "builtin.h" #include "parse-options.h" #include "string-list.h" #include "run-command.h" @@ -28,9 +27,11 @@ #include "submodule-config.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "packfile.h" #include "pager.h" +#include "path.h" +#include "read-cache-ll.h" #include "write-or-die.h" static const char *grep_prefix; @@ -290,14 +291,18 @@ static int wait_all(void) return hit; } -static int grep_cmd_config(const char *var, const char *value, void *cb) +static int grep_cmd_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { - int st = grep_config(var, value, cb); - if (git_color_default_config(var, value, NULL) < 0) + int st = grep_config(var, value, ctx, cb); + + if (git_color_config(var, value, cb) < 0) + st = -1; + else if (git_default_config(var, value, ctx, cb) < 0) st = -1; if (!strcmp(var, "grep.threads")) { - num_threads = git_config_int(var, value); + num_threads = git_config_int(var, value, ctx->kvi); if (num_threads < 0) die(_("invalid number of threads specified (%d) for %s"), num_threads, var); diff --git a/builtin/hash-object.c b/builtin/hash-object.c index a380121166..5ffec99dce 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -10,12 +10,13 @@ #include "gettext.h" #include "hex.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "blob.h" #include "quote.h" #include "parse-options.h" #include "exec-cmd.h" #include "setup.h" +#include "strbuf.h" #include "write-or-die.h" /* diff --git a/builtin/help.c b/builtin/help.c index d3cf4af3f6..dc1fbe2b98 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -1,9 +1,8 @@ /* * Builtin help command */ -#include "cache.h" -#include "config.h" #include "builtin.h" +#include "config.h" #include "exec-cmd.h" #include "gettext.h" #include "pager.h" @@ -398,7 +397,8 @@ static int add_man_viewer_info(const char *var, const char *value) return 0; } -static int git_help_config(const char *var, const char *value, void *cb) +static int git_help_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "help.format")) { if (!value) @@ -421,7 +421,7 @@ static int git_help_config(const char *var, const char *value, void *cb) if (starts_with(var, "man.")) return add_man_viewer_info(var, value); - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } static struct cmdnames main_cmds, other_cmds; diff --git a/builtin/hook.c b/builtin/hook.c index 88051795c7..09b51a6487 100644 --- a/builtin/hook.c +++ b/builtin/hook.c @@ -1,4 +1,3 @@ -#include "cache.h" #include "builtin.h" #include "config.h" #include "gettext.h" diff --git a/builtin/index-pack.c b/builtin/index-pack.c index bb67e16655..e280180cac 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -14,12 +14,13 @@ #include "progress.h" #include "fsck.h" #include "exec-cmd.h" +#include "strbuf.h" #include "streaming.h" #include "thread-utils.h" #include "packfile.h" #include "pack-revindex.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "oid-array.h" #include "replace-object.h" #include "promisor-remote.h" @@ -1581,18 +1582,19 @@ static void final(const char *final_pack_name, const char *curr_pack_name, strbuf_release(&pack_name); } -static int git_index_pack_config(const char *k, const char *v, void *cb) +static int git_index_pack_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { struct pack_idx_option *opts = cb; if (!strcmp(k, "pack.indexversion")) { - opts->version = git_config_int(k, v); + opts->version = git_config_int(k, v, ctx->kvi); if (opts->version > 2) die(_("bad pack.indexVersion=%"PRIu32), opts->version); return 0; } if (!strcmp(k, "pack.threads")) { - nr_threads = git_config_int(k, v); + nr_threads = git_config_int(k, v, ctx->kvi); if (nr_threads < 0) die(_("invalid number of threads specified (%d)"), nr_threads); @@ -1608,7 +1610,7 @@ static int git_index_pack_config(const char *k, const char *v, void *cb) else opts->flags &= ~WRITE_REV; } - return git_default_config(k, v, cb); + return git_default_config(k, v, ctx, cb); } static int cmp_uint32(const void *a_, const void *b_) @@ -1752,7 +1754,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (argc == 2 && !strcmp(argv[1], "-h")) usage(index_pack_usage); - read_replace_refs = 0; + disable_replace_refs(); fsck_options.walk = mark_link; reset_pack_idx_option(&opts); diff --git a/builtin/init-db.c b/builtin/init-db.c index aef4036105..0d8bd4d721 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -3,485 +3,18 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#include "cache.h" +#include "builtin.h" #include "abspath.h" #include "config.h" -#include "copy.h" #include "environment.h" #include "gettext.h" -#include "refs.h" -#include "builtin.h" -#include "exec-cmd.h" #include "object-file.h" #include "parse-options.h" #include "path.h" #include "setup.h" -#include "worktree.h" +#include "strbuf.h" #include "wrapper.h" -#ifndef DEFAULT_GIT_TEMPLATE_DIR -#define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates" -#endif - -#ifdef NO_TRUSTABLE_FILEMODE -#define TEST_FILEMODE 0 -#else -#define TEST_FILEMODE 1 -#endif - -#define GIT_DEFAULT_HASH_ENVIRONMENT "GIT_DEFAULT_HASH" - -static int init_is_bare_repository = 0; -static int init_shared_repository = -1; - -static void copy_templates_1(struct strbuf *path, struct strbuf *template_path, - DIR *dir) -{ - size_t path_baselen = path->len; - size_t template_baselen = template_path->len; - struct dirent *de; - - /* Note: if ".git/hooks" file exists in the repository being - * re-initialized, /etc/core-git/templates/hooks/update would - * cause "git init" to fail here. I think this is sane but - * it means that the set of templates we ship by default, along - * with the way the namespace under .git/ is organized, should - * be really carefully chosen. - */ - safe_create_dir(path->buf, 1); - while ((de = readdir(dir)) != NULL) { - struct stat st_git, st_template; - int exists = 0; - - strbuf_setlen(path, path_baselen); - strbuf_setlen(template_path, template_baselen); - - if (de->d_name[0] == '.') - continue; - strbuf_addstr(path, de->d_name); - strbuf_addstr(template_path, de->d_name); - if (lstat(path->buf, &st_git)) { - if (errno != ENOENT) - die_errno(_("cannot stat '%s'"), path->buf); - } - else - exists = 1; - - if (lstat(template_path->buf, &st_template)) - die_errno(_("cannot stat template '%s'"), template_path->buf); - - if (S_ISDIR(st_template.st_mode)) { - DIR *subdir = opendir(template_path->buf); - if (!subdir) - die_errno(_("cannot opendir '%s'"), template_path->buf); - strbuf_addch(path, '/'); - strbuf_addch(template_path, '/'); - copy_templates_1(path, template_path, subdir); - closedir(subdir); - } - else if (exists) - continue; - else if (S_ISLNK(st_template.st_mode)) { - struct strbuf lnk = STRBUF_INIT; - if (strbuf_readlink(&lnk, template_path->buf, - st_template.st_size) < 0) - die_errno(_("cannot readlink '%s'"), template_path->buf); - if (symlink(lnk.buf, path->buf)) - die_errno(_("cannot symlink '%s' '%s'"), - lnk.buf, path->buf); - strbuf_release(&lnk); - } - else if (S_ISREG(st_template.st_mode)) { - if (copy_file(path->buf, template_path->buf, st_template.st_mode)) - die_errno(_("cannot copy '%s' to '%s'"), - template_path->buf, path->buf); - } - else - error(_("ignoring template %s"), template_path->buf); - } -} - -static void copy_templates(const char *template_dir, const char *init_template_dir) -{ - struct strbuf path = STRBUF_INIT; - struct strbuf template_path = STRBUF_INIT; - size_t template_len; - struct repository_format template_format = REPOSITORY_FORMAT_INIT; - struct strbuf err = STRBUF_INIT; - DIR *dir; - char *to_free = NULL; - - if (!template_dir) - template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT); - if (!template_dir) - template_dir = init_template_dir; - if (!template_dir) - template_dir = to_free = system_path(DEFAULT_GIT_TEMPLATE_DIR); - if (!template_dir[0]) { - free(to_free); - return; - } - - strbuf_addstr(&template_path, template_dir); - strbuf_complete(&template_path, '/'); - template_len = template_path.len; - - dir = opendir(template_path.buf); - if (!dir) { - warning(_("templates not found in %s"), template_dir); - goto free_return; - } - - /* Make sure that template is from the correct vintage */ - strbuf_addstr(&template_path, "config"); - read_repository_format(&template_format, template_path.buf); - strbuf_setlen(&template_path, template_len); - - /* - * No mention of version at all is OK, but anything else should be - * verified. - */ - if (template_format.version >= 0 && - verify_repository_format(&template_format, &err) < 0) { - warning(_("not copying templates from '%s': %s"), - template_dir, err.buf); - strbuf_release(&err); - goto close_free_return; - } - - strbuf_addstr(&path, get_git_common_dir()); - strbuf_complete(&path, '/'); - copy_templates_1(&path, &template_path, dir); -close_free_return: - closedir(dir); -free_return: - free(to_free); - strbuf_release(&path); - strbuf_release(&template_path); - clear_repository_format(&template_format); -} - -/* - * If the git_dir is not directly inside the working tree, then git will not - * find it by default, and we need to set the worktree explicitly. - */ -static int needs_work_tree_config(const char *git_dir, const char *work_tree) -{ - if (!strcmp(work_tree, "/") && !strcmp(git_dir, "/.git")) - return 0; - if (skip_prefix(git_dir, work_tree, &git_dir) && - !strcmp(git_dir, "/.git")) - return 0; - return 1; -} - -void initialize_repository_version(int hash_algo, int reinit) -{ - char repo_version_string[10]; - int repo_version = GIT_REPO_VERSION; - - if (hash_algo != GIT_HASH_SHA1) - repo_version = GIT_REPO_VERSION_READ; - - /* This forces creation of new config file */ - xsnprintf(repo_version_string, sizeof(repo_version_string), - "%d", repo_version); - git_config_set("core.repositoryformatversion", repo_version_string); - - if (hash_algo != GIT_HASH_SHA1) - git_config_set("extensions.objectformat", - hash_algos[hash_algo].name); - else if (reinit) - git_config_set_gently("extensions.objectformat", NULL); -} - -static int create_default_files(const char *template_path, - const char *original_git_dir, - const char *initial_branch, - const struct repository_format *fmt, - int quiet) -{ - struct stat st1; - struct strbuf buf = STRBUF_INIT; - char *path; - char junk[2]; - int reinit; - int filemode; - struct strbuf err = STRBUF_INIT; - const char *init_template_dir = NULL; - const char *work_tree = get_git_work_tree(); - - /* - * First copy the templates -- we might have the default - * config file there, in which case we would want to read - * from it after installing. - * - * Before reading that config, we also need to clear out any cached - * values (since we've just potentially changed what's available on - * disk). - */ - git_config_get_pathname("init.templatedir", &init_template_dir); - copy_templates(template_path, init_template_dir); - free((char *)init_template_dir); - git_config_clear(); - reset_shared_repository(); - git_config(git_default_config, NULL); - - /* - * We must make sure command-line options continue to override any - * values we might have just re-read from the config. - */ - is_bare_repository_cfg = init_is_bare_repository || !work_tree; - if (init_shared_repository != -1) - set_shared_repository(init_shared_repository); - - /* - * We would have created the above under user's umask -- under - * shared-repository settings, we would need to fix them up. - */ - if (get_shared_repository()) { - adjust_shared_perm(get_git_dir()); - } - - /* - * We need to create a "refs" dir in any case so that older - * versions of git can tell that this is a repository. - */ - safe_create_dir(git_path("refs"), 1); - adjust_shared_perm(git_path("refs")); - - if (refs_init_db(&err)) - die("failed to set up refs db: %s", err.buf); - - /* - * Point the HEAD symref to the initial branch with if HEAD does - * not yet exist. - */ - path = git_path_buf(&buf, "HEAD"); - reinit = (!access(path, R_OK) - || readlink(path, junk, sizeof(junk)-1) != -1); - if (!reinit) { - char *ref; - - if (!initial_branch) - initial_branch = git_default_branch_name(quiet); - - ref = xstrfmt("refs/heads/%s", initial_branch); - if (check_refname_format(ref, 0) < 0) - die(_("invalid initial branch name: '%s'"), - initial_branch); - - if (create_symref("HEAD", ref, NULL) < 0) - exit(1); - free(ref); - } - - initialize_repository_version(fmt->hash_algo, 0); - - /* Check filemode trustability */ - path = git_path_buf(&buf, "config"); - filemode = TEST_FILEMODE; - if (TEST_FILEMODE && !lstat(path, &st1)) { - struct stat st2; - filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) && - !lstat(path, &st2) && - st1.st_mode != st2.st_mode && - !chmod(path, st1.st_mode)); - if (filemode && !reinit && (st1.st_mode & S_IXUSR)) - filemode = 0; - } - git_config_set("core.filemode", filemode ? "true" : "false"); - - if (is_bare_repository()) - git_config_set("core.bare", "true"); - else { - git_config_set("core.bare", "false"); - /* allow template config file to override the default */ - if (log_all_ref_updates == LOG_REFS_UNSET) - git_config_set("core.logallrefupdates", "true"); - if (needs_work_tree_config(original_git_dir, work_tree)) - git_config_set("core.worktree", work_tree); - } - - if (!reinit) { - /* Check if symlink is supported in the work tree */ - path = git_path_buf(&buf, "tXXXXXX"); - if (!close(xmkstemp(path)) && - !unlink(path) && - !symlink("testing", path) && - !lstat(path, &st1) && - S_ISLNK(st1.st_mode)) - unlink(path); /* good */ - else - git_config_set("core.symlinks", "false"); - - /* Check if the filesystem is case-insensitive */ - path = git_path_buf(&buf, "CoNfIg"); - if (!access(path, F_OK)) - git_config_set("core.ignorecase", "true"); - probe_utf8_pathname_composition(); - } - - strbuf_release(&buf); - return reinit; -} - -static void create_object_directory(void) -{ - struct strbuf path = STRBUF_INIT; - size_t baselen; - - strbuf_addstr(&path, get_object_directory()); - baselen = path.len; - - safe_create_dir(path.buf, 1); - - strbuf_setlen(&path, baselen); - strbuf_addstr(&path, "/pack"); - safe_create_dir(path.buf, 1); - - strbuf_setlen(&path, baselen); - strbuf_addstr(&path, "/info"); - safe_create_dir(path.buf, 1); - - strbuf_release(&path); -} - -static void separate_git_dir(const char *git_dir, const char *git_link) -{ - struct stat st; - - if (!stat(git_link, &st)) { - const char *src; - - if (S_ISREG(st.st_mode)) - src = read_gitfile(git_link); - else if (S_ISDIR(st.st_mode)) - src = git_link; - else - die(_("unable to handle file type %d"), (int)st.st_mode); - - if (rename(src, git_dir)) - die_errno(_("unable to move %s to %s"), src, git_dir); - repair_worktrees(NULL, NULL); - } - - write_file(git_link, "gitdir: %s", git_dir); -} - -static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash) -{ - const char *env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT); - /* - * If we already have an initialized repo, don't allow the user to - * specify a different algorithm, as that could cause corruption. - * Otherwise, if the user has specified one on the command line, use it. - */ - if (repo_fmt->version >= 0 && hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo) - die(_("attempt to reinitialize repository with different hash")); - else if (hash != GIT_HASH_UNKNOWN) - repo_fmt->hash_algo = hash; - else if (env) { - int env_algo = hash_algo_by_name(env); - if (env_algo == GIT_HASH_UNKNOWN) - die(_("unknown hash algorithm '%s'"), env); - repo_fmt->hash_algo = env_algo; - } -} - -int init_db(const char *git_dir, const char *real_git_dir, - const char *template_dir, int hash, const char *initial_branch, - unsigned int flags) -{ - int reinit; - int exist_ok = flags & INIT_DB_EXIST_OK; - char *original_git_dir = real_pathdup(git_dir, 1); - struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; - - if (real_git_dir) { - struct stat st; - - if (!exist_ok && !stat(git_dir, &st)) - die(_("%s already exists"), git_dir); - - if (!exist_ok && !stat(real_git_dir, &st)) - die(_("%s already exists"), real_git_dir); - - set_git_dir(real_git_dir, 1); - git_dir = get_git_dir(); - separate_git_dir(git_dir, original_git_dir); - } - else { - set_git_dir(git_dir, 1); - git_dir = get_git_dir(); - } - startup_info->have_repository = 1; - - /* Ensure `core.hidedotfiles` is processed */ - git_config(platform_core_config, NULL); - - safe_create_dir(git_dir, 0); - - init_is_bare_repository = is_bare_repository(); - - /* Check to see if the repository version is right. - * Note that a newly created repository does not have - * config file, so this will not fail. What we are catching - * is an attempt to reinitialize new repository with an old tool. - */ - check_repository_format(&repo_fmt); - - validate_hash_algorithm(&repo_fmt, hash); - - reinit = create_default_files(template_dir, original_git_dir, - initial_branch, &repo_fmt, - flags & INIT_DB_QUIET); - if (reinit && initial_branch) - warning(_("re-init: ignored --initial-branch=%s"), - initial_branch); - - create_object_directory(); - - if (get_shared_repository()) { - char buf[10]; - /* We do not spell "group" and such, so that - * the configuration can be read by older version - * of git. Note, we use octal numbers for new share modes, - * and compatibility values for PERM_GROUP and - * PERM_EVERYBODY. - */ - if (get_shared_repository() < 0) - /* force to the mode value */ - xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository()); - else if (get_shared_repository() == PERM_GROUP) - xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP); - else if (get_shared_repository() == PERM_EVERYBODY) - xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY); - else - BUG("invalid value for shared_repository"); - git_config_set("core.sharedrepository", buf); - git_config_set("receive.denyNonFastforwards", "true"); - } - - if (!(flags & INIT_DB_QUIET)) { - int len = strlen(git_dir); - - if (reinit) - printf(get_shared_repository() - ? _("Reinitialized existing shared Git repository in %s%s\n") - : _("Reinitialized existing Git repository in %s%s\n"), - git_dir, len && git_dir[len-1] != '/' ? "/" : ""); - else - printf(get_shared_repository() - ? _("Initialized empty shared Git repository in %s%s\n") - : _("Initialized empty Git repository in %s%s\n"), - git_dir, len && git_dir[len-1] != '/' ? "/" : ""); - } - - free(original_git_dir); - return 0; -} - static int guess_repository_type(const char *git_dir) { const char *slash; @@ -546,6 +79,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) const char *object_format = NULL; const char *initial_branch = NULL; int hash_algo = GIT_HASH_UNKNOWN; + int init_shared_repository = -1; const struct option init_db_options[] = { OPT_STRING(0, "template", &template_dir, N_("template-directory"), N_("directory from which templates will be used")), @@ -703,5 +237,5 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) flags |= INIT_DB_EXIST_OK; return init_db(git_dir, real_git_dir, template_dir, hash_algo, - initial_branch, flags); + initial_branch, init_shared_repository, flags); } diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 107ac28f0e..c5e8345265 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -5,7 +5,6 @@ * */ -#include "cache.h" #include "builtin.h" #include "gettext.h" #include "parse-options.h" diff --git a/builtin/log.c b/builtin/log.c index 676de107d6..1aca560ec3 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -14,7 +14,7 @@ #include "refs.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "pager.h" #include "color.h" #include "commit.h" @@ -564,7 +564,8 @@ static int cmd_log_walk(struct rev_info *rev) return retval; } -static int git_log_config(const char *var, const char *value, void *cb) +static int git_log_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { const char *slot_name; @@ -573,7 +574,7 @@ static int git_log_config(const char *var, const char *value, void *cb) if (!strcmp(var, "format.subjectprefix")) return git_config_string(&fmt_patch_subject_prefix, var, value); if (!strcmp(var, "format.filenamemaxlength")) { - fmt_patch_name_max = git_config_int(var, value); + fmt_patch_name_max = git_config_int(var, value, ctx->kvi); return 0; } if (!strcmp(var, "format.encodeemailheaders")) { @@ -613,7 +614,7 @@ static int git_log_config(const char *var, const char *value, void *cb) return 0; } - return git_diff_ui_config(var, value, cb); + return git_diff_ui_config(var, value, ctx, cb); } int cmd_whatchanged(int argc, const char **argv, const char *prefix) @@ -866,7 +867,7 @@ static void log_setup_revisions_tweak(struct rev_info *rev, struct setup_revision_opt *opt) { if (rev->diffopt.flags.default_follow_renames && - rev->prune_data.nr == 1) + diff_check_follow_pathspec(&rev->prune_data, 0)) rev->diffopt.flags.follow_renames = 1; if (rev->first_parent_only) @@ -979,7 +980,8 @@ static enum cover_from_description parse_cover_from_description(const char *arg) die(_("%s: invalid cover from description mode"), arg); } -static int git_format_config(const char *var, const char *value, void *cb) +static int git_format_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "format.headers")) { if (!value) @@ -1108,7 +1110,7 @@ static int git_format_config(const char *var, const char *value, void *cb) if (!strcmp(var, "diff.noprefix")) return 0; - return git_log_config(var, value, cb); + return git_log_config(var, value, ctx, cb); } static const char *output_directory = NULL; @@ -1406,7 +1408,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, } } -static const char *clean_message_id(const char *msg_id) +static char *clean_message_id(const char *msg_id) { char ch; const char *a, *z, *m; @@ -1424,7 +1426,7 @@ static const char *clean_message_id(const char *msg_id) if (!z) die(_("insane in-reply-to: %s"), msg_id); if (++z == m) - return a; + return xstrdup(a); return xmemdupz(a, z - a); } @@ -2310,11 +2312,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (in_reply_to || thread || cover_letter) { rev.ref_message_ids = xmalloc(sizeof(*rev.ref_message_ids)); - string_list_init_nodup(rev.ref_message_ids); + string_list_init_dup(rev.ref_message_ids); } if (in_reply_to) { - const char *msgid = clean_message_id(in_reply_to); - string_list_append(rev.ref_message_ids, msgid); + char *msgid = clean_message_id(in_reply_to); + string_list_append_nodup(rev.ref_message_ids, msgid); } rev.numbered_files = just_numbers; rev.patch_suffix = fmt_patch_suffix; @@ -2370,8 +2372,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) && (!cover_letter || rev.nr > 1)) free(rev.message_id); else - string_list_append(rev.ref_message_ids, - rev.message_id); + string_list_append_nodup(rev.ref_message_ids, + rev.message_id); } gen_message_id(&rev, oid_to_hex(&commit->object.oid)); } @@ -2420,6 +2422,7 @@ done: strbuf_release(&rdiff_title); strbuf_release(&sprefix); free(to_free); + free(rev.message_id); if (rev.ref_message_ids) string_list_clear(rev.ref_message_ids, 0); free(rev.ref_message_ids); diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 625f48f0d6..a0229c3277 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -5,13 +5,12 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#include "cache.h" +#include "builtin.h" #include "repository.h" #include "config.h" #include "convert.h" #include "quote.h" #include "dir.h" -#include "builtin.h" #include "gettext.h" #include "object-name.h" #include "strbuf.h" @@ -20,11 +19,17 @@ #include "parse-options.h" #include "resolve-undo.h" #include "string-list.h" +#include "path.h" #include "pathspec.h" +#include "read-cache.h" #include "run-command.h" #include "setup.h" +#include "sparse-index.h" #include "submodule.h" #include "submodule-config.h" +#include "object-store.h" +#include "hex.h" + static int abbrev; static int show_deleted; @@ -241,68 +246,75 @@ static void show_submodule(struct repository *superproject, repo_clear(&subrepo); } -struct show_index_data { - const char *pathname; - struct index_state *istate; - const struct cache_entry *ce; -}; - -static size_t expand_show_index(struct strbuf *sb, const char *start, - void *context) +static void expand_objectsize(struct strbuf *line, const struct object_id *oid, + const enum object_type type, unsigned int padded) { - struct show_index_data *data = context; - const char *end; - const char *p; - size_t len = strbuf_expand_literal_cb(sb, start, NULL); - struct stat st; - - if (len) - return len; - if (*start != '(') - die(_("bad ls-files format: element '%s' " - "does not start with '('"), start); - - end = strchr(start + 1, ')'); - if (!end) - die(_("bad ls-files format: element '%s' " - "does not end in ')'"), start); - - len = end - start + 1; - if (skip_prefix(start, "(objectmode)", &p)) - strbuf_addf(sb, "%06o", data->ce->ce_mode); - else if (skip_prefix(start, "(objectname)", &p)) - strbuf_add_unique_abbrev(sb, &data->ce->oid, abbrev); - else if (skip_prefix(start, "(stage)", &p)) - strbuf_addf(sb, "%d", ce_stage(data->ce)); - else if (skip_prefix(start, "(eolinfo:index)", &p)) - strbuf_addstr(sb, S_ISREG(data->ce->ce_mode) ? - get_cached_convert_stats_ascii(data->istate, - data->ce->name) : ""); - else if (skip_prefix(start, "(eolinfo:worktree)", &p)) - strbuf_addstr(sb, !lstat(data->pathname, &st) && - S_ISREG(st.st_mode) ? - get_wt_convert_stats_ascii(data->pathname) : ""); - else if (skip_prefix(start, "(eolattr)", &p)) - strbuf_addstr(sb, get_convert_attr_ascii(data->istate, - data->pathname)); - else if (skip_prefix(start, "(path)", &p)) - write_name_to_buf(sb, data->pathname); - else - die(_("bad ls-files format: %%%.*s"), (int)len, start); - - return len; + if (type == OBJ_BLOB) { + unsigned long size; + if (oid_object_info(the_repository, oid, &size) < 0) + die(_("could not get object info about '%s'"), + oid_to_hex(oid)); + if (padded) + strbuf_addf(line, "%7"PRIuMAX, (uintmax_t)size); + else + strbuf_addf(line, "%"PRIuMAX, (uintmax_t)size); + } else if (padded) { + strbuf_addf(line, "%7s", "-"); + } else { + strbuf_addstr(line, "-"); + } } static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, const char *format, const char *fullname) { - struct show_index_data data = { - .pathname = fullname, - .istate = repo->index, - .ce = ce, - }; struct strbuf sb = STRBUF_INIT; - strbuf_expand(&sb, format, expand_show_index, &data); + while (strbuf_expand_step(&sb, &format)) { + const char *end; + size_t len; + struct stat st; + + if (skip_prefix(format, "%", &format)) + strbuf_addch(&sb, '%'); + else if ((len = strbuf_expand_literal(&sb, format))) + format += len; + else if (*format != '(') + die(_("bad ls-files format: element '%s' " + "does not start with '('"), format); + else if (!(end = strchr(format + 1, ')'))) + die(_("bad ls-files format: element '%s' " + "does not end in ')'"), format); + else if (skip_prefix(format, "(objectmode)", &format)) + strbuf_addf(&sb, "%06o", ce->ce_mode); + else if (skip_prefix(format, "(objectname)", &format)) + strbuf_add_unique_abbrev(&sb, &ce->oid, abbrev); + else if (skip_prefix(format, "(objecttype)", &format)) + strbuf_addstr(&sb, type_name(object_type(ce->ce_mode))); + else if (skip_prefix(format, "(objectsize:padded)", &format)) + expand_objectsize(&sb, &ce->oid, + object_type(ce->ce_mode), 1); + else if (skip_prefix(format, "(objectsize)", &format)) + expand_objectsize(&sb, &ce->oid, + object_type(ce->ce_mode), 0); + else if (skip_prefix(format, "(stage)", &format)) + strbuf_addf(&sb, "%d", ce_stage(ce)); + else if (skip_prefix(format, "(eolinfo:index)", &format)) + strbuf_addstr(&sb, S_ISREG(ce->ce_mode) ? + get_cached_convert_stats_ascii(repo->index, + ce->name) : ""); + else if (skip_prefix(format, "(eolinfo:worktree)", &format)) + strbuf_addstr(&sb, !lstat(fullname, &st) && + S_ISREG(st.st_mode) ? + get_wt_convert_stats_ascii(fullname) : ""); + else if (skip_prefix(format, "(eolattr)", &format)) + strbuf_addstr(&sb, get_convert_attr_ascii(repo->index, + fullname)); + else if (skip_prefix(format, "(path)", &format)) + write_name_to_buf(&sb, fullname); + else + die(_("bad ls-files format: %%%.*s"), + (int)(end - format + 1), format); + } strbuf_addch(&sb, line_terminator); fwrite(sb.buf, sb.len, 1, stdout); strbuf_release(&sb); @@ -516,143 +528,6 @@ static int get_common_prefix_len(const char *common_prefix) return common_prefix_len; } -static int read_one_entry_opt(struct index_state *istate, - const struct object_id *oid, - struct strbuf *base, - const char *pathname, - unsigned mode, int opt) -{ - int len; - struct cache_entry *ce; - - if (S_ISDIR(mode)) - return READ_TREE_RECURSIVE; - - len = strlen(pathname); - ce = make_empty_cache_entry(istate, base->len + len); - - ce->ce_mode = create_ce_mode(mode); - ce->ce_flags = create_ce_flags(1); - ce->ce_namelen = base->len + len; - memcpy(ce->name, base->buf, base->len); - memcpy(ce->name + base->len, pathname, len+1); - oidcpy(&ce->oid, oid); - return add_index_entry(istate, ce, opt); -} - -static int read_one_entry(const struct object_id *oid, struct strbuf *base, - const char *pathname, unsigned mode, - void *context) -{ - struct index_state *istate = context; - return read_one_entry_opt(istate, oid, base, pathname, - mode, - ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); -} - -/* - * This is used when the caller knows there is no existing entries at - * the stage that will conflict with the entry being added. - */ -static int read_one_entry_quick(const struct object_id *oid, struct strbuf *base, - const char *pathname, unsigned mode, - void *context) -{ - struct index_state *istate = context; - return read_one_entry_opt(istate, oid, base, pathname, - mode, ADD_CACHE_JUST_APPEND); -} - -/* - * Read the tree specified with --with-tree option - * (typically, HEAD) into stage #1 and then - * squash them down to stage #0. This is used for - * --error-unmatch to list and check the path patterns - * that were given from the command line. We are not - * going to write this index out. - */ -void overlay_tree_on_index(struct index_state *istate, - const char *tree_name, const char *prefix) -{ - struct tree *tree; - struct object_id oid; - struct pathspec pathspec; - struct cache_entry *last_stage0 = NULL; - int i; - read_tree_fn_t fn = NULL; - int err; - - if (repo_get_oid(the_repository, tree_name, &oid)) - die("tree-ish %s not found.", tree_name); - tree = parse_tree_indirect(&oid); - if (!tree) - die("bad tree-ish %s", tree_name); - - /* Hoist the unmerged entries up to stage #3 to make room */ - /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(istate); - for (i = 0; i < istate->cache_nr; i++) { - struct cache_entry *ce = istate->cache[i]; - if (!ce_stage(ce)) - continue; - ce->ce_flags |= CE_STAGEMASK; - } - - if (prefix) { - static const char *(matchbuf[1]); - matchbuf[0] = NULL; - parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC, - PATHSPEC_PREFER_CWD, prefix, matchbuf); - } else - memset(&pathspec, 0, sizeof(pathspec)); - - /* - * See if we have cache entry at the stage. If so, - * do it the original slow way, otherwise, append and then - * sort at the end. - */ - for (i = 0; !fn && i < istate->cache_nr; i++) { - const struct cache_entry *ce = istate->cache[i]; - if (ce_stage(ce) == 1) - fn = read_one_entry; - } - - if (!fn) - fn = read_one_entry_quick; - err = read_tree(the_repository, tree, &pathspec, fn, istate); - clear_pathspec(&pathspec); - if (err) - die("unable to read tree entries %s", tree_name); - - /* - * Sort the cache entry -- we need to nuke the cache tree, though. - */ - if (fn == read_one_entry_quick) { - cache_tree_free(&istate->cache_tree); - QSORT(istate->cache, istate->cache_nr, cmp_cache_name_compare); - } - - for (i = 0; i < istate->cache_nr; i++) { - struct cache_entry *ce = istate->cache[i]; - switch (ce_stage(ce)) { - case 0: - last_stage0 = ce; - /* fallthru */ - default: - continue; - case 1: - /* - * If there is stage #0 entry for this, we do not - * need to show it. We use CE_UPDATE bit to mark - * such an entry. - */ - if (last_stage0 && - !strcmp(last_stage0->name, ce->name)) - ce->ce_flags |= CE_UPDATE; - } - } -} - static const char * const ls_files_usage[] = { N_("git ls-files [<options>] [<file>...]"), NULL diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index cb6cb77e08..fc76575430 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -1,5 +1,4 @@ #include "builtin.h" -#include "cache.h" #include "gettext.h" #include "hex.h" #include "transport.h" @@ -8,6 +7,7 @@ #include "remote.h" #include "refs.h" #include "parse-options.h" +#include "wildmatch.h" static const char * const ls_remote_usage[] = { N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 077977a461..53073d64cb 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -3,17 +3,17 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "gettext.h" #include "hex.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "blob.h" #include "tree.h" #include "commit.h" +#include "path.h" #include "quote.h" -#include "builtin.h" #include "parse-options.h" #include "pathspec.h" @@ -50,68 +50,10 @@ struct ls_tree_options { LS_SHOW_TREES = 1 << 2, } ls_options; struct pathspec pathspec; - int chomp_prefix; - const char *ls_tree_prefix; + const char *prefix; const char *format; }; -struct show_tree_data { - struct ls_tree_options *options; - unsigned mode; - enum object_type type; - const struct object_id *oid; - const char *pathname; - struct strbuf *base; -}; - -static size_t expand_show_tree(struct strbuf *sb, const char *start, - void *context) -{ - struct show_tree_data *data = context; - struct ls_tree_options *options = data->options; - const char *end; - const char *p; - unsigned int errlen; - size_t len = strbuf_expand_literal_cb(sb, start, NULL); - - if (len) - return len; - if (*start != '(') - die(_("bad ls-tree format: element '%s' does not start with '('"), start); - - end = strchr(start + 1, ')'); - if (!end) - die(_("bad ls-tree format: element '%s' does not end in ')'"), start); - - len = end - start + 1; - if (skip_prefix(start, "(objectmode)", &p)) { - strbuf_addf(sb, "%06o", data->mode); - } else if (skip_prefix(start, "(objecttype)", &p)) { - strbuf_addstr(sb, type_name(data->type)); - } else if (skip_prefix(start, "(objectsize:padded)", &p)) { - expand_objectsize(sb, data->oid, data->type, 1); - } else if (skip_prefix(start, "(objectsize)", &p)) { - expand_objectsize(sb, data->oid, data->type, 0); - } else if (skip_prefix(start, "(objectname)", &p)) { - strbuf_add_unique_abbrev(sb, data->oid, options->abbrev); - } else if (skip_prefix(start, "(path)", &p)) { - const char *name = data->base->buf; - const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; - struct strbuf sbuf = STRBUF_INIT; - size_t baselen = data->base->len; - - strbuf_addstr(data->base, data->pathname); - name = relative_path(data->base->buf, prefix, &sbuf); - quote_c_style(name, sb, NULL, 0); - strbuf_setlen(data->base, baselen); - strbuf_release(&sbuf); - } else { - errlen = (unsigned long)len; - die(_("bad ls-tree format: %%%.*s"), errlen, start); - } - return len; -} - static int show_recursive(struct ls_tree_options *options, const char *base, size_t baselen, const char *pathname) { @@ -150,14 +92,7 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, int recurse = 0; struct strbuf sb = STRBUF_INIT; enum object_type type = object_type(mode); - struct show_tree_data cb_data = { - .options = options, - .mode = mode, - .type = type, - .oid = oid, - .pathname = pathname, - .base = base, - }; + const char *format = options->format; if (type == OBJ_TREE && show_recursive(options, base->buf, base->len, pathname)) recurse = READ_TREE_RECURSIVE; @@ -166,7 +101,45 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, if (type == OBJ_BLOB && (options->ls_options & LS_TREE_ONLY)) return 0; - strbuf_expand(&sb, options->format, expand_show_tree, &cb_data); + while (strbuf_expand_step(&sb, &format)) { + const char *end; + size_t len; + + if (skip_prefix(format, "%", &format)) + strbuf_addch(&sb, '%'); + else if ((len = strbuf_expand_literal(&sb, format))) + format += len; + else if (*format != '(') + die(_("bad ls-tree format: element '%s' " + "does not start with '('"), format); + else if (!(end = strchr(format + 1, ')'))) + die(_("bad ls-tree format: element '%s' " + "does not end in ')'"), format); + else if (skip_prefix(format, "(objectmode)", &format)) + strbuf_addf(&sb, "%06o", mode); + else if (skip_prefix(format, "(objecttype)", &format)) + strbuf_addstr(&sb, type_name(type)); + else if (skip_prefix(format, "(objectsize:padded)", &format)) + expand_objectsize(&sb, oid, type, 1); + else if (skip_prefix(format, "(objectsize)", &format)) + expand_objectsize(&sb, oid, type, 0); + else if (skip_prefix(format, "(objectname)", &format)) + strbuf_add_unique_abbrev(&sb, oid, options->abbrev); + else if (skip_prefix(format, "(path)", &format)) { + const char *name; + const char *prefix = options->prefix; + struct strbuf sbuf = STRBUF_INIT; + size_t baselen = base->len; + + strbuf_addstr(base, pathname); + name = relative_path(base->buf, prefix, &sbuf); + quote_c_style(name, &sb, NULL, 0); + strbuf_setlen(base, baselen); + strbuf_release(&sbuf); + } else + die(_("bad ls-tree format: %%%.*s"), + (int)(end - format + 1), format); + } strbuf_addch(&sb, options->null_termination ? '\0' : '\n'); fwrite(sb.buf, sb.len, 1, stdout); strbuf_release(&sb); @@ -198,7 +171,7 @@ static void show_tree_common_default_long(struct ls_tree_options *options, const char *pathname, const size_t baselen) { - const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; + const char *prefix = options->prefix; strbuf_addstr(base, pathname); @@ -283,7 +256,7 @@ static int show_tree_name_only(const struct object_id *oid, struct strbuf *base, if (early >= 0) return early; - prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; + prefix = options->prefix; strbuf_addstr(base, pathname); if (options->null_termination) { struct strbuf sb = STRBUF_INIT; @@ -370,6 +343,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) struct object_id oid; struct tree *tree; int i, full_tree = 0; + int chomp_prefix = prefix && *prefix; read_tree_fn_t fn = NULL; enum ls_tree_cmdmode cmdmode = MODE_DEFAULT; int null_termination = 0; @@ -391,7 +365,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) MODE_NAME_STATUS), OPT_CMDMODE(0, "object-only", &cmdmode, N_("list only objects"), MODE_OBJECT_ONLY), - OPT_SET_INT(0, "full-name", &options.chomp_prefix, + OPT_SET_INT(0, "full-name", &chomp_prefix, N_("use full path names"), 0), OPT_BOOL(0, "full-tree", &full_tree, N_("list entire tree; not just current directory " @@ -406,18 +380,15 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) int ret; git_config(git_default_config, NULL); - options.ls_tree_prefix = prefix; - if (prefix) - options.chomp_prefix = strlen(prefix); argc = parse_options(argc, argv, prefix, ls_tree_options, ls_tree_usage, 0); options.null_termination = null_termination; - if (full_tree) { - options.ls_tree_prefix = prefix = NULL; - options.chomp_prefix = 0; - } + if (full_tree) + prefix = NULL; + options.prefix = chomp_prefix ? prefix : NULL; + /* * We wanted to detect conflicts between --name-only and * --name-status, but once we're done with that subsequent diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index a032a1c388..53b55dd71c 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -2,9 +2,8 @@ * Another stupid program, this one parsing the headers of an * email to figure out authorship and subject */ -#include "cache.h" -#include "abspath.h" #include "builtin.h" +#include "abspath.h" #include "environment.h" #include "gettext.h" #include "utf8.h" diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c index 0b6193a091..3af9ddb8ae 100644 --- a/builtin/mailsplit.c +++ b/builtin/mailsplit.c @@ -4,7 +4,6 @@ * It just splits a mbox into a list of files: "0001" "0002" .. * so you can process them further from there. */ -#include "cache.h" #include "builtin.h" #include "gettext.h" #include "string-list.h" diff --git a/builtin/merge-base.c b/builtin/merge-base.c index 854019a32d..e68b7fe45d 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -1,5 +1,4 @@ #include "builtin.h" -#include "cache.h" #include "config.h" #include "commit.h" #include "gettext.h" diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 781818d08f..d7eb4c6540 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -1,6 +1,5 @@ #include "builtin.h" #include "abspath.h" -#include "cache.h" #include "config.h" #include "gettext.h" #include "setup.h" diff --git a/builtin/merge-index.c b/builtin/merge-index.c index ab16e70f23..270d5f644a 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -1,8 +1,10 @@ #define USE_THE_INDEX_VARIABLE #include "builtin.h" #include "hex.h" +#include "read-cache-ll.h" #include "repository.h" #include "run-command.h" +#include "sparse-index.h" static const char *pgm; static int one_shot, quiet; diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c index c2e519301e..932924e5d0 100644 --- a/builtin/merge-ours.c +++ b/builtin/merge-ours.c @@ -10,6 +10,7 @@ #include "git-compat-util.h" #include "builtin.h" #include "diff.h" +#include "repository.h" static const char builtin_merge_ours_usage[] = "git merge-ours <base>... -- HEAD <remote>..."; diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index b9e980384a..3366699657 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -1,4 +1,3 @@ -#include "cache.h" #include "builtin.h" #include "advice.h" #include "commit.h" diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index b8f8a8b5d9..6f7db436d2 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -9,7 +9,7 @@ #include "commit-reach.h" #include "merge-ort.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "parse-options.h" #include "repository.h" #include "blob.h" @@ -448,7 +448,7 @@ static int real_merge(struct merge_tree_options *o, base_commit = lookup_commit_reference_by_name(merge_base); if (!base_commit) - die(_("could not lookup commit %s"), merge_base); + die(_("could not lookup commit '%s'"), merge_base); opt.ancestor = merge_base; base_tree = repo_get_commit_tree(the_repository, base_commit); diff --git a/builtin/merge.c b/builtin/merge.c index 8da3e46abb..06cf6afdcb 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -7,7 +7,7 @@ */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "abspath.h" #include "advice.h" #include "alloc.h" @@ -18,7 +18,6 @@ #include "hex.h" #include "object-name.h" #include "parse-options.h" -#include "builtin.h" #include "lockfile.h" #include "run-command.h" #include "hook.h" @@ -28,6 +27,7 @@ #include "refspec.h" #include "commit.h" #include "diffcore.h" +#include "path.h" #include "revision.h" #include "unpack-trees.h" #include "cache-tree.h" @@ -37,6 +37,7 @@ #include "color.h" #include "rerere.h" #include "help.h" +#include "merge.h" #include "merge-recursive.h" #include "merge-ort-wrappers.h" #include "resolve-undo.h" @@ -623,7 +624,8 @@ static void parse_branch_merge_options(char *bmo) free(argv); } -static int git_merge_config(const char *k, const char *v, void *cb) +static int git_merge_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { int status; const char *str; @@ -668,10 +670,10 @@ static int git_merge_config(const char *k, const char *v, void *cb) return 0; } - status = fmt_merge_msg_config(k, v, cb); + status = fmt_merge_msg_config(k, v, ctx, cb); if (status) return status; - return git_diff_ui_config(k, v, cb); + return git_diff_ui_config(k, v, ctx, cb); } static int read_tree_trivial(struct object_id *common, struct object_id *head, @@ -879,13 +881,15 @@ static void prepare_to_commit(struct commit_list *remoteheads) strbuf_addch(&msg, '\n'); if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) { wt_status_append_cut_line(&msg); - strbuf_commented_addf(&msg, "\n"); + strbuf_commented_addf(&msg, comment_line_char, "\n"); } - strbuf_commented_addf(&msg, _(merge_editor_comment)); + strbuf_commented_addf(&msg, comment_line_char, + _(merge_editor_comment)); if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) - strbuf_commented_addf(&msg, _(scissors_editor_comment)); + strbuf_commented_addf(&msg, comment_line_char, + _(scissors_editor_comment)); else - strbuf_commented_addf(&msg, + strbuf_commented_addf(&msg, comment_line_char, _(no_scissors_editor_comment), comment_line_char); } if (signoff) diff --git a/builtin/mktag.c b/builtin/mktag.c index 44fa56eff3..43e2766db4 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -2,10 +2,11 @@ #include "gettext.h" #include "hex.h" #include "parse-options.h" +#include "strbuf.h" #include "tag.h" #include "replace-object.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "fsck.h" #include "config.h" diff --git a/builtin/mktree.c b/builtin/mktree.c index 09a7bd5c5c..0eea810c7e 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -8,9 +8,10 @@ #include "gettext.h" #include "hex.h" #include "quote.h" +#include "strbuf.h" #include "tree.h" #include "parse-options.h" -#include "object-store.h" +#include "object-store-ll.h" static struct treeent { unsigned mode; diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c index 1b5083f8b2..a72aebecaa 100644 --- a/builtin/multi-pack-index.c +++ b/builtin/multi-pack-index.c @@ -1,13 +1,13 @@ #include "builtin.h" #include "abspath.h" -#include "cache.h" #include "config.h" #include "environment.h" #include "gettext.h" #include "parse-options.h" #include "midx.h" +#include "strbuf.h" #include "trace2.h" -#include "object-store.h" +#include "object-store-ll.h" #define BUILTIN_MIDX_WRITE_USAGE \ N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]" \ @@ -82,6 +82,7 @@ static struct option *add_common_options(struct option *prev) } static int git_multi_pack_index_write_config(const char *var, const char *value, + const struct config_context *ctx UNUSED, void *cb UNUSED) { if (!strcmp(var, "pack.writebitmaphashcache")) { diff --git a/builtin/mv.c b/builtin/mv.c index 665bd27448..ae462bd7d4 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -11,6 +11,7 @@ #include "config.h" #include "environment.h" #include "gettext.h" +#include "name-hash.h" #include "object-file.h" #include "pathspec.h" #include "lockfile.h" @@ -18,6 +19,7 @@ #include "cache-tree.h" #include "string-list.h" #include "parse-options.h" +#include "read-cache-ll.h" #include "repository.h" #include "setup.h" #include "submodule.h" diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 4d15a23fc4..c3b722b36f 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -15,6 +15,7 @@ #include "hash-lookup.h" #include "commit-slab.h" #include "commit-graph.h" +#include "wildmatch.h" /* * One day. See the 'name a rev shortly after epoch' test in t6120 when diff --git a/builtin/notes.c b/builtin/notes.c index d5788352b6..9f38863dd5 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -7,15 +7,17 @@ * and builtin/tag.c by Kristian Høgsberg and Carlos Rica. */ -#include "cache.h" -#include "config.h" #include "builtin.h" +#include "config.h" +#include "alloc.h" #include "editor.h" +#include "environment.h" #include "gettext.h" #include "hex.h" #include "notes.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" +#include "path.h" #include "repository.h" #include "blob.h" #include "pretty.h" @@ -29,11 +31,12 @@ #include "worktree.h" #include "write-or-die.h" +static const char *separator = "\n"; static const char * const git_notes_usage[] = { N_("git notes [--ref <notes-ref>] [list [<object>]]"), - N_("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"), + N_("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"), N_("git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>"), - N_("git notes [--ref <notes-ref>] append [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"), + N_("git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"), N_("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"), N_("git notes [--ref <notes-ref>] show [<object>]"), N_("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"), @@ -101,11 +104,26 @@ static const char * const git_notes_get_ref_usage[] = { static const char note_template[] = N_("Write/edit the notes for the following object:"); +enum notes_stripspace { + UNSPECIFIED = -1, + NO_STRIPSPACE = 0, + STRIPSPACE = 1, +}; + +struct note_msg { + enum notes_stripspace stripspace; + struct strbuf buf; +}; + struct note_data { int given; int use_editor; + int stripspace; char *edit_path; struct strbuf buf; + struct note_msg **messages; + size_t msg_nr; + size_t msg_alloc; }; static void free_note_data(struct note_data *d) @@ -115,6 +133,12 @@ static void free_note_data(struct note_data *d) free(d->edit_path); } strbuf_release(&d->buf); + + while (d->msg_nr--) { + strbuf_release(&d->messages[d->msg_nr]->buf); + free(d->messages[d->msg_nr]); + } + free(d->messages); } static int list_each_note(const struct object_id *object_oid, @@ -157,7 +181,7 @@ static void write_commented_object(int fd, const struct object_id *object) if (strbuf_read(&buf, show.out, 0) < 0) die_errno(_("could not read 'show' output")); - strbuf_add_commented_lines(&cbuf, buf.buf, buf.len); + strbuf_add_commented_lines(&cbuf, buf.buf, buf.len, comment_line_char); write_or_die(fd, cbuf.buf, cbuf.len); strbuf_release(&cbuf); @@ -185,9 +209,10 @@ static void prepare_note_data(const struct object_id *object, struct note_data * copy_obj_to_fd(fd, old_note); strbuf_addch(&buf, '\n'); - strbuf_add_commented_lines(&buf, "\n", strlen("\n")); - strbuf_add_commented_lines(&buf, _(note_template), strlen(_(note_template))); - strbuf_add_commented_lines(&buf, "\n", strlen("\n")); + strbuf_add_commented_lines(&buf, "\n", strlen("\n"), comment_line_char); + strbuf_add_commented_lines(&buf, _(note_template), strlen(_(note_template)), + comment_line_char); + strbuf_add_commented_lines(&buf, "\n", strlen("\n"), comment_line_char); write_or_die(fd, buf.buf, buf.len); write_commented_object(fd, object); @@ -199,7 +224,8 @@ static void prepare_note_data(const struct object_id *object, struct note_data * if (launch_editor(d->edit_path, &d->buf, NULL)) { die(_("please supply the note contents using either -m or -F option")); } - strbuf_stripspace(&d->buf, 1); + if (d->stripspace) + strbuf_stripspace(&d->buf, comment_line_char); } } @@ -215,66 +241,102 @@ static void write_note_data(struct note_data *d, struct object_id *oid) } } +static void append_separator(struct strbuf *message) +{ + size_t sep_len = 0; + + if (!separator) + return; + else if ((sep_len = strlen(separator)) && separator[sep_len - 1] == '\n') + strbuf_addstr(message, separator); + else + strbuf_addf(message, "%s%s", separator, "\n"); +} + +static void concat_messages(struct note_data *d) +{ + struct strbuf msg = STRBUF_INIT; + size_t i; + + for (i = 0; i < d->msg_nr ; i++) { + if (d->buf.len) + append_separator(&d->buf); + strbuf_add(&msg, d->messages[i]->buf.buf, d->messages[i]->buf.len); + strbuf_addbuf(&d->buf, &msg); + if ((d->stripspace == UNSPECIFIED && + d->messages[i]->stripspace == STRIPSPACE) || + d->stripspace == STRIPSPACE) + strbuf_stripspace(&d->buf, 0); + strbuf_reset(&msg); + } + strbuf_release(&msg); +} + static int parse_msg_arg(const struct option *opt, const char *arg, int unset) { struct note_data *d = opt->value; + struct note_msg *msg = xmalloc(sizeof(*msg)); BUG_ON_OPT_NEG(unset); - strbuf_grow(&d->buf, strlen(arg) + 2); - if (d->buf.len) - strbuf_addch(&d->buf, '\n'); - strbuf_addstr(&d->buf, arg); - strbuf_stripspace(&d->buf, 0); - - d->given = 1; + strbuf_init(&msg->buf, strlen(arg)); + strbuf_addstr(&msg->buf, arg); + ALLOC_GROW_BY(d->messages, d->msg_nr, 1, d->msg_alloc); + d->messages[d->msg_nr - 1] = msg; + msg->stripspace = STRIPSPACE; return 0; } static int parse_file_arg(const struct option *opt, const char *arg, int unset) { struct note_data *d = opt->value; + struct note_msg *msg = xmalloc(sizeof(*msg)); BUG_ON_OPT_NEG(unset); - if (d->buf.len) - strbuf_addch(&d->buf, '\n'); + strbuf_init(&msg->buf , 0); if (!strcmp(arg, "-")) { - if (strbuf_read(&d->buf, 0, 1024) < 0) + if (strbuf_read(&msg->buf, 0, 1024) < 0) die_errno(_("cannot read '%s'"), arg); - } else if (strbuf_read_file(&d->buf, arg, 1024) < 0) + } else if (strbuf_read_file(&msg->buf, arg, 1024) < 0) die_errno(_("could not open or read '%s'"), arg); - strbuf_stripspace(&d->buf, 0); - d->given = 1; + ALLOC_GROW_BY(d->messages, d->msg_nr, 1, d->msg_alloc); + d->messages[d->msg_nr - 1] = msg; + msg->stripspace = STRIPSPACE; return 0; } static int parse_reuse_arg(const struct option *opt, const char *arg, int unset) { struct note_data *d = opt->value; - char *buf; + struct note_msg *msg = xmalloc(sizeof(*msg)); + char *value; struct object_id object; enum object_type type; unsigned long len; BUG_ON_OPT_NEG(unset); - if (d->buf.len) - strbuf_addch(&d->buf, '\n'); - + strbuf_init(&msg->buf, 0); if (repo_get_oid(the_repository, arg, &object)) die(_("failed to resolve '%s' as a valid ref."), arg); - if (!(buf = repo_read_object_file(the_repository, &object, &type, &len))) + if (!(value = repo_read_object_file(the_repository, &object, &type, &len))) die(_("failed to read object '%s'."), arg); if (type != OBJ_BLOB) { - free(buf); + strbuf_release(&msg->buf); + free(value); + free(msg); die(_("cannot read note data from non-blob object '%s'."), arg); } - strbuf_add(&d->buf, buf, len); - free(buf); - d->given = 1; + strbuf_add(&msg->buf, value, len); + free(value); + + msg->buf.len = len; + ALLOC_GROW_BY(d->messages, d->msg_nr, 1, d->msg_alloc); + d->messages[d->msg_nr - 1] = msg; + msg->stripspace = NO_STRIPSPACE; return 0; } @@ -286,6 +348,16 @@ static int parse_reedit_arg(const struct option *opt, const char *arg, int unset return parse_reuse_arg(opt, arg, unset); } +static int parse_separator_arg(const struct option *opt, const char *arg, + int unset) +{ + if (unset) + *(const char **)opt->value = NULL; + else + *(const char **)opt->value = arg ? arg : "\n"; + return 0; +} + static int notes_copy_from_stdin(int force, const char *rewrite_cmd) { struct strbuf buf = STRBUF_INIT; @@ -408,7 +480,8 @@ static int add(int argc, const char **argv, const char *prefix) struct notes_tree *t; struct object_id object, new_note; const struct object_id *note; - struct note_data d = { 0, 0, NULL, STRBUF_INIT }; + struct note_data d = { .buf = STRBUF_INIT, .stripspace = UNSPECIFIED }; + struct option options[] = { OPT_CALLBACK_F('m', "message", &d, N_("message"), N_("note contents as a string"), PARSE_OPT_NONEG, @@ -425,6 +498,12 @@ static int add(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "allow-empty", &allow_empty, N_("allow storing empty note")), OPT__FORCE(&force, N_("replace existing notes"), PARSE_OPT_NOCOMPLETE), + OPT_CALLBACK_F(0, "separator", &separator, + N_("<paragraph-break>"), + N_("insert <paragraph-break> between paragraphs"), + PARSE_OPT_OPTARG, parse_separator_arg), + OPT_BOOL(0, "stripspace", &d.stripspace, + N_("remove unnecessary whitespace")), OPT_END() }; @@ -436,6 +515,10 @@ static int add(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_add_usage, options); } + if (d.msg_nr) + concat_messages(&d); + d.given = !!d.buf.len; + object_ref = argc > 1 ? argv[1] : "HEAD"; if (repo_get_oid(the_repository, object_ref, &object)) @@ -574,7 +657,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) const struct object_id *note; char *logmsg; const char * const *usage; - struct note_data d = { 0, 0, NULL, STRBUF_INIT }; + struct note_data d = { .buf = STRBUF_INIT, .stripspace = UNSPECIFIED }; struct option options[] = { OPT_CALLBACK_F('m', "message", &d, N_("message"), N_("note contents as a string"), PARSE_OPT_NONEG, @@ -590,6 +673,12 @@ static int append_edit(int argc, const char **argv, const char *prefix) parse_reuse_arg), OPT_BOOL(0, "allow-empty", &allow_empty, N_("allow storing empty note")), + OPT_CALLBACK_F(0, "separator", &separator, + N_("<paragraph-break>"), + N_("insert <paragraph-break> between paragraphs"), + PARSE_OPT_OPTARG, parse_separator_arg), + OPT_BOOL(0, "stripspace", &d.stripspace, + N_("remove unnecessary whitespace")), OPT_END() }; int edit = !strcmp(argv[0], "edit"); @@ -603,6 +692,10 @@ static int append_edit(int argc, const char **argv, const char *prefix) usage_with_options(usage, options); } + if (d.msg_nr) + concat_messages(&d); + d.given = !!d.buf.len; + if (d.given && edit) fprintf(stderr, _("The -m/-F/-c/-C options have been deprecated " "for the 'edit' subcommand.\n" @@ -622,15 +715,17 @@ static int append_edit(int argc, const char **argv, const char *prefix) /* Append buf to previous note contents */ unsigned long size; enum object_type type; - char *prev_buf = repo_read_object_file(the_repository, note, - &type, &size); + struct strbuf buf = STRBUF_INIT; + char *prev_buf = repo_read_object_file(the_repository, note, &type, &size); - strbuf_grow(&d.buf, size + 1); - if (d.buf.len && prev_buf && size) - strbuf_insertstr(&d.buf, 0, "\n"); if (prev_buf && size) - strbuf_insert(&d.buf, 0, prev_buf, size); + strbuf_add(&buf, prev_buf, size); + if (d.buf.len && prev_buf && size) + append_separator(&buf); + strbuf_insert(&d.buf, 0, buf.buf, buf.len); + free(prev_buf); + strbuf_release(&buf); } if (d.buf.len || allow_empty) { diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 9cfc8801f9..8e77638145 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -34,7 +34,7 @@ #include "list.h" #include "packfile.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "replace-object.h" #include "dir.h" #include "midx.h" @@ -3135,26 +3135,27 @@ static void prepare_pack(int window, int depth) free(delta_list); } -static int git_pack_config(const char *k, const char *v, void *cb) +static int git_pack_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { if (!strcmp(k, "pack.window")) { - window = git_config_int(k, v); + window = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.windowmemory")) { - window_memory_limit = git_config_ulong(k, v); + window_memory_limit = git_config_ulong(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.depth")) { - depth = git_config_int(k, v); + depth = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.deltacachesize")) { - max_delta_cache_size = git_config_int(k, v); + max_delta_cache_size = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.deltacachelimit")) { - cache_max_small_delta_size = git_config_int(k, v); + cache_max_small_delta_size = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.writebitmaphashcache")) { @@ -3180,7 +3181,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) return 0; } if (!strcmp(k, "pack.threads")) { - delta_search_threads = git_config_int(k, v); + delta_search_threads = git_config_int(k, v, ctx->kvi); if (delta_search_threads < 0) die(_("invalid number of threads specified (%d)"), delta_search_threads); @@ -3191,7 +3192,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) return 0; } if (!strcmp(k, "pack.indexversion")) { - pack_idx_opts.version = git_config_int(k, v); + pack_idx_opts.version = git_config_int(k, v, ctx->kvi); if (pack_idx_opts.version > 2) die(_("bad pack.indexVersion=%"PRIu32), pack_idx_opts.version); @@ -3227,7 +3228,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) ex->uri = xstrdup(pack_end + 1); oidmap_put(&configured_exclusions, ex); } - return git_default_config(k, v, cb); + return git_default_config(k, v, ctx, cb); } /* Counters for trace2 output when in --stdin-packs mode. */ @@ -4284,7 +4285,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (DFS_NUM_STATES > (1 << OE_DFS_STATE_BITS)) BUG("too many dfs states, increase OE_DFS_STATE_BITS"); - read_replace_refs = 0; + disable_replace_refs(); sparse = git_env_bool("GIT_TEST_PACK_SPARSE", -1); if (the_repository->gitdir) { diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index 43e9d12dfd..4c735ba069 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -11,7 +11,7 @@ #include "hex.h" #include "repository.h" #include "packfile.h" -#include "object-store.h" +#include "object-store-ll.h" #define BLKSIZE 512 diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index 9833815fb3..bcf383cac9 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -4,22 +4,45 @@ #include "parse-options.h" #include "refs.h" #include "repository.h" +#include "revision.h" static char const * const pack_refs_usage[] = { - N_("git pack-refs [--all] [--no-prune]"), + N_("git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude <pattern>]"), NULL }; int cmd_pack_refs(int argc, const char **argv, const char *prefix) { unsigned int flags = PACK_REFS_PRUNE; + static struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; + static struct string_list included_refs = STRING_LIST_INIT_NODUP; + struct pack_refs_opts pack_refs_opts = { .exclusions = &excludes, + .includes = &included_refs, + .flags = flags }; + static struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP; + struct string_list_item *item; + struct option opts[] = { - OPT_BIT(0, "all", &flags, N_("pack everything"), PACK_REFS_ALL), - OPT_BIT(0, "prune", &flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE), + OPT_BIT(0, "all", &pack_refs_opts.flags, N_("pack everything"), PACK_REFS_ALL), + OPT_BIT(0, "prune", &pack_refs_opts.flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE), + OPT_STRING_LIST(0, "include", pack_refs_opts.includes, N_("pattern"), + N_("references to include")), + OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"), + N_("references to exclude")), OPT_END(), }; git_config(git_default_config, NULL); if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) usage_with_options(pack_refs_usage, opts); - return refs_pack_refs(get_main_ref_store(the_repository), flags); + + for_each_string_list_item(item, &option_excluded_refs) + add_ref_exclusion(pack_refs_opts.exclusions, item->string); + + if (pack_refs_opts.flags & PACK_REFS_ALL) + string_list_append(pack_refs_opts.includes, "*"); + + if (!pack_refs_opts.includes->nr) + string_list_append(pack_refs_opts.includes, "refs/tags/*"); + + return refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts); } diff --git a/builtin/patch-id.c b/builtin/patch-id.c index 9d5585d3a7..3894d2b970 100644 --- a/builtin/patch-id.c +++ b/builtin/patch-id.c @@ -1,8 +1,8 @@ -#include "cache.h" #include "builtin.h" #include "config.h" #include "diff.h" #include "gettext.h" +#include "hash.h" #include "hex.h" #include "parse-options.h" @@ -196,7 +196,8 @@ struct patch_id_opts { int verbatim; }; -static int git_patch_id_config(const char *var, const char *value, void *cb) +static int git_patch_id_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { struct patch_id_opts *opts = cb; @@ -209,7 +210,7 @@ static int git_patch_id_config(const char *var, const char *value, void *cb) return 0; } - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } int cmd_patch_id(int argc, const char **argv, const char *prefix) diff --git a/builtin/prune.c b/builtin/prune.c index 5dc9b20720..57fe31467f 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -1,19 +1,20 @@ -#include "cache.h" +#include "builtin.h" #include "commit.h" #include "diff.h" +#include "dir.h" #include "environment.h" #include "gettext.h" #include "hex.h" #include "revision.h" -#include "builtin.h" #include "reachable.h" #include "parse-options.h" +#include "path.h" #include "progress.h" #include "prune-packed.h" #include "replace-object.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "shallow.h" static const char * const prune_usage[] = { @@ -164,7 +165,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix) expire = TIME_MAX; save_commit_buffer = 0; - read_replace_refs = 0; + disable_replace_refs(); repo_init_revisions(the_repository, &revs, prefix); argc = parse_options(argc, argv, prefix, options, prune_usage, 0); diff --git a/builtin/pull.c b/builtin/pull.c index 0c7bac97b7..be2b2c9ebc 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -6,12 +6,12 @@ * Fetch one or more remote refs and merge it/them into the current HEAD. */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "advice.h" #include "config.h" -#include "builtin.h" #include "gettext.h" #include "hex.h" +#include "merge.h" #include "object-name.h" #include "parse-options.h" #include "exec-cmd.h" @@ -19,6 +19,8 @@ #include "oid-array.h" #include "remote.h" #include "dir.h" +#include "path.h" +#include "read-cache-ll.h" #include "rebase.h" #include "refs.h" #include "refspec.h" @@ -361,7 +363,8 @@ static enum rebase_type config_get_rebase(int *rebase_unspecified) /** * Read config variables. */ -static int git_pull_config(const char *var, const char *value, void *cb) +static int git_pull_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "rebase.autostash")) { config_autostash = git_config_bool(var, value); @@ -374,7 +377,7 @@ static int git_pull_config(const char *var, const char *value, void *cb) check_trust_level = 0; } - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } /** diff --git a/builtin/push.c b/builtin/push.c index dbdf609daf..82603a5570 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -1,7 +1,7 @@ /* * "git push" */ -#include "cache.h" +#include "builtin.h" #include "advice.h" #include "branch.h" #include "config.h" @@ -10,7 +10,6 @@ #include "refs.h" #include "refspec.h" #include "run-command.h" -#include "builtin.h" #include "remote.h" #include "transport.h" #include "parse-options.h" @@ -510,7 +509,8 @@ static void set_push_cert_flags(int *flags, int v) } -static int git_push_config(const char *k, const char *v, void *cb) +static int git_push_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { const char *slot_name; int *flags = cb; @@ -577,7 +577,7 @@ static int git_push_config(const char *k, const char *v, void *cb) return 0; } - return git_default_config(k, v, NULL); + return git_default_config(k, v, ctx, NULL); } int cmd_push(int argc, const char **argv, const char *prefix) diff --git a/builtin/range-diff.c b/builtin/range-diff.c index 04339a92ea..e455a4795c 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -1,10 +1,10 @@ -#include "cache.h" #include "builtin.h" #include "gettext.h" #include "object-name.h" #include "parse-options.h" #include "range-diff.h" #include "config.h" +#include "repository.h" #include "revision.h" static const char * const builtin_range_diff_usage[] = { diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 440f19b1b8..1fec702a04 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -5,7 +5,7 @@ */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "config.h" #include "gettext.h" #include "hex.h" @@ -17,11 +17,11 @@ #include "cache-tree.h" #include "unpack-trees.h" #include "dir.h" -#include "builtin.h" #include "parse-options.h" #include "repository.h" #include "resolve-undo.h" #include "setup.h" +#include "sparse-index.h" #include "submodule.h" #include "submodule-config.h" @@ -102,12 +102,13 @@ static int debug_merge(const struct cache_entry * const *stages, return 0; } -static int git_read_tree_config(const char *var, const char *value, void *cb) +static int git_read_tree_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "submodule.recurse")) return git_default_submodule_config(var, value, cb); - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) diff --git a/builtin/rebase.c b/builtin/rebase.c index ace1d5e8d1..1b3f68d9b0 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -24,6 +24,7 @@ #include "object-file.h" #include "object-name.h" #include "parse-options.h" +#include "path.h" #include "commit.h" #include "diff.h" #include "wt-status.h" @@ -209,7 +210,7 @@ static int edit_todo_file(unsigned flags) if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0) return error_errno(_("could not read '%s'."), todo_file); - strbuf_stripspace(&todo_list.buf, 1); + strbuf_stripspace(&todo_list.buf, comment_line_char); res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags); if (!res && todo_list_write_to_file(the_repository, &new_todo, todo_file, NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS))) @@ -772,7 +773,8 @@ static void parse_rebase_merges_value(struct rebase_options *options, const char die(_("Unknown rebase-merges mode: %s"), value); } -static int rebase_config(const char *var, const char *value, void *data) +static int rebase_config(const char *var, const char *value, + const struct config_context *ctx, void *data) { struct rebase_options *opts = data; @@ -831,7 +833,7 @@ static int rebase_config(const char *var, const char *value, void *data) return git_config_string(&opts->default_backend, var, value); } - return git_default_config(var, value, data); + return git_default_config(var, value, ctx, data); } static int checkout_up_to_date(struct rebase_options *options) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 1a31a58367..faa8f84c5a 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -30,7 +30,8 @@ #include "oidset.h" #include "packfile.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" +#include "path.h" #include "protocol.h" #include "commit-reach.h" #include "server-info.h" @@ -139,7 +140,8 @@ static enum deny_action parse_deny_action(const char *var, const char *value) return DENY_IGNORE; } -static int receive_pack_config(const char *var, const char *value, void *cb) +static int receive_pack_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { int status = parse_hide_refs_config(var, value, "receive", &hidden_refs); @@ -157,12 +159,12 @@ static int receive_pack_config(const char *var, const char *value, void *cb) } if (strcmp(var, "receive.unpacklimit") == 0) { - receive_unpack_limit = git_config_int(var, value); + receive_unpack_limit = git_config_int(var, value, ctx->kvi); return 0; } if (strcmp(var, "transfer.unpacklimit") == 0) { - transfer_unpack_limit = git_config_int(var, value); + transfer_unpack_limit = git_config_int(var, value, ctx->kvi); return 0; } @@ -230,7 +232,7 @@ static int receive_pack_config(const char *var, const char *value, void *cb) return git_config_string(&cert_nonce_seed, var, value); if (strcmp(var, "receive.certnonceslop") == 0) { - nonce_stamp_slop_limit = git_config_ulong(var, value); + nonce_stamp_slop_limit = git_config_ulong(var, value, ctx->kvi); return 0; } @@ -245,12 +247,12 @@ static int receive_pack_config(const char *var, const char *value, void *cb) } if (strcmp(var, "receive.keepalive") == 0) { - keepalive_in_sec = git_config_int(var, value); + keepalive_in_sec = git_config_int(var, value, ctx->kvi); return 0; } if (strcmp(var, "receive.maxinputsize") == 0) { - max_input_size = git_config_int64(var, value); + max_input_size = git_config_int64(var, value, ctx->kvi); return 0; } @@ -266,7 +268,7 @@ static int receive_pack_config(const char *var, const char *value, void *cb) return 0; } - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } static void show_ref(const char *path, const struct object_id *oid) diff --git a/builtin/reflog.c b/builtin/reflog.c index a1fa0c855f..df63a5892e 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -1,8 +1,10 @@ #include "builtin.h" #include "config.h" #include "gettext.h" +#include "repository.h" #include "revision.h" #include "reachable.h" +#include "wildmatch.h" #include "worktree.h" #include "reflog.h" #include "parse-options.h" @@ -108,7 +110,8 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len) #define EXPIRE_TOTAL 01 #define EXPIRE_UNREACH 02 -static int reflog_expire_config(const char *var, const char *value, void *cb) +static int reflog_expire_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { const char *pattern, *key; size_t pattern_len; @@ -117,7 +120,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb) struct reflog_expire_cfg *ent; if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0) - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); if (!strcmp(key, "reflogexpire")) { slot = EXPIRE_TOTAL; @@ -128,7 +131,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb) if (git_config_expiry_date(&expire, var, value)) return -1; } else - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); if (!pattern) { switch (slot) { diff --git a/builtin/remote.c b/builtin/remote.c index 1e0b137d97..479a5191d4 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -2,6 +2,7 @@ #include "config.h" #include "gettext.h" #include "parse-options.h" +#include "path.h" #include "transport.h" #include "remote.h" #include "string-list.h" @@ -10,7 +11,7 @@ #include "rebase.h" #include "refs.h" #include "refspec.h" -#include "object-store.h" +#include "object-store-ll.h" #include "strvec.h" #include "commit-reach.h" #include "progress.h" @@ -268,6 +269,7 @@ static const char *abbrev_ref(const char *name, const char *prefix) #define abbrev_branch(name) abbrev_ref((name), "refs/heads/") static int config_read_branches(const char *key, const char *value, + const struct config_context *ctx UNUSED, void *data UNUSED) { const char *orig_key = key; @@ -645,17 +647,19 @@ struct push_default_info }; static int config_read_push_default(const char *key, const char *value, - void *cb) + const struct config_context *ctx, void *cb) { + const struct key_value_info *kvi = ctx->kvi; + struct push_default_info* info = cb; if (strcmp(key, "remote.pushdefault") || !value || strcmp(value, info->old_name)) return 0; - info->scope = current_config_scope(); + info->scope = kvi->scope; strbuf_reset(&info->origin); - strbuf_addstr(&info->origin, current_config_name()); - info->linenr = current_config_line(); + strbuf_addstr(&info->origin, config_origin_type_name(kvi->origin_type)); + info->linenr = kvi->linenr; return 0; } @@ -1494,7 +1498,9 @@ static int prune(int argc, const char **argv, const char *prefix) return result; } -static int get_remote_default(const char *key, const char *value UNUSED, void *priv) +static int get_remote_default(const char *key, const char *value UNUSED, + const struct config_context *ctx UNUSED, + void *priv) { if (strcmp(key, "remotes.default") == 0) { int *found = priv; diff --git a/builtin/repack.c b/builtin/repack.c index 0541c3ce15..51698e3c68 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -6,6 +6,7 @@ #include "gettext.h" #include "hex.h" #include "parse-options.h" +#include "path.h" #include "run-command.h" #include "server-info.h" #include "sigchain.h" @@ -15,7 +16,7 @@ #include "midx.h" #include "packfile.h" #include "prune-packed.h" -#include "object-store.h" +#include "object-store-ll.h" #include "promisor-remote.h" #include "shallow.h" #include "pack.h" @@ -59,7 +60,8 @@ struct pack_objects_args { int local; }; -static int repack_config(const char *var, const char *value, void *cb) +static int repack_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { struct pack_objects_args *cruft_po_args = cb; if (!strcmp(var, "repack.usedeltabaseoffset")) { @@ -91,12 +93,12 @@ static int repack_config(const char *var, const char *value, void *cb) return git_config_string(&cruft_po_args->depth, var, value); if (!strcmp(var, "repack.cruftthreads")) return git_config_string(&cruft_po_args->threads, var, value); - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } /* - * Adds all packs hex strings to either fname_nonkept_list or - * fname_kept_list based on whether each pack has a corresponding + * Adds all packs hex strings (pack-$HASH) to either fname_nonkept_list + * or fname_kept_list based on whether each pack has a corresponding * .keep file or not. Packs without a .keep file are not to be kept * if we are going to pack everything into one file. */ @@ -107,6 +109,7 @@ static void collect_pack_filenames(struct string_list *fname_nonkept_list, DIR *dir; struct dirent *e; char *fname; + struct strbuf buf = STRBUF_INIT; if (!(dir = opendir(packdir))) return; @@ -115,11 +118,15 @@ static void collect_pack_filenames(struct string_list *fname_nonkept_list, size_t len; int i; - if (!strip_suffix(e->d_name, ".pack", &len)) + if (!strip_suffix(e->d_name, ".idx", &len)) continue; + strbuf_reset(&buf); + strbuf_add(&buf, e->d_name, len); + strbuf_addstr(&buf, ".pack"); + for (i = 0; i < extra_keep->nr; i++) - if (!fspathcmp(e->d_name, extra_keep->items[i].string)) + if (!fspathcmp(buf.buf, extra_keep->items[i].string)) break; fname = xmemdupz(e->d_name, len); @@ -136,6 +143,7 @@ static void collect_pack_filenames(struct string_list *fname_nonkept_list, } } closedir(dir); + strbuf_release(&buf); string_list_sort(fname_kept_list); } diff --git a/builtin/replace.c b/builtin/replace.c index 981f189443..9ceaa25233 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -8,22 +8,23 @@ * git-tag.sh and mktag.c by Linus Torvalds. */ -#include "cache.h" -#include "config.h" #include "builtin.h" +#include "config.h" #include "editor.h" #include "environment.h" #include "gettext.h" #include "hex.h" #include "refs.h" #include "parse-options.h" +#include "path.h" #include "run-command.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "replace-object.h" #include "repository.h" #include "tag.h" +#include "wildmatch.h" static const char * const git_replace_usage[] = { N_("git replace [-f] <object> <replacement>"), @@ -566,7 +567,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix) OPT_END() }; - read_replace_refs = 0; + disable_replace_refs(); git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0); diff --git a/builtin/rerere.c b/builtin/rerere.c index d4bd52797f..0458db9cad 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -1,5 +1,4 @@ #include "builtin.h" -#include "cache.h" #include "config.h" #include "dir.h" #include "gettext.h" diff --git a/builtin/reset.c b/builtin/reset.c index f99f32d580..7f18dc03b8 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -13,6 +13,7 @@ #include "config.h" #include "environment.h" #include "gettext.h" +#include "hash.h" #include "hex.h" #include "lockfile.h" #include "tag.h" @@ -26,9 +27,11 @@ #include "branch.h" #include "object-name.h" #include "parse-options.h" +#include "path.h" #include "unpack-trees.h" #include "cache-tree.h" #include "setup.h" +#include "sparse-index.h" #include "submodule.h" #include "submodule-config.h" #include "trace.h" @@ -312,12 +315,13 @@ static int reset_refs(const char *rev, const struct object_id *oid) return update_ref_status; } -static int git_reset_config(const char *var, const char *value, void *cb) +static int git_reset_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "submodule.recurse")) return git_default_submodule_config(var, value, cb); - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } int cmd_reset(int argc, const char **argv, const char *prefix) diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 6dc8be492a..ff715d6918 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -1,4 +1,4 @@ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "commit.h" #include "diff.h" @@ -12,10 +12,9 @@ #include "object.h" #include "object-name.h" #include "object-file.h" -#include "object-store.h" +#include "object-store-ll.h" #include "pack.h" #include "pack-bitmap.h" -#include "builtin.h" #include "log-tree.h" #include "graph.h" #include "bisect.h" diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 852e49e340..3e2ee44177 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -4,20 +4,22 @@ * Copyright (C) Linus Torvalds, 2005 */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "abspath.h" #include "alloc.h" #include "config.h" #include "commit.h" #include "environment.h" #include "gettext.h" +#include "hash.h" #include "hex.h" #include "refs.h" #include "quote.h" -#include "builtin.h" #include "object-name.h" #include "parse-options.h" +#include "path.h" #include "diff.h" +#include "read-cache-ll.h" #include "revision.h" #include "setup.h" #include "split-index.h" @@ -156,9 +158,12 @@ static void show_rev(int type, const struct object_id *oid, const char *name) */ break; case 1: /* happy */ - if (abbrev_ref) + if (abbrev_ref) { + char *old = full; full = shorten_unambiguous_ref(full, abbrev_ref_strict); + free(old); + } show_with_type(type, full); break; default: /* ambiguous */ diff --git a/builtin/revert.c b/builtin/revert.c index 0240ec8593..f6f07d9b53 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -5,6 +5,7 @@ #include "parse-options.h" #include "diff.h" #include "gettext.h" +#include "repository.h" #include "revision.h" #include "rerere.h" #include "dir.h" diff --git a/builtin/rm.c b/builtin/rm.c index b4589c824c..463eeabcea 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -16,9 +16,11 @@ #include "tree-walk.h" #include "object-name.h" #include "parse-options.h" +#include "read-cache.h" #include "repository.h" #include "string-list.h" #include "setup.h" +#include "sparse-index.h" #include "submodule.h" #include "pathspec.h" diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 4784143004..cd6d9e4112 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -131,7 +131,8 @@ static void print_helper_status(struct ref *ref) strbuf_release(&buf); } -static int send_pack_config(const char *k, const char *v, void *cb) +static int send_pack_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { if (!strcmp(k, "push.gpgsign")) { const char *value; @@ -151,7 +152,7 @@ static int send_pack_config(const char *k, const char *v, void *cb) } } } - return git_default_config(k, v, cb); + return git_default_config(k, v, ctx, cb); } int cmd_send_pack(int argc, const char **argv, const char *prefix) diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 46f4e0832a..1307ed2b88 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -1,11 +1,11 @@ #include "builtin.h" -#include "cache.h" #include "config.h" #include "commit.h" #include "diff.h" #include "environment.h" #include "gettext.h" #include "string-list.h" +#include "repository.h" #include "revision.h" #include "utf8.h" #include "mailmap.h" diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 7ef4a642c1..a86b3c7677 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -1,4 +1,4 @@ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "environment.h" #include "gettext.h" @@ -6,7 +6,6 @@ #include "hex.h" #include "pretty.h" #include "refs.h" -#include "builtin.h" #include "color.h" #include "strvec.h" #include "object-name.h" @@ -15,6 +14,7 @@ #include "dir.h" #include "commit-slab.h" #include "date.h" +#include "wildmatch.h" static const char* show_branch_usage[] = { N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n" @@ -559,7 +559,8 @@ static void append_one_rev(const char *av) die("bad sha1 reference %s", av); } -static int git_show_branch_config(const char *var, const char *value, void *cb) +static int git_show_branch_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "showbranch.default")) { if (!value) @@ -579,7 +580,10 @@ static int git_show_branch_config(const char *var, const char *value, void *cb) return 0; } - return git_color_default_config(var, value, cb); + if (git_color_config(var, value, cb) < 0) + return -1; + + return git_default_config(var, value, ctx, cb); } static int omit_in_dense(struct commit *commit, struct commit **rev, int n) diff --git a/builtin/show-index.c b/builtin/show-index.c index d839e55335..540dc3dad1 100644 --- a/builtin/show-index.c +++ b/builtin/show-index.c @@ -1,5 +1,4 @@ #include "builtin.h" -#include "cache.h" #include "gettext.h" #include "hash.h" #include "hex.h" diff --git a/builtin/show-ref.c b/builtin/show-ref.c index a2243b4219..5110814f79 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -1,11 +1,10 @@ #include "builtin.h" -#include "cache.h" #include "config.h" #include "gettext.h" #include "hex.h" #include "refs.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "object.h" #include "tag.h" #include "string-list.h" diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 40d420f06c..5c8ffb1f75 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -1,5 +1,4 @@ #include "builtin.h" -#include "cache.h" #include "config.h" #include "dir.h" #include "environment.h" diff --git a/builtin/stash.c b/builtin/stash.c index a7e17ffe38..fe64cde9ce 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -4,6 +4,7 @@ #include "config.h" #include "environment.h" #include "gettext.h" +#include "hash.h" #include "hex.h" #include "object-name.h" #include "parse-options.h" @@ -17,9 +18,12 @@ #include "run-command.h" #include "dir.h" #include "entry.h" +#include "preload-index.h" +#include "read-cache.h" #include "rerere.h" #include "revision.h" #include "setup.h" +#include "sparse-index.h" #include "log-tree.h" #include "diffcore.h" #include "exec-cmd.h" @@ -837,7 +841,8 @@ static int show_stat = 1; static int show_patch; static int show_include_untracked; -static int git_stash_config(const char *var, const char *value, void *cb) +static int git_stash_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "stash.showstat")) { show_stat = git_config_bool(var, value); @@ -851,7 +856,7 @@ static int git_stash_config(const char *var, const char *value, void *cb) show_include_untracked = git_config_bool(var, value); return 0; } - return git_diff_basic_config(var, value, cb); + return git_diff_basic_config(var, value, ctx, cb); } static void diff_include_untracked(const struct stash_info *info, struct diff_options *diff_opt) diff --git a/builtin/stripspace.c b/builtin/stripspace.c index 9451eb69ff..7b700a9fb1 100644 --- a/builtin/stripspace.c +++ b/builtin/stripspace.c @@ -1,6 +1,6 @@ #include "builtin.h" -#include "cache.h" #include "config.h" +#include "environment.h" #include "gettext.h" #include "parse-options.h" #include "setup.h" @@ -13,7 +13,7 @@ static void comment_lines(struct strbuf *buf) size_t len; msg = strbuf_detach(buf, &len); - strbuf_add_commented_lines(buf, msg, len); + strbuf_add_commented_lines(buf, msg, len, comment_line_char); free(msg); } @@ -58,7 +58,8 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix) die_errno("could not read the input"); if (mode == STRIP_DEFAULT || mode == STRIP_COMMENTS) - strbuf_stripspace(&buf, mode == STRIP_COMMENTS); + strbuf_stripspace(&buf, + mode == STRIP_COMMENTS ? comment_line_char : '\0'); else comment_lines(&buf); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 6bf8d666ce..42706150cf 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -6,13 +6,16 @@ #include "gettext.h" #include "hex.h" #include "repository.h" -#include "cache.h" #include "config.h" #include "parse-options.h" #include "quote.h" +#include "path.h" #include "pathspec.h" +#include "preload-index.h" #include "dir.h" +#include "read-cache.h" #include "setup.h" +#include "sparse-index.h" #include "submodule.h" #include "submodule-config.h" #include "string-list.h" @@ -26,7 +29,7 @@ #include "diff.h" #include "object-file.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "advice.h" #include "branch.h" #include "list-objects-filter-options.h" @@ -2024,14 +2027,17 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, strbuf_reset(&sb); strbuf_addf(&sb, "submodule.%s.url", sub->name); if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) { - if (starts_with_dot_slash(sub->url) || - starts_with_dot_dot_slash(sub->url)) { + if (sub->url && (starts_with_dot_slash(sub->url) || + starts_with_dot_dot_slash(sub->url))) { url = resolve_relative_url(sub->url, NULL, 0); need_free_url = 1; } else url = sub->url; } + if (!url) + die(_("cannot clone submodule '%s' without a URL"), sub->name); + strbuf_reset(&sb); strbuf_addf(&sb, "%s/.git", ce->name); needs_cloning = !file_exists(sb.buf); @@ -2189,12 +2195,13 @@ static int update_clone_task_finished(int result, } static int git_update_clone_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { int *max_jobs = cb; if (!strcmp(var, "submodule.fetchjobs")) - *max_jobs = parse_submodule_fetchjobs(var, value); + *max_jobs = parse_submodule_fetchjobs(var, value, ctx->kvi); return 0; } diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c index 10198a74fa..a61fa3c0f8 100644 --- a/builtin/symbolic-ref.c +++ b/builtin/symbolic-ref.c @@ -1,6 +1,5 @@ #include "builtin.h" #include "config.h" -#include "cache.h" #include "gettext.h" #include "refs.h" #include "parse-options.h" diff --git a/builtin/tag.c b/builtin/tag.c index 1850a6a6fd..7d34af416c 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -6,17 +6,17 @@ * Based on git-tag.sh and mktag.c by Linus Torvalds. */ -#include "cache.h" +#include "builtin.h" #include "advice.h" #include "config.h" -#include "builtin.h" #include "editor.h" #include "environment.h" #include "gettext.h" #include "hex.h" #include "refs.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" +#include "path.h" #include "tag.h" #include "run-command.h" #include "parse-options.h" @@ -188,7 +188,8 @@ static const char tag_template_nocleanup[] = "Lines starting with '%c' will be kept; you may remove them" " yourself if you want to.\n"); -static int git_tag_config(const char *var, const char *value, void *cb) +static int git_tag_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "tag.gpgsign")) { config_sign_tag = git_config_bool(var, value); @@ -209,7 +210,11 @@ static int git_tag_config(const char *var, const char *value, void *cb) if (starts_with(var, "column.")) return git_column_config(var, value, "tag", &colopts); - return git_color_default_config(var, value, cb); + + if (git_color_config(var, value, cb) < 0) + return -1; + + return git_default_config(var, value, ctx, cb); } static void write_tag_body(int fd, const struct object_id *oid) @@ -271,11 +276,10 @@ static const char message_advice_nested_tag[] = static void create_tag(const struct object_id *object, const char *object_ref, const char *tag, struct strbuf *buf, struct create_tag_options *opt, - struct object_id *prev, struct object_id *result) + struct object_id *prev, struct object_id *result, char *path) { enum object_type type; struct strbuf header = STRBUF_INIT; - char *path = NULL; type = oid_object_info(the_repository, object, NULL); if (type <= OBJ_NONE) @@ -299,7 +303,6 @@ static void create_tag(const struct object_id *object, const char *object_ref, int fd; /* write the template message before editing: */ - path = git_pathdup("TAG_EDITMSG"); fd = xopen(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (opt->message_given) { @@ -311,9 +314,11 @@ static void create_tag(const struct object_id *object, const char *object_ref, struct strbuf buf = STRBUF_INIT; strbuf_addch(&buf, '\n'); if (opt->cleanup_mode == CLEANUP_ALL) - strbuf_commented_addf(&buf, _(tag_template), tag, comment_line_char); + strbuf_commented_addf(&buf, comment_line_char, + _(tag_template), tag, comment_line_char); else - strbuf_commented_addf(&buf, _(tag_template_nocleanup), tag, comment_line_char); + strbuf_commented_addf(&buf, comment_line_char, + _(tag_template_nocleanup), tag, comment_line_char); write_or_die(fd, buf.buf, buf.len); strbuf_release(&buf); } @@ -327,7 +332,8 @@ static void create_tag(const struct object_id *object, const char *object_ref, } if (opt->cleanup_mode != CLEANUP_NONE) - strbuf_stripspace(buf, opt->cleanup_mode == CLEANUP_ALL); + strbuf_stripspace(buf, + opt->cleanup_mode == CLEANUP_ALL ? comment_line_char : '\0'); if (!opt->message_given && !buf->len) die(_("no tag message?")); @@ -341,10 +347,6 @@ static void create_tag(const struct object_id *object, const char *object_ref, path); exit(128); } - if (path) { - unlink_or_warn(path); - free(path); - } } static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb) @@ -495,6 +497,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) }; int ret = 0; const char *only_in_list = NULL; + char *path = NULL; setup_ref_filter_porcelain_msg(); @@ -629,7 +632,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix) if (create_tag_object) { if (force_sign_annotate && !annotate) opt.sign = 1; - create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object); + path = git_pathdup("TAG_EDITMSG"); + create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object, + path); } transaction = ref_transaction_begin(&err); @@ -637,8 +642,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix) ref_transaction_update(transaction, ref.buf, &object, &prev, create_reflog ? REF_FORCE_CREATE_REFLOG : 0, reflog_msg.buf, &err) || - ref_transaction_commit(transaction, &err)) + ref_transaction_commit(transaction, &err)) { + if (path) + fprintf(stderr, + _("The tag message has been left in %s\n"), + path); die("%s", err.buf); + } + if (path) { + unlink_or_warn(path); + free(path); + } ref_transaction_free(transaction); if (force && !is_null_oid(&prev) && !oideq(&prev, &object)) printf(_("Updated tag '%s' (was %s)\n"), tag, diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c index b35a4b9dfe..6842a6c499 100644 --- a/builtin/unpack-file.c +++ b/builtin/unpack-file.c @@ -2,7 +2,7 @@ #include "config.h" #include "hex.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "wrapper.h" static char *create_temp_file(struct object_id *oid) diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 2c52c3a741..1979532a9d 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -1,12 +1,11 @@ #include "builtin.h" -#include "cache.h" #include "bulk-checkin.h" #include "config.h" #include "environment.h" #include "gettext.h" #include "git-zlib.h" #include "hex.h" -#include "object-store.h" +#include "object-store-ll.h" #include "object.h" #include "delta.h" #include "pack.h" @@ -609,7 +608,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED) int i; struct object_id oid; - read_replace_refs = 0; + disable_replace_refs(); git_config(git_default_config, NULL); diff --git a/builtin/update-index.c b/builtin/update-index.c index 5fab9ad2ec..aee3cb8cbd 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -4,7 +4,7 @@ * Copyright (C) Linus Torvalds, 2005 */ #define USE_THE_INDEX_VARIABLE -#include "cache.h" +#include "builtin.h" #include "bulk-checkin.h" #include "config.h" #include "environment.h" @@ -15,15 +15,16 @@ #include "quote.h" #include "cache-tree.h" #include "tree-walk.h" -#include "builtin.h" #include "object-file.h" #include "refs.h" #include "resolve-undo.h" #include "parse-options.h" #include "pathspec.h" #include "dir.h" +#include "read-cache.h" #include "repository.h" #include "setup.h" +#include "sparse-index.h" #include "split-index.h" #include "symlinks.h" #include "fsmonitor.h" diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 0c59b1c9ef..242102273e 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -1,9 +1,8 @@ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "gettext.h" #include "hash.h" #include "refs.h" -#include "builtin.h" #include "object-name.h" #include "parse-options.h" #include "quote.h" diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c index 19dce3c065..1dc3971ede 100644 --- a/builtin/update-server-info.c +++ b/builtin/update-server-info.c @@ -1,6 +1,5 @@ -#include "cache.h" -#include "config.h" #include "builtin.h" +#include "config.h" #include "gettext.h" #include "parse-options.h" #include "server-info.h" diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c index 44ad400e18..1b09e5e1aa 100644 --- a/builtin/upload-archive.c +++ b/builtin/upload-archive.c @@ -1,9 +1,9 @@ /* * Copyright (c) 2006 Franck Bui-Huu */ -#include "cache.h" #include "builtin.h" #include "archive.h" +#include "path.h" #include "pkt-line.h" #include "sideband.h" #include "repository.h" diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c index beb9dd0861..9b021ef026 100644 --- a/builtin/upload-pack.c +++ b/builtin/upload-pack.c @@ -1,9 +1,9 @@ -#include "cache.h" #include "builtin.h" #include "exec-cmd.h" #include "gettext.h" #include "pkt-line.h" #include "parse-options.h" +#include "path.h" #include "protocol.h" #include "replace-object.h" #include "upload-pack.h" @@ -36,7 +36,7 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix) }; packet_trace_identity("upload-pack"); - read_replace_refs = 0; + disable_replace_refs(); argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0); diff --git a/builtin/var.c b/builtin/var.c index 2149998980..74161bdf1c 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -4,60 +4,188 @@ * Copyright (C) Eric Biederman, 2005 */ #include "builtin.h" +#include "attr.h" #include "config.h" #include "editor.h" #include "ident.h" #include "pager.h" #include "refs.h" +#include "path.h" +#include "strbuf.h" static const char var_usage[] = "git var (-l | <variable>)"; -static const char *editor(int flag) +static char *committer(int ident_flag) { - return git_editor(); + return xstrdup_or_null(git_committer_info(ident_flag)); } -static const char *sequence_editor(int flag) +static char *author(int ident_flag) { - return git_sequence_editor(); + return xstrdup_or_null(git_author_info(ident_flag)); } -static const char *pager(int flag) +static char *editor(int ident_flag UNUSED) +{ + return xstrdup_or_null(git_editor()); +} + +static char *sequence_editor(int ident_flag UNUSED) +{ + return xstrdup_or_null(git_sequence_editor()); +} + +static char *pager(int ident_flag UNUSED) { const char *pgm = git_pager(1); if (!pgm) pgm = "cat"; - return pgm; + return xstrdup(pgm); +} + +static char *default_branch(int ident_flag UNUSED) +{ + return xstrdup_or_null(git_default_branch_name(1)); +} + +static char *shell_path(int ident_flag UNUSED) +{ + return xstrdup(SHELL_PATH); } -static const char *default_branch(int flag) +static char *git_attr_val_system(int ident_flag UNUSED) { - return git_default_branch_name(1); + if (git_attr_system_is_enabled()) { + char *file = xstrdup(git_attr_system_file()); + normalize_path_copy(file, file); + return file; + } + return NULL; +} + +static char *git_attr_val_global(int ident_flag UNUSED) +{ + char *file = xstrdup(git_attr_global_file()); + if (file) { + normalize_path_copy(file, file); + return file; + } + return NULL; +} + +static char *git_config_val_system(int ident_flag UNUSED) +{ + if (git_config_system()) { + char *file = git_system_config(); + normalize_path_copy(file, file); + return file; + } + return NULL; +} + +static char *git_config_val_global(int ident_flag UNUSED) +{ + struct strbuf buf = STRBUF_INIT; + char *user, *xdg; + size_t unused; + + git_global_config(&user, &xdg); + if (xdg && *xdg) { + normalize_path_copy(xdg, xdg); + strbuf_addf(&buf, "%s\n", xdg); + } + if (user && *user) { + normalize_path_copy(user, user); + strbuf_addf(&buf, "%s\n", user); + } + free(xdg); + free(user); + strbuf_trim_trailing_newline(&buf); + if (buf.len == 0) { + strbuf_release(&buf); + return NULL; + } + return strbuf_detach(&buf, &unused); } struct git_var { const char *name; - const char *(*read)(int); + char *(*read)(int); + int multivalued; }; static struct git_var git_vars[] = { - { "GIT_COMMITTER_IDENT", git_committer_info }, - { "GIT_AUTHOR_IDENT", git_author_info }, - { "GIT_EDITOR", editor }, - { "GIT_SEQUENCE_EDITOR", sequence_editor }, - { "GIT_PAGER", pager }, - { "GIT_DEFAULT_BRANCH", default_branch }, - { "", NULL }, + { + .name = "GIT_COMMITTER_IDENT", + .read = committer, + }, + { + .name = "GIT_AUTHOR_IDENT", + .read = author, + }, + { + .name = "GIT_EDITOR", + .read = editor, + }, + { + .name = "GIT_SEQUENCE_EDITOR", + .read = sequence_editor, + }, + { + .name = "GIT_PAGER", + .read = pager, + }, + { + .name = "GIT_DEFAULT_BRANCH", + .read = default_branch, + }, + { + .name = "GIT_SHELL_PATH", + .read = shell_path, + }, + { + .name = "GIT_ATTR_SYSTEM", + .read = git_attr_val_system, + }, + { + .name = "GIT_ATTR_GLOBAL", + .read = git_attr_val_global, + }, + { + .name = "GIT_CONFIG_SYSTEM", + .read = git_config_val_system, + }, + { + .name = "GIT_CONFIG_GLOBAL", + .read = git_config_val_global, + .multivalued = 1, + }, + { + .name = "", + .read = NULL, + }, }; static void list_vars(void) { struct git_var *ptr; - const char *val; + char *val; for (ptr = git_vars; ptr->read; ptr++) - if ((val = ptr->read(0))) - printf("%s=%s\n", ptr->name, val); + if ((val = ptr->read(0))) { + if (ptr->multivalued && *val) { + struct string_list list = STRING_LIST_INIT_DUP; + int i; + + string_list_split(&list, val, '\n', -1); + for (i = 0; i < list.nr; i++) + printf("%s=%s\n", ptr->name, list.items[i].string); + string_list_clear(&list, 0); + } else { + printf("%s=%s\n", ptr->name, val); + } + free(val); + } } static const struct git_var *get_git_var(const char *var) @@ -71,19 +199,20 @@ static const struct git_var *get_git_var(const char *var) return NULL; } -static int show_config(const char *var, const char *value, void *cb) +static int show_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (value) printf("%s=%s\n", var, value); else printf("%s\n", var); - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } int cmd_var(int argc, const char **argv, const char *prefix UNUSED) { const struct git_var *git_var; - const char *val; + char *val; if (argc != 2) usage(var_usage); @@ -104,6 +233,7 @@ int cmd_var(int argc, const char **argv, const char *prefix UNUSED) return 1; printf("%s\n", val); + free(val); return 0; } diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 5d99b82a64..9680b58701 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -5,12 +5,11 @@ * * Based on git-verify-tag */ -#include "cache.h" -#include "config.h" #include "builtin.h" +#include "config.h" #include "gettext.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "repository.h" #include "commit.h" #include "run-command.h" diff --git a/builtin/verify-pack.c b/builtin/verify-pack.c index 190fd69540..011dddd2dc 100644 --- a/builtin/verify-pack.c +++ b/builtin/verify-pack.c @@ -1,9 +1,9 @@ #include "builtin.h" -#include "cache.h" #include "config.h" #include "gettext.h" #include "run-command.h" #include "parse-options.h" +#include "strbuf.h" #define VERIFY_PACK_VERBOSE 01 #define VERIFY_PACK_STAT_ONLY 02 diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index c6019a0ad8..d8753270eb 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -5,9 +5,8 @@ * * Based on git-verify-tag.sh */ -#include "cache.h" -#include "config.h" #include "builtin.h" +#include "config.h" #include "gettext.h" #include "tag.h" #include "run-command.h" diff --git a/builtin/worktree.c b/builtin/worktree.c index f3180463be..7c114d56a3 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -1,9 +1,9 @@ -#include "cache.h" +#include "builtin.h" #include "abspath.h" +#include "advice.h" #include "checkout.h" #include "config.h" #include "copy.h" -#include "builtin.h" #include "dir.h" #include "environment.h" #include "gettext.h" @@ -11,9 +11,12 @@ #include "object-file.h" #include "object-name.h" #include "parse-options.h" +#include "path.h" #include "strvec.h" #include "branch.h" +#include "read-cache-ll.h" #include "refs.h" +#include "remote.h" #include "repository.h" #include "run-command.h" #include "hook.h" @@ -26,7 +29,8 @@ #define BUILTIN_WORKTREE_ADD_USAGE \ N_("git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n" \ - " [-b <new-branch>] <path> [<commit-ish>]") + " [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]") + #define BUILTIN_WORKTREE_LIST_USAGE \ N_("git worktree list [-v | --porcelain [-z]]") #define BUILTIN_WORKTREE_LOCK_USAGE \ @@ -42,6 +46,23 @@ #define BUILTIN_WORKTREE_UNLOCK_USAGE \ N_("git worktree unlock <worktree>") +#define WORKTREE_ADD_DWIM_ORPHAN_INFER_TEXT \ + _("No possible source branch, inferring '--orphan'") + +#define WORKTREE_ADD_ORPHAN_WITH_DASH_B_HINT_TEXT \ + _("If you meant to create a worktree containing a new orphan branch\n" \ + "(branch with no commits) for this repository, you can do so\n" \ + "using the --orphan flag:\n" \ + "\n" \ + " git worktree add --orphan -b %s %s\n") + +#define WORKTREE_ADD_ORPHAN_NO_DASH_B_HINT_TEXT \ + _("If you meant to create a worktree containing a new orphan branch\n" \ + "(branch with no commits) for this repository, you can do so\n" \ + "using the --orphan flag:\n" \ + "\n" \ + " git worktree add --orphan %s\n") + static const char * const git_worktree_usage[] = { BUILTIN_WORKTREE_ADD_USAGE, BUILTIN_WORKTREE_LIST_USAGE, @@ -99,6 +120,7 @@ struct add_opts { int detach; int quiet; int checkout; + int orphan; const char *keep_locked; }; @@ -107,14 +129,15 @@ static int verbose; static int guess_remote; static timestamp_t expire; -static int git_worktree_config(const char *var, const char *value, void *cb) +static int git_worktree_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (!strcmp(var, "worktree.guessremote")) { guess_remote = git_config_bool(var, value); return 0; } - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } static int delete_git_dir(const char *id) @@ -372,6 +395,22 @@ static int checkout_worktree(const struct add_opts *opts, return run_command(&cp); } +static int make_worktree_orphan(const char * ref, const struct add_opts *opts, + struct strvec *child_env) +{ + struct strbuf symref = STRBUF_INIT; + struct child_process cp = CHILD_PROCESS_INIT; + + validate_new_branchname(ref, &symref, 0); + strvec_pushl(&cp.args, "symbolic-ref", "HEAD", symref.buf, NULL); + if (opts->quiet) + strvec_push(&cp.args, "--quiet"); + strvec_pushv(&cp.env, child_env->v); + strbuf_release(&symref); + cp.git_cmd = 1; + return run_command(&cp); +} + static int add_worktree(const char *path, const char *refname, const struct add_opts *opts) { @@ -401,7 +440,7 @@ static int add_worktree(const char *path, const char *refname, die_if_checked_out(symref.buf, 0); } commit = lookup_commit_reference_by_name(refname); - if (!commit) + if (!commit && !opts->orphan) die(_("invalid reference: %s"), refname); name = worktree_basename(path, &len); @@ -483,17 +522,17 @@ static int add_worktree(const char *path, const char *refname, * values from the current worktree into the new one, that way the * new worktree behaves the same as this one. */ - if (repository_format_worktree_config) + if (the_repository->repository_format_worktree_config) copy_filtered_worktree_config(sb_repo.buf); strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf); strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path); cp.git_cmd = 1; - if (!is_branch) + if (!is_branch && commit) { strvec_pushl(&cp.args, "update-ref", "HEAD", oid_to_hex(&commit->object.oid), NULL); - else { + } else { strvec_pushl(&cp.args, "symbolic-ref", "HEAD", symref.buf, NULL); if (opts->quiet) @@ -505,6 +544,10 @@ static int add_worktree(const char *path, const char *refname, if (ret) goto done; + if (opts->orphan && + (ret = make_worktree_orphan(refname, opts, &child_env))) + goto done; + if (opts->checkout && (ret = checkout_worktree(opts, &child_env))) goto done; @@ -524,7 +567,7 @@ done: * Hook failure does not warrant worktree deletion, so run hook after * is_junk is cleared, but do return appropriate code when hook fails. */ - if (!ret && opts->checkout) { + if (!ret && opts->checkout && !opts->orphan) { struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; strvec_pushl(&opt.env, "GIT_DIR", "GIT_WORK_TREE", NULL); @@ -572,7 +615,7 @@ static void print_preparing_worktree_line(int detach, else { struct commit *commit = lookup_commit_reference_by_name(branch); if (!commit) - die(_("invalid reference: %s"), branch); + BUG(_("unreachable: invalid reference: %s"), branch); fprintf_ln(stderr, _("Preparing worktree (detached HEAD %s)"), repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV)); } @@ -580,6 +623,123 @@ static void print_preparing_worktree_line(int detach, } } +/** + * Callback to short circuit iteration over refs on the first reference + * corresponding to a valid oid. + * + * Returns 0 on failure and non-zero on success. + */ +static int first_valid_ref(const char *refname, + const struct object_id *oid, + int flags, + void *cb_data) +{ + return 1; +} + +/** + * Verifies HEAD and determines whether there exist any valid local references. + * + * - Checks whether HEAD points to a valid reference. + * + * - Checks whether any valid local branches exist. + * + * - Emits a warning if there exist any valid branches but HEAD does not point + * to a valid reference. + * + * Returns 1 if any of the previous checks are true, otherwise returns 0. + */ +static int can_use_local_refs(const struct add_opts *opts) +{ + if (head_ref(first_valid_ref, NULL)) { + return 1; + } else if (for_each_branch_ref(first_valid_ref, NULL)) { + if (!opts->quiet) { + struct strbuf path = STRBUF_INIT; + struct strbuf contents = STRBUF_INIT; + + strbuf_add_real_path(&path, get_worktree_git_dir(NULL)); + strbuf_addstr(&path, "/HEAD"); + strbuf_read_file(&contents, path.buf, 64); + strbuf_stripspace(&contents, 0); + strbuf_strip_suffix(&contents, "\n"); + + warning(_("HEAD points to an invalid (or orphaned) reference.\n" + "HEAD path: '%s'\n" + "HEAD contents: '%s'"), + path.buf, contents.buf); + strbuf_release(&path); + strbuf_release(&contents); + } + return 1; + } + return 0; +} + +/** + * Reports whether the necessary flags were set and whether the repository has + * remote references to attempt DWIM tracking of upstream branches. + * + * 1. Checks that `--guess-remote` was used or `worktree.guessRemote = true`. + * + * 2. Checks whether any valid remote branches exist. + * + * 3. Checks that there exists at least one remote and emits a warning/error + * if both checks 1. and 2. are false (can be bypassed with `--force`). + * + * Returns 1 if checks 1. and 2. are true, otherwise 0. + */ +static int can_use_remote_refs(const struct add_opts *opts) +{ + if (!guess_remote) { + return 0; + } else if (for_each_remote_ref(first_valid_ref, NULL)) { + return 1; + } else if (!opts->force && remote_get(NULL)) { + die(_("No local or remote refs exist despite at least one remote\n" + "present, stopping; use 'add -f' to overide or fetch a remote first")); + } + return 0; +} + +/** + * Determines whether `--orphan` should be inferred in the evaluation of + * `worktree add path/` or `worktree add -b branch path/` and emits an error + * if the supplied arguments would produce an illegal combination when the + * `--orphan` flag is included. + * + * `opts` and `opt_track` contain the other options & flags supplied to the + * command. + * + * remote determines whether to check `can_use_remote_refs()` or not. This + * is primarily to differentiate between the basic `add` DWIM and `add -b`. + * + * Returns 1 when inferring `--orphan`, 0 otherwise, and emits an error when + * `--orphan` is inferred but doing so produces an illegal combination of + * options and flags. Additionally produces an error when remote refs are + * checked and the repo is in a state that looks like the user added a remote + * but forgot to fetch (and did not override the warning with -f). + */ +static int dwim_orphan(const struct add_opts *opts, int opt_track, int remote) +{ + if (can_use_local_refs(opts)) { + return 0; + } else if (remote && can_use_remote_refs(opts)) { + return 0; + } else if (!opts->quiet) { + fprintf_ln(stderr, WORKTREE_ADD_DWIM_ORPHAN_INFER_TEXT); + } + + if (opt_track) { + die(_("'%s' and '%s' cannot be used together"), "--orphan", + "--track"); + } else if (!opts->checkout) { + die(_("'%s' and '%s' cannot be used together"), "--orphan", + "--no-checkout"); + } + return 1; +} + static const char *dwim_branch(const char *path, const char **new_branch) { int n; @@ -616,6 +776,7 @@ static int add(int ac, const char **av, const char *prefix) const char *opt_track = NULL; const char *lock_reason = NULL; int keep_locked = 0; + int used_new_branch_options; struct option options[] = { OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree"), @@ -624,6 +785,7 @@ static int add(int ac, const char **av, const char *prefix) N_("create a new branch")), OPT_STRING('B', NULL, &new_branch_force, N_("branch"), N_("create or reset a branch")), + OPT_BOOL(0, "orphan", &opts.orphan, N_("create unborn/orphaned branch")), OPT_BOOL('d', "detach", &opts.detach, N_("detach HEAD at named commit")), OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")), OPT_BOOL(0, "lock", &keep_locked, N_("keep the new working tree locked")), @@ -644,6 +806,17 @@ static int add(int ac, const char **av, const char *prefix) ac = parse_options(ac, av, prefix, options, git_worktree_add_usage, 0); if (!!opts.detach + !!new_branch + !!new_branch_force > 1) die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach"); + if (opts.detach && opts.orphan) + die(_("options '%s', and '%s' cannot be used together"), + "--orphan", "--detach"); + if (opts.orphan && opt_track) + die(_("'%s' and '%s' cannot be used together"), "--orphan", "--track"); + if (opts.orphan && !opts.checkout) + die(_("'%s' and '%s' cannot be used together"), "--orphan", + "--no-checkout"); + if (opts.orphan && ac == 2) + die(_("'%s' and '%s' cannot be used together"), "--orphan", + _("<commit-ish>")); if (lock_reason && !keep_locked) die(_("the option '%s' requires '%s'"), "--reason", "--lock"); if (lock_reason) @@ -656,6 +829,7 @@ static int add(int ac, const char **av, const char *prefix) path = prefix_filename(prefix, av[0]); branch = ac < 2 ? "HEAD" : av[1]; + used_new_branch_options = new_branch || new_branch_force; if (!strcmp(branch, "-")) branch = "@{-1}"; @@ -672,13 +846,28 @@ static int add(int ac, const char **av, const char *prefix) strbuf_release(&symref); } - if (ac < 2 && !new_branch && !opts.detach) { + if (opts.orphan && !new_branch) { + int n; + const char *s = worktree_basename(path, &n); + new_branch = xstrndup(s, n); + } else if (opts.orphan) { + // No-op + } else if (opts.detach) { + // Check HEAD + if (!strcmp(branch, "HEAD")) + can_use_local_refs(&opts); + } else if (ac < 2 && new_branch) { + // DWIM: Infer --orphan when repo has no refs. + opts.orphan = dwim_orphan(&opts, !!opt_track, 0); + } else if (ac < 2) { + // DWIM: Guess branch name from path. const char *s = dwim_branch(path, &new_branch); if (s) branch = s; - } - if (ac == 2 && !new_branch && !opts.detach) { + // DWIM: Infer --orphan when repo has no refs. + opts.orphan = (!s) && dwim_orphan(&opts, !!opt_track, 1); + } else if (ac == 2) { struct object_id oid; struct commit *commit; const char *remote; @@ -691,11 +880,31 @@ static int add(int ac, const char **av, const char *prefix) branch = remote; } } + + if (!strcmp(branch, "HEAD")) + can_use_local_refs(&opts); + + } + + if (!opts.orphan && !lookup_commit_reference_by_name(branch)) { + int attempt_hint = !opts.quiet && (ac < 2); + if (attempt_hint && used_new_branch_options) { + advise_if_enabled(ADVICE_WORKTREE_ADD_ORPHAN, + WORKTREE_ADD_ORPHAN_WITH_DASH_B_HINT_TEXT, + new_branch, path); + } else if (attempt_hint) { + advise_if_enabled(ADVICE_WORKTREE_ADD_ORPHAN, + WORKTREE_ADD_ORPHAN_NO_DASH_B_HINT_TEXT, path); + } + die(_("invalid reference: %s"), branch); } + if (!opts.quiet) print_preparing_worktree_line(opts.detach, branch, new_branch, !!new_branch_force); - if (new_branch) { + if (opts.orphan) { + branch = new_branch; + } else if (new_branch) { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; strvec_push(&cp.args, "branch"); @@ -1200,5 +1409,9 @@ int cmd_worktree(int ac, const char **av, const char *prefix) prefix = ""; ac = parse_options(ac, av, prefix, options, git_worktree_usage, 0); + + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + return fn(ac, av, prefix); } diff --git a/builtin/write-tree.c b/builtin/write-tree.c index 84b83318c9..66e83d0ecb 100644 --- a/builtin/write-tree.c +++ b/builtin/write-tree.c @@ -5,7 +5,6 @@ */ #define USE_THE_INDEX_VARIABLE #include "builtin.h" -#include "cache.h" #include "config.h" #include "environment.h" #include "gettext.h" |