diff options
Diffstat (limited to 'builtin')
42 files changed, 410 insertions, 474 deletions
diff --git a/builtin/add.c b/builtin/add.c index e888fb8c5f..c20548e4f5 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -32,7 +32,7 @@ struct update_callback_data { int add_errors; }; -static void chmod_pathspec(struct pathspec *pathspec, int force_mode) +static void chmod_pathspec(struct pathspec *pathspec, char flip) { int i; @@ -42,8 +42,8 @@ static void chmod_pathspec(struct pathspec *pathspec, int force_mode) if (pathspec && !ce_path_match(ce, pathspec, NULL)) continue; - if (chmod_cache_entry(ce, force_mode) < 0) - fprintf(stderr, "cannot chmod '%s'", ce->name); + if (chmod_cache_entry(ce, flip) < 0) + fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name); } } @@ -116,6 +116,7 @@ int add_files_to_cache(const char *prefix, rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = update_callback; rev.diffopt.format_callback_data = &data; + rev.diffopt.flags |= DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG; rev.max_count = 0; /* do not compare unmerged paths with stage #2 */ run_diff_files(&rev, DIFF_RACY_IS_MODIFIED); return !!data.add_errors; diff --git a/builtin/am.c b/builtin/am.c index 40cc6d6fe8..c369dd1dce 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -31,6 +31,7 @@ #include "mailinfo.h" #include "apply.h" #include "string-list.h" +#include "packfile.h" /** * Returns 1 if the file is empty or does not exist, 0 otherwise. @@ -431,6 +432,14 @@ static void am_load(struct am_state *state) read_state_file(&sb, state, "utf8", 1); state->utf8 = !strcmp(sb.buf, "t"); + if (file_exists(am_path(state, "rerere-autoupdate"))) { + read_state_file(&sb, state, "rerere-autoupdate", 1); + state->allow_rerere_autoupdate = strcmp(sb.buf, "t") ? + RERERE_NOAUTOUPDATE : RERERE_AUTOUPDATE; + } else { + state->allow_rerere_autoupdate = 0; + } + read_state_file(&sb, state, "keep", 1); if (!strcmp(sb.buf, "t")) state->keep = KEEP_TRUE; @@ -1003,6 +1012,10 @@ static void am_setup(struct am_state *state, enum patch_format patch_format, write_state_bool(state, "sign", state->signoff); write_state_bool(state, "utf8", state->utf8); + if (state->allow_rerere_autoupdate) + write_state_bool(state, "rerere-autoupdate", + state->allow_rerere_autoupdate == RERERE_AUTOUPDATE); + switch (state->keep) { case KEEP_FALSE: str = "f"; @@ -1181,34 +1194,10 @@ static void NORETURN die_user_resolve(const struct am_state *state) */ static void am_append_signoff(struct am_state *state) { - char *cp; - struct strbuf mine = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len); - - /* our sign-off */ - strbuf_addf(&mine, "\n%s%s\n", - sign_off_header, - fmt_name(getenv("GIT_COMMITTER_NAME"), - getenv("GIT_COMMITTER_EMAIL"))); - - /* Does sb end with it already? */ - if (mine.len < sb.len && - !strcmp(mine.buf, sb.buf + sb.len - mine.len)) - goto exit; /* no need to duplicate */ - - /* Does it have any Signed-off-by: in the text */ - for (cp = sb.buf; - cp && *cp && (cp = strstr(cp, sign_off_header)) != NULL; - cp = strchr(cp, '\n')) { - if (sb.buf == cp || cp[-1] == '\n') - break; - } - - strbuf_addstr(&sb, mine.buf + !!cp); -exit: - strbuf_release(&mine); + append_signoff(&sb, 0, 0); state->msg = strbuf_detach(&sb, &state->msg_len); } diff --git a/builtin/blame.c b/builtin/blame.c index bda1a78726..e0daf17548 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -925,8 +925,7 @@ parse_done: sb.found_guilty_entry = &found_guilty_entry; sb.found_guilty_entry_data = π if (show_progress) - pi.progress = start_progress_delay(_("Blaming lines"), - sb.num_lines, 50, 1); + pi.progress = start_delayed_progress(_("Blaming lines"), sb.num_lines); assign_blame(&sb, opt); diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 62c8cf0ebf..4ccbfaac31 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -12,6 +12,7 @@ #include "streaming.h" #include "tree-walk.h" #include "sha1-array.h" +#include "packfile.h" struct batch_options { int enabled; diff --git a/builtin/checkout.c b/builtin/checkout.c index 2d75ac66c7..5c202b7af5 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -861,7 +861,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb) } if (starts_with(var, "submodule.")) - return submodule_config(var, value, NULL); + return git_default_submodule_config(var, value, NULL); return git_xmerge_config(var, value, NULL); } @@ -1182,7 +1182,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) opts.prefix = prefix; opts.show_progress = -1; - gitmodules_config(); git_config(git_checkout_config, &opts); opts.track = BRANCH_TRACK_UNSPECIFIED; diff --git a/builtin/clone.c b/builtin/clone.c index 08b5cc433c..8d11b570a1 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -25,6 +25,7 @@ #include "remote.h" #include "run-command.h" #include "connected.h" +#include "packfile.h" /* * Overall FIXMEs: @@ -768,6 +769,9 @@ static int checkout(int submodule_progress) if (submodule_progress) argv_array_push(&args, "--progress"); + if (option_verbosity < 0) + argv_array_push(&args, "--quiet"); + err = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); } diff --git a/builtin/commit.c b/builtin/commit.c index e7a2cb6285..b3b04f5dd3 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -195,7 +195,6 @@ static void determine_whence(struct wt_status *s) static void status_init_config(struct wt_status *s, config_fn_t fn) { wt_status_prepare(s); - gitmodules_config(); git_config(fn, s); determine_whence(s); init_diff_ui_defaults(); @@ -940,13 +939,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix, return 0; } - /* - * Re-read the index as pre-commit hook could have updated it, - * and write it out as a tree. We must do this before we invoke - * the editor and after we invoke run_status above. - */ - discard_cache(); + if (!no_verify && find_hook("pre-commit")) { + /* + * Re-read the index as pre-commit hook could have updated it, + * and write it out as a tree. We must do this before we invoke + * the editor and after we invoke run_status above. + */ + discard_cache(); + } read_cache_from(index_file); + if (update_main_cache_tree(0)) { error(_("Error building trees")); return 0; diff --git a/builtin/count-objects.c b/builtin/count-objects.c index 1d82e61f2a..33343818c8 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -10,6 +10,7 @@ #include "builtin.h" #include "parse-options.h" #include "quote.h" +#include "packfile.h" static unsigned long garbage; static off_t size_garbage; diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 17bf84d18f..e88493ffe5 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -26,7 +26,6 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ init_revisions(&rev, prefix); - gitmodules_config(); rev.abbrev = 0; precompose_argv(argc, argv); diff --git a/builtin/diff-index.c b/builtin/diff-index.c index 185e6f9b58..9d772f8f27 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -23,7 +23,6 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ init_revisions(&rev, prefix); - gitmodules_config(); rev.abbrev = 0; precompose_argv(argc, argv); diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 31d2cb4107..d66499909e 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -110,7 +110,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ init_revisions(opt, prefix); - gitmodules_config(); opt->abbrev = 0; opt->diff = 1; opt->disable_stdin = 1; diff --git a/builtin/diff.c b/builtin/diff.c index 7cde6abbcf..7e3ebcea38 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -315,8 +315,6 @@ int cmd_diff(int argc, const char **argv, const char *prefix) no_index = DIFF_NO_INDEX_IMPLICIT; } - if (!no_index) - gitmodules_config(); init_diff_ui_defaults(); git_config(git_diff_ui_config, NULL); precompose_argv(argc, argv); diff --git a/builtin/difftool.c b/builtin/difftool.c index 8864d846f8..b2d3ba7539 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -111,7 +111,7 @@ static int use_wt_file(const char *workdir, const char *name, int fd = open(buf.buf, O_RDONLY); if (fd >= 0 && - !index_fd(wt_oid.hash, fd, &st, OBJ_BLOB, name, 0)) { + !index_fd(&wt_oid, fd, &st, OBJ_BLOB, name, 0)) { if (is_null_oid(oid)) { oidcpy(oid, &wt_oid); use = 1; diff --git a/builtin/fetch.c b/builtin/fetch.c index c87e59f3b1..225c734924 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -17,6 +17,7 @@ #include "connected.h" #include "argv-array.h" #include "utf8.h" +#include "packfile.h" static const char * const builtin_fetch_usage[] = { N_("git fetch [<options>] [<repository> [<refspec>...]]"), @@ -39,7 +40,7 @@ static int prune = -1; /* unspecified */ static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative; static int progress = -1; static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen; -static int max_children = -1; +static int max_children = 1; static enum transport_family family; static const char *depth; static const char *deepen_since; @@ -68,9 +69,30 @@ static int git_fetch_config(const char *k, const char *v, void *cb) recurse_submodules = r; } + if (!strcmp(k, "submodule.fetchjobs")) { + max_children = parse_submodule_fetchjobs(k, v); + return 0; + } else if (!strcmp(k, "fetch.recursesubmodules")) { + recurse_submodules = parse_fetch_recurse_submodules_arg(k, v); + return 0; + } + return git_default_config(k, v, cb); } +static int gitmodules_fetch_config(const char *var, const char *value, void *cb) +{ + if (!strcmp(var, "submodule.fetchjobs")) { + max_children = parse_submodule_fetchjobs(var, value); + return 0; + } else if (!strcmp(var, "fetch.recursesubmodules")) { + recurse_submodules = parse_fetch_recurse_submodules_arg(var, value); + return 0; + } + + return 0; +} + static int parse_refmap_arg(const struct option *opt, const char *arg, int unset) { ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc); @@ -1311,6 +1333,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) for (i = 1; i < argc; i++) strbuf_addf(&default_rla, " %s", argv[i]); + config_from_gitmodules(gitmodules_fetch_config, NULL); git_config(git_fetch_config, NULL); argc = parse_options(argc, argv, prefix, @@ -1338,12 +1361,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (depth || deepen_since || deepen_not.nr) deepen = 1; - if (recurse_submodules != RECURSE_SUBMODULES_OFF) { - set_config_fetch_recurse_submodules(recurse_submodules_default); - gitmodules_config(); - git_config(submodule_config, NULL); - } - if (all) { if (argc == 1) die(_("fetch --all does not take a repository argument")); @@ -1383,6 +1400,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) result = fetch_populated_submodules(&options, submodule_prefix, recurse_submodules, + recurse_submodules_default, verbosity < 0, max_children); argv_array_clear(&options); diff --git a/builtin/fsck.c b/builtin/fsck.c index a92f448186..1e4c471b41 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -15,6 +15,7 @@ #include "progress.h" #include "streaming.h" #include "decorate.h" +#include "packfile.h" #define REACHABLE 0x0001 #define SEEN 0x0002 @@ -179,7 +180,7 @@ static int traverse_reachable(void) unsigned int nr = 0; int result = 0; if (show_progress) - progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2); + progress = start_delayed_progress(_("Checking connectivity"), 0); while (pending.nr) { struct object_array_entry *entry; struct object *obj; @@ -326,6 +327,8 @@ static void check_connectivity(void) static int fsck_obj(struct object *obj) { + int err; + if (obj->flags & SEEN) return 0; obj->flags |= SEEN; @@ -336,20 +339,13 @@ static int fsck_obj(struct object *obj) if (fsck_walk(obj, NULL, &fsck_obj_options)) objerror(obj, "broken links"); - if (fsck_object(obj, NULL, 0, &fsck_obj_options)) - return -1; - - if (obj->type == OBJ_TREE) { - struct tree *item = (struct tree *) obj; - - free_tree_buffer(item); - } + err = fsck_object(obj, NULL, 0, &fsck_obj_options); + if (err) + goto out; if (obj->type == OBJ_COMMIT) { struct commit *commit = (struct commit *) obj; - free_commit_buffer(commit); - if (!commit->parents && show_root) printf("root %s\n", describe_object(&commit->object)); } @@ -365,7 +361,12 @@ static int fsck_obj(struct object *obj) } } - return 0; +out: + if (obj->type == OBJ_TREE) + free_tree_buffer((struct tree *)obj); + if (obj->type == OBJ_COMMIT) + free_commit_buffer((struct commit *)obj); + return err; } static int fsck_obj_buffer(const struct object_id *oid, enum object_type type, diff --git a/builtin/gc.c b/builtin/gc.c index e6b84475ae..3c78fcb9b1 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -19,6 +19,7 @@ #include "sigchain.h" #include "argv-array.h" #include "commit.h" +#include "packfile.h" #define FAILED_RUN "failed to run %s" diff --git a/builtin/grep.c b/builtin/grep.c index 3cbee04dc4..19e23946ac 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -28,13 +28,7 @@ static char const * const grep_usage[] = { NULL }; -static const char *super_prefix; static int recurse_submodules; -static struct argv_array submodule_options = ARGV_ARRAY_INIT; -static const char *parent_basename; - -static int grep_submodule_launch(struct grep_opt *opt, - const struct grep_source *gs); #define GREP_NUM_THREADS_DEFAULT 8 static int num_threads; @@ -186,10 +180,7 @@ static void *run(void *arg) break; opt->output_priv = w; - if (w->source.type == GREP_SOURCE_SUBMODULE) - hit |= grep_submodule_launch(opt, &w->source); - else - hit |= grep_source(opt, &w->source); + hit |= grep_source(opt, &w->source); grep_source_clear_data(&w->source); work_done(w); } @@ -327,21 +318,13 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid, { struct strbuf pathbuf = STRBUF_INIT; - if (super_prefix) { - strbuf_add(&pathbuf, filename, tree_name_len); - strbuf_addstr(&pathbuf, super_prefix); - strbuf_addstr(&pathbuf, filename + tree_name_len); + if (opt->relative && opt->prefix_length) { + quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf); + strbuf_insert(&pathbuf, 0, filename, tree_name_len); } else { strbuf_addstr(&pathbuf, filename); } - if (opt->relative && opt->prefix_length) { - char *name = strbuf_detach(&pathbuf, NULL); - quote_path_relative(name + tree_name_len, opt->prefix, &pathbuf); - strbuf_insert(&pathbuf, 0, name, tree_name_len); - free(name); - } - #ifndef NO_PTHREADS if (num_threads) { add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid); @@ -366,15 +349,10 @@ static int grep_file(struct grep_opt *opt, const char *filename) { struct strbuf buf = STRBUF_INIT; - if (super_prefix) - strbuf_addstr(&buf, super_prefix); - strbuf_addstr(&buf, filename); - - if (opt->relative && opt->prefix_length) { - char *name = strbuf_detach(&buf, NULL); - quote_path_relative(name, opt->prefix, &buf); - free(name); - } + if (opt->relative && opt->prefix_length) + quote_path_relative(filename, opt->prefix, &buf); + else + strbuf_addstr(&buf, filename); #ifndef NO_PTHREADS if (num_threads) { @@ -421,284 +399,89 @@ static void run_pager(struct grep_opt *opt, const char *prefix) exit(status); } -static void compile_submodule_options(const struct grep_opt *opt, - const char **argv, - int cached, int untracked, - int opt_exclude, int use_index, - int pattern_type_arg) -{ - struct grep_pat *pattern; - - if (recurse_submodules) - argv_array_push(&submodule_options, "--recurse-submodules"); - - if (cached) - argv_array_push(&submodule_options, "--cached"); - if (!use_index) - argv_array_push(&submodule_options, "--no-index"); - if (untracked) - argv_array_push(&submodule_options, "--untracked"); - if (opt_exclude > 0) - argv_array_push(&submodule_options, "--exclude-standard"); - - if (opt->invert) - argv_array_push(&submodule_options, "-v"); - if (opt->ignore_case) - argv_array_push(&submodule_options, "-i"); - if (opt->word_regexp) - argv_array_push(&submodule_options, "-w"); - switch (opt->binary) { - case GREP_BINARY_NOMATCH: - argv_array_push(&submodule_options, "-I"); - break; - case GREP_BINARY_TEXT: - argv_array_push(&submodule_options, "-a"); - break; - default: - break; - } - if (opt->allow_textconv) - argv_array_push(&submodule_options, "--textconv"); - if (opt->max_depth != -1) - argv_array_pushf(&submodule_options, "--max-depth=%d", - opt->max_depth); - if (opt->linenum) - argv_array_push(&submodule_options, "-n"); - if (!opt->pathname) - argv_array_push(&submodule_options, "-h"); - if (!opt->relative) - argv_array_push(&submodule_options, "--full-name"); - if (opt->name_only) - argv_array_push(&submodule_options, "-l"); - if (opt->unmatch_name_only) - argv_array_push(&submodule_options, "-L"); - if (opt->null_following_name) - argv_array_push(&submodule_options, "-z"); - if (opt->count) - argv_array_push(&submodule_options, "-c"); - if (opt->file_break) - argv_array_push(&submodule_options, "--break"); - if (opt->heading) - argv_array_push(&submodule_options, "--heading"); - if (opt->pre_context) - argv_array_pushf(&submodule_options, "--before-context=%d", - opt->pre_context); - if (opt->post_context) - argv_array_pushf(&submodule_options, "--after-context=%d", - opt->post_context); - if (opt->funcname) - argv_array_push(&submodule_options, "-p"); - if (opt->funcbody) - argv_array_push(&submodule_options, "-W"); - if (opt->all_match) - argv_array_push(&submodule_options, "--all-match"); - if (opt->debug) - argv_array_push(&submodule_options, "--debug"); - if (opt->status_only) - argv_array_push(&submodule_options, "-q"); - - switch (pattern_type_arg) { - case GREP_PATTERN_TYPE_BRE: - argv_array_push(&submodule_options, "-G"); - break; - case GREP_PATTERN_TYPE_ERE: - argv_array_push(&submodule_options, "-E"); - break; - case GREP_PATTERN_TYPE_FIXED: - argv_array_push(&submodule_options, "-F"); - break; - case GREP_PATTERN_TYPE_PCRE: - argv_array_push(&submodule_options, "-P"); - break; - case GREP_PATTERN_TYPE_UNSPECIFIED: - break; - default: - die("BUG: Added a new grep pattern type without updating switch statement"); - } - - for (pattern = opt->pattern_list; pattern != NULL; - pattern = pattern->next) { - switch (pattern->token) { - case GREP_PATTERN: - argv_array_pushf(&submodule_options, "-e%s", - pattern->pattern); - break; - case GREP_AND: - case GREP_OPEN_PAREN: - case GREP_CLOSE_PAREN: - case GREP_NOT: - case GREP_OR: - argv_array_push(&submodule_options, pattern->pattern); - break; - /* BODY and HEAD are not used by git-grep */ - case GREP_PATTERN_BODY: - case GREP_PATTERN_HEAD: - break; - } - } - - /* - * Limit number of threads for child process to use. - * This is to prevent potential fork-bomb behavior of git-grep as each - * submodule process has its own thread pool. - */ - argv_array_pushf(&submodule_options, "--threads=%d", - DIV_ROUND_UP(num_threads, 2)); - - /* Add Pathspecs */ - argv_array_push(&submodule_options, "--"); - for (; *argv; argv++) - argv_array_push(&submodule_options, *argv); -} +static int grep_cache(struct grep_opt *opt, struct repository *repo, + const struct pathspec *pathspec, int cached); +static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, + struct tree_desc *tree, struct strbuf *base, int tn_len, + int check_attr, struct repository *repo); -/* - * Launch child process to grep contents of a submodule - */ -static int grep_submodule_launch(struct grep_opt *opt, - const struct grep_source *gs) +static int grep_submodule(struct grep_opt *opt, struct repository *superproject, + const struct pathspec *pathspec, + const struct object_id *oid, + const char *filename, const char *path) { - struct child_process cp = CHILD_PROCESS_INIT; - int status, i; - const char *end_of_base; - const char *name; - struct strbuf child_output = STRBUF_INIT; - - end_of_base = strchr(gs->name, ':'); - if (gs->identifier && end_of_base) - name = end_of_base + 1; - else - name = gs->name; + struct repository submodule; + int hit; - prepare_submodule_repo_env(&cp.env_array); - argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT); + if (!is_submodule_active(superproject, path)) + return 0; - if (opt->relative && opt->prefix_length) - argv_array_pushf(&cp.env_array, "%s=%s", - GIT_TOPLEVEL_PREFIX_ENVIRONMENT, - opt->prefix); + if (repo_submodule_init(&submodule, superproject, path)) + return 0; - /* Add super prefix */ - argv_array_pushf(&cp.args, "--super-prefix=%s%s/", - super_prefix ? super_prefix : "", - name); - argv_array_push(&cp.args, "grep"); + repo_read_gitmodules(&submodule); /* - * Add basename of parent project - * When performing grep on a tree object the filename is prefixed - * with the object's name: 'tree-name:filename'. In order to - * provide uniformity of output we want to pass the name of the - * parent project's object name to the submodule so the submodule can - * prefix its output with the parent's name and not its own OID. + * NEEDSWORK: This adds the submodule's object directory to the list of + * alternates for the single in-memory object store. This has some bad + * consequences for memory (processed objects will never be freed) and + * performance (this increases the number of pack files git has to pay + * attention to, to the sum of the number of pack files in all the + * repositories processed so far). This can be removed once the object + * store is no longer global and instead is a member of the repository + * object. */ - if (gs->identifier && end_of_base) - argv_array_pushf(&cp.args, "--parent-basename=%.*s", - (int) (end_of_base - gs->name), - gs->name); + add_to_alternates_memory(submodule.objectdir); - /* Add options */ - for (i = 0; i < submodule_options.argc; i++) { - /* - * If there is a tree identifier for the submodule, add the - * rev after adding the submodule options but before the - * pathspecs. To do this we listen for the '--' and insert the - * oid before pushing the '--' onto the child process argv - * array. - */ - if (gs->identifier && - !strcmp("--", submodule_options.argv[i])) { - argv_array_push(&cp.args, oid_to_hex(gs->identifier)); - } + if (oid) { + struct object *object; + struct tree_desc tree; + void *data; + unsigned long size; + struct strbuf base = STRBUF_INIT; - argv_array_push(&cp.args, submodule_options.argv[i]); - } + object = parse_object_or_die(oid, oid_to_hex(oid)); - cp.git_cmd = 1; - cp.dir = gs->path; + grep_read_lock(); + data = read_object_with_reference(object->oid.hash, tree_type, + &size, NULL); + grep_read_unlock(); - /* - * Capture output to output buffer and check the return code from the - * child process. A '0' indicates a hit, a '1' indicates no hit and - * anything else is an error. - */ - status = capture_command(&cp, &child_output, 0); - if (status && (status != 1)) { - /* flush the buffer */ - write_or_die(1, child_output.buf, child_output.len); - die("process for submodule '%s' failed with exit code: %d", - gs->name, status); - } + if (!data) + die(_("unable to read tree (%s)"), oid_to_hex(&object->oid)); - opt->output(opt, child_output.buf, child_output.len); - strbuf_release(&child_output); - /* invert the return code to make a hit equal to 1 */ - return !status; -} + strbuf_addstr(&base, filename); + strbuf_addch(&base, '/'); -/* - * Prep grep structures for a submodule grep - * oid: the oid of the submodule or NULL if using the working tree - * filename: name of the submodule including tree name of parent - * path: location of the submodule - */ -static int grep_submodule(struct grep_opt *opt, const struct object_id *oid, - const char *filename, const char *path) -{ - if (!is_submodule_active(the_repository, path)) - return 0; - if (!is_submodule_populated_gently(path, NULL)) { - /* - * If searching history, check for the presence of the - * submodule's gitdir before skipping the submodule. - */ - if (oid) { - const struct submodule *sub = - submodule_from_path(&null_oid, path); - if (sub) - path = git_path("modules/%s", sub->name); - - if (!(is_directory(path) && is_git_directory(path))) - return 0; - } else { - return 0; - } + init_tree_desc(&tree, data, size); + hit = grep_tree(opt, pathspec, &tree, &base, base.len, + object->type == OBJ_COMMIT, &submodule); + strbuf_release(&base); + free(data); + } else { + hit = grep_cache(opt, &submodule, pathspec, 1); } -#ifndef NO_PTHREADS - if (num_threads) { - add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, oid); - return 0; - } else -#endif - { - struct grep_source gs; - int hit; - - grep_source_init(&gs, GREP_SOURCE_SUBMODULE, - filename, path, oid); - hit = grep_submodule_launch(opt, &gs); - - grep_source_clear(&gs); - return hit; - } + repo_clear(&submodule); + return hit; } -static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, - int cached) +static int grep_cache(struct grep_opt *opt, struct repository *repo, + const struct pathspec *pathspec, int cached) { int hit = 0; int nr; struct strbuf name = STRBUF_INIT; int name_base_len = 0; - if (super_prefix) { - name_base_len = strlen(super_prefix); - strbuf_addstr(&name, super_prefix); + if (repo->submodule_prefix) { + name_base_len = strlen(repo->submodule_prefix); + strbuf_addstr(&name, repo->submodule_prefix); } - read_cache(); + repo_read_index(repo); - for (nr = 0; nr < active_nr; nr++) { - const struct cache_entry *ce = active_cache[nr]; + for (nr = 0; nr < repo->index->cache_nr; nr++) { + const struct cache_entry *ce = repo->index->cache[nr]; strbuf_setlen(&name, name_base_len); strbuf_addstr(&name, ce->name); @@ -715,14 +498,14 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, ce_skip_worktree(ce)) { if (ce_stage(ce) || ce_intent_to_add(ce)) continue; - hit |= grep_oid(opt, &ce->oid, ce->name, - 0, ce->name); + hit |= grep_oid(opt, &ce->oid, name.buf, + 0, name.buf); } else { - hit |= grep_file(opt, ce->name); + hit |= grep_file(opt, name.buf); } } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && submodule_path_match(pathspec, name.buf, NULL)) { - hit |= grep_submodule(opt, NULL, ce->name, ce->name); + hit |= grep_submodule(opt, repo, pathspec, NULL, ce->name, ce->name); } else { continue; } @@ -730,8 +513,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, if (ce_stage(ce)) { do { nr++; - } while (nr < active_nr && - !strcmp(ce->name, active_cache[nr]->name)); + } while (nr < repo->index->cache_nr && + !strcmp(ce->name, repo->index->cache[nr]->name)); nr--; /* compensate for loop control */ } if (hit && opt->status_only) @@ -744,7 +527,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, struct tree_desc *tree, struct strbuf *base, int tn_len, - int check_attr) + int check_attr, struct repository *repo) { int hit = 0; enum interesting match = entry_not_interesting; @@ -752,8 +535,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, int old_baselen = base->len; struct strbuf name = STRBUF_INIT; int name_base_len = 0; - if (super_prefix) { - strbuf_addstr(&name, super_prefix); + if (repo->submodule_prefix) { + strbuf_addstr(&name, repo->submodule_prefix); name_base_len = name.len; } @@ -791,11 +574,11 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, strbuf_addch(base, '/'); init_tree_desc(&sub, data, size); hit |= grep_tree(opt, pathspec, &sub, base, tn_len, - check_attr); + check_attr, repo); free(data); } else if (recurse_submodules && S_ISGITLINK(entry.mode)) { - hit |= grep_submodule(opt, entry.oid, base->buf, - base->buf + tn_len); + hit |= grep_submodule(opt, repo, pathspec, entry.oid, + base->buf, base->buf + tn_len); } strbuf_setlen(base, old_baselen); @@ -809,7 +592,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, } static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, - struct object *obj, const char *name, const char *path) + struct object *obj, const char *name, const char *path, + struct repository *repo) { if (obj->type == OBJ_BLOB) return grep_oid(opt, &obj->oid, name, 0, path); @@ -828,10 +612,6 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, if (!data) die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid)); - /* Use parent's name as base when recursing submodules */ - if (recurse_submodules && parent_basename) - name = parent_basename; - len = name ? strlen(name) : 0; strbuf_init(&base, PATH_MAX + len + 1); if (len) { @@ -840,7 +620,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, } init_tree_desc(&tree, data, size); hit = grep_tree(opt, pathspec, &tree, &base, base.len, - obj->type == OBJ_COMMIT); + obj->type == OBJ_COMMIT, repo); strbuf_release(&base); free(data); return hit; @@ -849,6 +629,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, } static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, + struct repository *repo, const struct object_array *list) { unsigned int i; @@ -864,7 +645,8 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, submodule_free(); gitmodules_config_oid(&real_obj->oid); } - if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path)) { + if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path, + repo)) { hit = 1; if (opt->status_only) break; @@ -1005,9 +787,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) N_("ignore files specified via '.gitignore'"), 1), OPT_BOOL(0, "recurse-submodules", &recurse_submodules, N_("recursively search in each submodule")), - OPT_STRING(0, "parent-basename", &parent_basename, - N_("basename"), - N_("prepend parent project's basename to output")), OPT_GROUP(""), OPT_BOOL('v', "invert-match", &opt.invert, N_("show non-matching lines")), @@ -1112,7 +891,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) init_grep_defaults(); git_config(grep_cmd_config, NULL); grep_init(&opt, prefix); - super_prefix = get_super_prefix(); /* * If there is no -- then the paths must exist in the working @@ -1270,13 +1048,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) } #endif - if (recurse_submodules) { - gitmodules_config(); - compile_submodule_options(&opt, argv + i, cached, untracked, - opt_exclude, use_index, - pattern_type_arg); - } - if (show_in_pager && (cached || list.nr)) die(_("--open-files-in-pager only works on the worktree")); @@ -1318,11 +1089,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix) if (!cached) setup_work_tree(); - hit = grep_cache(&opt, &pathspec, cached); + hit = grep_cache(&opt, the_repository, &pathspec, cached); } else { if (cached) die(_("both --cached and trees are given.")); - hit = grep_objects(&opt, &pathspec, &list); + + hit = grep_objects(&opt, &pathspec, the_repository, &list); } if (num_threads) diff --git a/builtin/hash-object.c b/builtin/hash-object.c index d04baf999a..c532ff9320 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -16,7 +16,7 @@ * needs to bypass the data conversion performed by, and the type * limitation imposed by, index_fd() and its callees. */ -static int hash_literally(unsigned char *sha1, int fd, const char *type, unsigned flags) +static int hash_literally(struct object_id *oid, int fd, const char *type, unsigned flags) { struct strbuf buf = STRBUF_INIT; int ret; @@ -24,7 +24,7 @@ static int hash_literally(unsigned char *sha1, int fd, const char *type, unsigne if (strbuf_read(&buf, fd, 4096) < 0) ret = -1; else - ret = hash_sha1_file_literally(buf.buf, buf.len, type, sha1, flags); + ret = hash_sha1_file_literally(buf.buf, buf.len, type, oid, flags); strbuf_release(&buf); return ret; } @@ -33,16 +33,16 @@ static void hash_fd(int fd, const char *type, const char *path, unsigned flags, int literally) { struct stat st; - unsigned char sha1[20]; + struct object_id oid; if (fstat(fd, &st) < 0 || (literally - ? hash_literally(sha1, fd, type, flags) - : index_fd(sha1, fd, &st, type_from_string(type), path, flags))) + ? hash_literally(&oid, fd, type, flags) + : index_fd(&oid, fd, &st, type_from_string(type), path, flags))) die((flags & HASH_WRITE_OBJECT) ? "Unable to add %s to database" : "Unable to hash %s", path); - printf("%s\n", sha1_to_hex(sha1)); + printf("%s\n", oid_to_hex(&oid)); maybe_flush_or_die(stdout, "hash to stdout"); } diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 26828c1d82..f2be145e12 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -12,6 +12,7 @@ #include "exec_cmd.h" #include "streaming.h" #include "thread-utils.h" +#include "packfile.h" static const char index_pack_usage[] = "git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])"; diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 175f14797b..b742539d4d 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -16,34 +16,119 @@ static const char * const git_interpret_trailers_usage[] = { NULL }; +static enum trailer_where where; +static enum trailer_if_exists if_exists; +static enum trailer_if_missing if_missing; + +static int option_parse_where(const struct option *opt, + const char *arg, int unset) +{ + return trailer_set_where(&where, arg); +} + +static int option_parse_if_exists(const struct option *opt, + const char *arg, int unset) +{ + return trailer_set_if_exists(&if_exists, arg); +} + +static int option_parse_if_missing(const struct option *opt, + const char *arg, int unset) +{ + return trailer_set_if_missing(&if_missing, arg); +} + +static void new_trailers_clear(struct list_head *trailers) +{ + struct list_head *pos, *tmp; + struct new_trailer_item *item; + + list_for_each_safe(pos, tmp, trailers) { + item = list_entry(pos, struct new_trailer_item, list); + list_del(pos); + free(item); + } +} + +static int option_parse_trailer(const struct option *opt, + const char *arg, int unset) +{ + struct list_head *trailers = opt->value; + struct new_trailer_item *item; + + if (unset) { + new_trailers_clear(trailers); + return 0; + } + + if (!arg) + return -1; + + item = xmalloc(sizeof(*item)); + item->text = arg; + item->where = where; + item->if_exists = if_exists; + item->if_missing = if_missing; + list_add_tail(&item->list, trailers); + return 0; +} + +static int parse_opt_parse(const struct option *opt, const char *arg, + int unset) +{ + struct process_trailer_options *v = opt->value; + v->only_trailers = 1; + v->only_input = 1; + v->unfold = 1; + return 0; +} + int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) { - int in_place = 0; - int trim_empty = 0; - struct string_list trailers = STRING_LIST_INIT_NODUP; + struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; + LIST_HEAD(trailers); struct option options[] = { - OPT_BOOL(0, "in-place", &in_place, N_("edit files in place")), - OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty trailers")), - OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"), - N_("trailer(s) to add")), + OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")), + OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")), + + OPT_CALLBACK(0, "where", NULL, N_("action"), + N_("where to place the new trailer"), option_parse_where), + OPT_CALLBACK(0, "if-exists", NULL, N_("action"), + N_("action if trailer already exists"), option_parse_if_exists), + OPT_CALLBACK(0, "if-missing", NULL, N_("action"), + N_("action if trailer is missing"), option_parse_if_missing), + + OPT_BOOL(0, "only-trailers", &opts.only_trailers, N_("output only the trailers")), + OPT_BOOL(0, "only-input", &opts.only_input, N_("do not apply config rules")), + OPT_BOOL(0, "unfold", &opts.unfold, N_("join whitespace-continued values")), + { OPTION_CALLBACK, 0, "parse", &opts, NULL, N_("set parsing options"), + PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse }, + OPT_CALLBACK(0, "trailer", &trailers, N_("trailer"), + N_("trailer(s) to add"), option_parse_trailer), OPT_END() }; argc = parse_options(argc, argv, prefix, options, git_interpret_trailers_usage, 0); + if (opts.only_input && !list_empty(&trailers)) + usage_msg_opt( + _("--trailer with --only-input does not make sense"), + git_interpret_trailers_usage, + options); + if (argc) { int i; for (i = 0; i < argc; i++) - process_trailers(argv[i], in_place, trim_empty, &trailers); + process_trailers(argv[i], &opts, &trailers); } else { - if (in_place) + if (opts.in_place) die(_("no input file given for in-place editing")); - process_trailers(NULL, in_place, trim_empty, &trailers); + process_trailers(NULL, &opts, &trailers); } - string_list_clear(&trailers, 0); + new_trailers_clear(&trailers); return 0; } diff --git a/builtin/log.c b/builtin/log.c index 725c7b8a1a..f8cccbc964 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -27,6 +27,7 @@ #include "version.h" #include "mailmap.h" #include "gpg-interface.h" +#include "progress.h" /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -58,9 +59,9 @@ static int auto_decoration_style(void) return (isatty(1) || pager_in_use()) ? DECORATE_SHORT_REFS : 0; } -static int parse_decoration_style(const char *var, const char *value) +static int parse_decoration_style(const char *value) { - switch (git_config_maybe_bool(var, value)) { + switch (git_parse_maybe_bool(value)) { case 1: return DECORATE_SHORT_REFS; case 0: @@ -82,7 +83,7 @@ static int decorate_callback(const struct option *opt, const char *arg, int unse if (unset) decoration_style = 0; else if (arg) - decoration_style = parse_decoration_style("command line", arg); + decoration_style = parse_decoration_style(arg); else decoration_style = DECORATE_SHORT_REFS; @@ -412,7 +413,7 @@ static int git_log_config(const char *var, const char *value, void *cb) if (!strcmp(var, "log.date")) return git_config_string(&default_date_mode, var, value); if (!strcmp(var, "log.decorate")) { - decoration_style = parse_decoration_style(var, value); + decoration_style = parse_decoration_style(value); if (decoration_style < 0) decoration_style = 0; /* maybe warn? */ return 0; @@ -824,7 +825,7 @@ static int git_format_config(const char *var, const char *value, void *cb) return 0; } if (!strcmp(var, "format.from")) { - int b = git_config_maybe_bool(var, value); + int b = git_parse_maybe_bool(value); free(from); if (b < 0) from = xstrdup(value); @@ -1422,6 +1423,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) char *branch_name = NULL; char *base_commit = NULL; struct base_tree_info bases; + int show_progress = 0; + struct progress *progress = NULL; const struct option builtin_format_patch_options[] = { { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, @@ -1493,6 +1496,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) OPT_FILENAME(0, "signature-file", &signature_file, N_("add a signature from a file")), OPT__QUIET(&quiet, N_("don't print the patch filenames")), + OPT_BOOL(0, "progress", &show_progress, + N_("show progress while generating patches")), OPT_END() }; @@ -1752,8 +1757,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) start_number--; } rev.add_signoff = do_signoff; + + if (show_progress) + progress = start_delayed_progress(_("Generating patches"), total); while (0 <= --nr) { int shown; + display_progress(progress, total - nr); commit = list[nr]; rev.nr = total - nr + (start_number - 1); /* Make the second and subsequent mails replies to the first */ @@ -1818,6 +1827,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!use_stdout) fclose(rev.diffopt.file); } + stop_progress(&progress); free(list); free(branch_name); string_list_clear(&extra_to, 0); diff --git a/builtin/ls-files.c b/builtin/ls-files.c index c6126eae55..e1339e6d17 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -19,6 +19,7 @@ #include "pathspec.h" #include "run-command.h" #include "submodule.h" +#include "submodule-config.h" static int abbrev; static int show_deleted; @@ -210,8 +211,6 @@ static void show_submodule(struct repository *superproject, if (repo_read_index(&submodule) < 0) die("index file corrupt"); - repo_read_gitmodules(&submodule); - show_files(&submodule, dir); repo_clear(&submodule); @@ -609,9 +608,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) if (require_work_tree && !is_inside_work_tree()) setup_work_tree(); - if (recurse_submodules) - repo_read_gitmodules(the_repository); - if (recurse_submodules && (show_stage || show_deleted || show_others || show_unmerged || show_killed || show_modified || show_resolve_undo || with_tree)) diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index f12da292cf..d01ddecf66 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -213,11 +213,11 @@ static void unresolved_directory(const struct traverse_info *info, newbase = traverse_path(info, p); -#define ENTRY_SHA1(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->oid->hash : NULL) - buf0 = fill_tree_descriptor(t+0, ENTRY_SHA1(n + 0)); - buf1 = fill_tree_descriptor(t+1, ENTRY_SHA1(n + 1)); - buf2 = fill_tree_descriptor(t+2, ENTRY_SHA1(n + 2)); -#undef ENTRY_SHA1 +#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->oid : NULL) + buf0 = fill_tree_descriptor(t + 0, ENTRY_OID(n + 0)); + buf1 = fill_tree_descriptor(t + 1, ENTRY_OID(n + 1)); + buf2 = fill_tree_descriptor(t + 2, ENTRY_OID(n + 2)); +#undef ENTRY_OID merge_trees(t, newbase); @@ -352,7 +352,7 @@ static void *get_tree_descriptor(struct tree_desc *desc, const char *rev) if (get_oid(rev, &oid)) die("unknown rev %s", rev); - buf = fill_tree_descriptor(desc, oid.hash); + buf = fill_tree_descriptor(desc, &oid); if (!buf) die("%s is not a tree", rev); return buf; diff --git a/builtin/merge.c b/builtin/merge.c index d5797b8fe7..7df3fe3927 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -32,6 +32,7 @@ #include "gpg-interface.h" #include "sequencer.h" #include "string-list.h" +#include "packfile.h" #define DEFAULT_TWOHEAD (1<<0) #define DEFAULT_OCTOPUS (1<<1) @@ -70,6 +71,7 @@ static int continue_current_merge; static int allow_unrelated_histories; static int show_progress = -1; static int default_to_upstream = 1; +static int signoff; static const char *sign_commit; static struct strategy all_strategy[] = { @@ -233,6 +235,7 @@ static struct option builtin_merge_options[] = { { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"), N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")), + OPT_BOOL(0, "signoff", &signoff, N_("add Signed-off-by:")), OPT_END() }; @@ -566,7 +569,7 @@ static int git_merge_config(const char *k, const char *v, void *cb) else if (!strcmp(k, "merge.renormalize")) option_renormalize = git_config_bool(k, v); else if (!strcmp(k, "merge.ff")) { - int boolval = git_config_maybe_bool(k, v); + int boolval = git_parse_maybe_bool(v); if (0 <= boolval) { fast_forward = boolval ? FF_ALLOW : FF_NO; } else if (v && !strcmp(v, "only")) { @@ -756,13 +759,19 @@ N_("Please enter a commit message to explain why this merge is necessary,\n" "Lines starting with '%c' will be ignored, and an empty message aborts\n" "the commit.\n"); +static void write_merge_heads(struct commit_list *); static void prepare_to_commit(struct commit_list *remoteheads) { struct strbuf msg = STRBUF_INIT; strbuf_addbuf(&msg, &merge_msg); strbuf_addch(&msg, '\n'); + if (squash) + BUG("the control must not reach here under --squash"); if (0 < option_edit) strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char); + if (signoff) + append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0); + write_merge_heads(remoteheads); write_file_buf(git_path_merge_msg(), msg.buf, msg.len); if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg", git_path_merge_msg(), "merge", NULL)) @@ -904,7 +913,7 @@ static int setup_with_upstream(const char ***argv) return i; } -static void write_merge_state(struct commit_list *remoteheads) +static void write_merge_heads(struct commit_list *remoteheads) { struct commit_list *j; struct strbuf buf = STRBUF_INIT; @@ -920,8 +929,6 @@ static void write_merge_state(struct commit_list *remoteheads) strbuf_addf(&buf, "%s\n", oid_to_hex(oid)); } write_file_buf(git_path_merge_head(), buf.buf, buf.len); - strbuf_addch(&merge_msg, '\n'); - write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len); strbuf_reset(&buf); if (fast_forward == FF_NO) @@ -929,6 +936,13 @@ static void write_merge_state(struct commit_list *remoteheads) write_file_buf(git_path_merge_mode(), buf.buf, buf.len); } +static void write_merge_state(struct commit_list *remoteheads) +{ + write_merge_heads(remoteheads); + strbuf_addch(&merge_msg, '\n'); + write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len); +} + static int default_edit_option(void) { static const char name[] = "GIT_MERGE_AUTOEDIT"; @@ -940,7 +954,7 @@ static int default_edit_option(void) return 0; if (e) { - int v = git_config_maybe_bool(name, e); + int v = git_parse_maybe_bool(e); if (v < 0) die(_("Bad value '%s' in environment '%s'"), e, name); return v; @@ -1117,8 +1131,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * current branch. */ branch = branch_to_free = resolve_refdup("HEAD", 0, head_oid.hash, NULL); - if (branch && starts_with(branch, "refs/heads/")) - branch += 11; + if (branch) + skip_prefix(branch, "refs/heads/", &branch); if (!branch || is_null_oid(&head_oid)) head_commit = NULL; else diff --git a/builtin/mv.c b/builtin/mv.c index dcf6736b5b..ffdd5f01a1 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -81,7 +81,7 @@ static void prepare_move_submodule(const char *src, int first, struct strbuf submodule_dotgit = STRBUF_INIT; if (!S_ISGITLINK(active_cache[first]->ce_mode)) die(_("Directory %s is in index and no submodule?"), src); - if (!is_staging_gitmodules_ok()) + if (!is_staging_gitmodules_ok(&the_index)) die(_("Please stage your changes to .gitmodules or stash them to proceed")); strbuf_addf(&submodule_dotgit, "%s/.git", src); *submodule_gitfile = read_gitfile(submodule_dotgit.buf); @@ -131,7 +131,6 @@ int cmd_mv(int argc, const char **argv, const char *prefix) struct stat st; struct string_list src_for_dst = STRING_LIST_INIT_NODUP; - gitmodules_config(); git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, builtin_mv_options, diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index c753e9237a..82ad6e0c81 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -25,6 +25,7 @@ #include "sha1-array.h" #include "argv-array.h" #include "mru.h" +#include "packfile.h" static const char *pack_usage[] = { N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"), diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index cb1df1c761..aaa8136322 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -7,6 +7,7 @@ */ #include "builtin.h" +#include "packfile.h" #define BLKSIZE 512 diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c index ac978ad401..419238171d 100644 --- a/builtin/prune-packed.c +++ b/builtin/prune-packed.c @@ -2,6 +2,7 @@ #include "cache.h" #include "progress.h" #include "parse-options.h" +#include "packfile.h" static const char * const prune_packed_usage[] = { N_("git prune-packed [-n | --dry-run] [-q | --quiet]"), @@ -37,8 +38,7 @@ static int prune_object(const struct object_id *oid, const char *path, void prune_packed_objects(int opts) { if (opts & PRUNE_PACKED_VERBOSE) - progress = start_progress_delay(_("Removing duplicate objects"), - 256, 95, 2); + progress = start_delayed_progress(_("Removing duplicate objects"), 256); for_each_loose_file_in_objdir(get_object_directory(), prune_object, NULL, prune_subdir, &opts); diff --git a/builtin/prune.c b/builtin/prune.c index c378690545..cddabf26a9 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -138,7 +138,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix) if (show_progress == -1) show_progress = isatty(2); if (show_progress) - progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2); + progress = start_delayed_progress(_("Checking connectivity"), 0); mark_reachable_objects(&revs, 1, expire, progress); stop_progress(&progress); diff --git a/builtin/pull.c b/builtin/pull.c index 9b86e519b1..7fe281414e 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -39,7 +39,7 @@ enum rebase_type { static enum rebase_type parse_config_rebase(const char *key, const char *value, int fatal) { - int v = git_config_maybe_bool("pull.rebase", value); + int v = git_parse_maybe_bool(value); if (!v) return REBASE_FALSE; @@ -274,7 +274,7 @@ static const char *config_get_ff(void) if (git_config_get_value("pull.ff", &value)) return NULL; - switch (git_config_maybe_bool("pull.ff", value)) { + switch (git_parse_maybe_bool(value)) { case 0: return "--no-ff"; case 1: diff --git a/builtin/push.c b/builtin/push.c index 03846e8379..2ac8104229 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -481,7 +481,7 @@ static int git_push_config(const char *k, const char *v, void *cb) } else if (!strcmp(k, "push.gpgsign")) { const char *value; if (!git_config_get_value("push.gpgsign", &value)) { - switch (git_config_maybe_bool("push.gpgsign", value)) { + switch (git_parse_maybe_bool(value)) { case 0: set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_NEVER); break; diff --git a/builtin/read-tree.c b/builtin/read-tree.c index d5f618d086..bf87a2710b 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -164,8 +164,6 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) argc = parse_options(argc, argv, unused_prefix, read_tree_options, read_tree_usage, 0); - load_submodule_cache(); - hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); prefix_set = opts.prefix ? 1 : 0; diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 14b6e09b42..52c63ebfdc 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -23,6 +23,7 @@ #include "fsck.h" #include "tmp-objdir.h" #include "oidset.h" +#include "packfile.h" static const char * const receive_pack_usage[] = { N_("git receive-pack <git-dir>"), diff --git a/builtin/remote.c b/builtin/remote.c index 6273c0c23c..a995ea86c1 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -301,7 +301,7 @@ static int config_read_branches(const char *key, const char *value, void *cb) } string_list_append(&info->merge, xstrdup(value)); } else { - int v = git_config_maybe_bool(orig_key, value); + int v = git_parse_maybe_bool(value); if (v >= 0) info->rebase = v; else if (!strcmp(value, "preserve")) diff --git a/builtin/replace.c b/builtin/replace.c index f4a85a165b..3e71a77152 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -269,7 +269,7 @@ static void import_object(struct object_id *oid, enum object_type type, if (fstat(fd, &st) < 0) die_errno("unable to fstat %s", filename); - if (index_fd(oid->hash, fd, &st, type, NULL, flags) < 0) + if (index_fd(oid, fd, &st, type, NULL, flags) < 0) die("unable to write object to database"); /* index_fd close()s fd for us */ } diff --git a/builtin/reset.c b/builtin/reset.c index 046403ed68..d72c7d1c96 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -75,13 +75,13 @@ static int reset_index(const struct object_id *oid, int reset_type, int quiet) struct object_id head_oid; if (get_oid("HEAD", &head_oid)) return error(_("You do not have a valid HEAD.")); - if (!fill_tree_descriptor(desc, head_oid.hash)) + if (!fill_tree_descriptor(desc, &head_oid)) return error(_("Failed to find tree of HEAD.")); nr++; opts.fn = twoway_merge; } - if (!fill_tree_descriptor(desc + nr - 1, oid->hash)) + if (!fill_tree_descriptor(desc + nr - 1, oid)) return error(_("Failed to find tree of %s."), oid_to_hex(oid)); if (unpack_trees(nr, desc, &opts)) return -1; @@ -156,6 +156,7 @@ static int read_from_tree(const struct pathspec *pathspec, opt.output_format = DIFF_FORMAT_CALLBACK; opt.format_callback = update_index_from_diff; opt.format_callback_data = &intent_to_add; + opt.flags |= DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG; if (do_diff_cache(tree_oid, &opt)) return 1; @@ -308,8 +309,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_DASHDASH); parse_args(&pathspec, argv, prefix, patch_mode, &rev); - load_submodule_cache(); - unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid); if (unborn) { /* reset on unborn branch: treat as reset to empty tree */ diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 95b4128250..c1c74d4a79 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -367,7 +367,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) revs.limited = 1; if (show_progress) - progress = start_progress_delay(show_progress, 0, 0, 2); + progress = start_delayed_progress(show_progress, 0); if (use_bitmap_index && !revs.prune) { if (revs.count && !revs.left_right && !revs.cherry_mark) { diff --git a/builtin/revert.c b/builtin/revert.c index 16028b9ea8..b9d927eb09 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -155,6 +155,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) "--strategy-option", opts->xopts ? 1 : 0, "-x", opts->record_origin, "--ff", opts->allow_ff, + "--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE, + "--no-rerere-autoupdate", opts->allow_rerere_auto == RERERE_NOAUTOUPDATE, NULL); } diff --git a/builtin/rm.c b/builtin/rm.c index 52826d1379..d91451fea1 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -255,7 +255,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix) struct pathspec pathspec; char *seen; - gitmodules_config(); git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, builtin_rm_options, @@ -286,7 +285,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix) list.entry[list.nr].name = xstrdup(ce->name); list.entry[list.nr].is_submodule = S_ISGITLINK(ce->ce_mode); if (list.entry[list.nr++].is_submodule && - !is_staging_gitmodules_ok()) + !is_staging_gitmodules_ok(&the_index)) die (_("Please stage your changes to .gitmodules or stash them to proceed")); } diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 633e0c3cdd..fc4f0bb5fb 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -105,7 +105,7 @@ static int send_pack_config(const char *k, const char *v, void *cb) if (!strcmp(k, "push.gpgsign")) { const char *value; if (!git_config_get_value("push.gpgsign", &value)) { - switch (git_config_maybe_bool("push.gpgsign", value)) { + switch (git_parse_maybe_bool(value)) { case 0: args.push_cert = SEND_PACK_PUSH_CERT_NEVER; break; diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 84562ec833..818fe74f0a 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -275,8 +275,6 @@ static void module_list_active(struct module_list *list) int i; struct module_list active_modules = MODULE_LIST_INIT; - gitmodules_config(); - for (i = 0; i < list->nr; i++) { const struct cache_entry *ce = list->entries[i]; @@ -337,9 +335,6 @@ static void init_submodule(const char *path, const char *prefix, int quiet) struct strbuf sb = STRBUF_INIT; char *upd = NULL, *url = NULL, *displaypath; - /* Only loads from .gitmodules, no overlay with .git/config */ - gitmodules_config(); - if (prefix && get_super_prefix()) die("BUG: cannot have prefix and superprefix"); else if (prefix) @@ -475,7 +470,6 @@ static int module_name(int argc, const char **argv, const char *prefix) if (argc != 2) usage(_("git submodule--helper name <path>")); - gitmodules_config(); sub = submodule_from_path(&null_oid, argv[1]); if (!sub) @@ -780,6 +774,10 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, struct strbuf *out) { const struct submodule *sub = NULL; + const char *url = NULL; + const char *update_string; + enum submodule_update_type update_type; + char *key; struct strbuf displaypath_sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; const char *displaypath = NULL; @@ -808,9 +806,17 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, goto cleanup; } + key = xstrfmt("submodule.%s.update", sub->name); + if (!repo_config_get_string_const(the_repository, key, &update_string)) { + update_type = parse_submodule_update_type(update_string); + } else { + update_type = sub->update_strategy.type; + } + free(key); + if (suc->update.type == SM_UPDATE_NONE || (suc->update.type == SM_UPDATE_UNSPECIFIED - && sub->update_strategy.type == SM_UPDATE_NONE)) { + && update_type == SM_UPDATE_NONE)) { strbuf_addf(out, _("Skipping submodule '%s'"), displaypath); strbuf_addch(out, '\n'); goto cleanup; @@ -823,6 +829,11 @@ 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_const(the_repository, sb.buf, &url)) + url = sub->url; + + strbuf_reset(&sb); strbuf_addf(&sb, "%s/.git", ce->name); needs_cloning = !file_exists(sb.buf); @@ -851,7 +862,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, argv_array_push(&child->args, "--depth=1"); argv_array_pushl(&child->args, "--path", sub->path, NULL); argv_array_pushl(&child->args, "--name", sub->name, NULL); - argv_array_pushl(&child->args, "--url", sub->url, NULL); + argv_array_pushl(&child->args, "--url", url, NULL); if (suc->references.nr) { struct string_list_item *item; for_each_string_list_item(item, &suc->references) @@ -960,10 +971,19 @@ static int update_clone_task_finished(int result, return 0; } +static int gitmodules_update_clone_config(const char *var, const char *value, + void *cb) +{ + int *max_jobs = cb; + if (!strcmp(var, "submodule.fetchjobs")) + *max_jobs = parse_submodule_fetchjobs(var, value); + return 0; +} + static int update_clone(int argc, const char **argv, const char *prefix) { const char *update = NULL; - int max_jobs = -1; + int max_jobs = 1; struct string_list_item *item; struct pathspec pathspec; struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT; @@ -1000,6 +1020,9 @@ static int update_clone(int argc, const char **argv, const char *prefix) }; suc.prefix = prefix; + config_from_gitmodules(gitmodules_update_clone_config, &max_jobs); + git_config(gitmodules_update_clone_config, &max_jobs); + argc = parse_options(argc, argv, prefix, module_update_clone_options, git_submodule_helper_usage, 0); @@ -1013,13 +1036,6 @@ static int update_clone(int argc, const char **argv, const char *prefix) if (pathspec.nr) suc.warn_if_uninitialized = 1; - /* Overlay the parsed .gitmodules file with .git/config */ - gitmodules_config(); - git_config(submodule_config, NULL); - - if (max_jobs < 0) - max_jobs = parallel_submodules(); - run_processes_parallel(max_jobs, update_clone_get_next_task, update_clone_start_failure, @@ -1057,17 +1073,22 @@ static int resolve_relative_path(int argc, const char **argv, const char *prefix static const char *remote_submodule_branch(const char *path) { const struct submodule *sub; - gitmodules_config(); - git_config(submodule_config, NULL); + const char *branch = NULL; + char *key; sub = submodule_from_path(&null_oid, path); if (!sub) return NULL; - if (!sub->branch) + key = xstrfmt("submodule.%s.branch", sub->name); + if (repo_config_get_string_const(the_repository, key, &branch)) + branch = sub->branch; + free(key); + + if (!branch) return "master"; - if (!strcmp(sub->branch, ".")) { + if (!strcmp(branch, ".")) { unsigned char sha1[20]; const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL); @@ -1085,7 +1106,7 @@ static const char *remote_submodule_branch(const char *path) return refname; } - return sub->branch; + return branch; } static int resolve_remote_submodule_branch(int argc, const char **argv, @@ -1108,9 +1129,28 @@ static int resolve_remote_submodule_branch(int argc, const char **argv, static int push_check(int argc, const char **argv, const char *prefix) { struct remote *remote; + const char *superproject_head; + char *head; + int detached_head = 0; + struct object_id head_oid; + + if (argc < 3) + die("submodule--helper push-check requires at least 2 arguments"); - if (argc < 2) - die("submodule--helper push-check requires at least 1 argument"); + /* + * superproject's resolved head ref. + * if HEAD then the superproject is in a detached head state, otherwise + * it will be the resolved head ref. + */ + superproject_head = argv[1]; + argv++; + argc--; + /* Get the submodule's head ref and determine if it is detached */ + head = resolve_refdup("HEAD", 0, head_oid.hash, NULL); + if (!head) + die(_("Failed to resolve HEAD as a valid ref.")); + if (!strcmp(head, "HEAD")) + detached_head = 1; /* * The remote must be configured. @@ -1133,18 +1173,30 @@ static int push_check(int argc, const char **argv, const char *prefix) if (rs->pattern || rs->matching) continue; - /* - * LHS must match a single ref - * NEEDSWORK: add logic to special case 'HEAD' once - * working with submodules in a detached head state - * ceases to be the norm. - */ - if (count_refspec_match(rs->src, local_refs, NULL) != 1) + /* LHS must match a single ref */ + switch (count_refspec_match(rs->src, local_refs, NULL)) { + case 1: + break; + case 0: + /* + * If LHS matches 'HEAD' then we need to ensure + * that it matches the same named branch + * checked out in the superproject. + */ + if (!strcmp(rs->src, "HEAD")) { + if (!detached_head && + !strcmp(head, superproject_head)) + break; + die("HEAD does not match the named branch in the superproject"); + } + default: die("src refspec '%s' must name a ref", rs->src); + } } free_refspec(refspec_nr, refspec); } + free(head); return 0; } @@ -1173,9 +1225,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, embed_gitdir_options, git_submodule_helper_usage, 0); - gitmodules_config(); - git_config(submodule_config, NULL); - if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0) return 1; @@ -1191,8 +1240,6 @@ static int is_active(int argc, const char **argv, const char *prefix) if (argc != 2) die("submodule--helper is-active takes exactly 1 argument"); - gitmodules_config(); - return !is_submodule_active(the_repository, argv[1]); } diff --git a/builtin/update-index.c b/builtin/update-index.c index 56721cf03d..d562f2ec69 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -280,7 +280,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len fill_stat_cache_info(ce, st); ce->ce_mode = ce_mode_from_stat(old, st->st_mode); - if (index_path(ce->oid.hash, path, st, + if (index_path(&ce->oid, path, st, info_only ? 0 : HASH_WRITE_OBJECT)) { free(ce); return -1; |
