diff options
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/add.c | 6 | ||||
-rw-r--r-- | builtin/am.c | 38 | ||||
-rw-r--r-- | builtin/branch.c | 24 | ||||
-rw-r--r-- | builtin/cat-file.c | 4 | ||||
-rw-r--r-- | builtin/checkout.c | 3 | ||||
-rw-r--r-- | builtin/clone.c | 3 | ||||
-rw-r--r-- | builtin/commit-tree.c | 1 | ||||
-rw-r--r-- | builtin/commit.c | 10 | ||||
-rw-r--r-- | builtin/describe.c | 9 | ||||
-rw-r--r-- | builtin/fast-export.c | 46 | ||||
-rw-r--r-- | builtin/fmt-merge-msg.c | 3 | ||||
-rw-r--r-- | builtin/for-each-ref.c | 28 | ||||
-rw-r--r-- | builtin/fsck.c | 63 | ||||
-rw-r--r-- | builtin/gc.c | 2 | ||||
-rw-r--r-- | builtin/log.c | 9 | ||||
-rw-r--r-- | builtin/ls-files.c | 5 | ||||
-rw-r--r-- | builtin/merge.c | 21 | ||||
-rw-r--r-- | builtin/name-rev.c | 2 | ||||
-rw-r--r-- | builtin/pack-objects.c | 7 | ||||
-rw-r--r-- | builtin/rev-list.c | 7 | ||||
-rw-r--r-- | builtin/rev-parse.c | 4 | ||||
-rw-r--r-- | builtin/revert.c | 2 | ||||
-rw-r--r-- | builtin/submodule--helper.c | 51 | ||||
-rw-r--r-- | builtin/tag.c | 67 | ||||
-rw-r--r-- | builtin/verify-tag.c | 14 |
25 files changed, 236 insertions, 193 deletions
diff --git a/builtin/add.c b/builtin/add.c index e888fb8c5f..5d5773d5cd 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); } } diff --git a/builtin/am.c b/builtin/am.c index c973bd96dc..73f542bec5 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -431,6 +431,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 +1011,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 +1193,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/branch.c b/builtin/branch.c index 8a0595e115..8f779b02b5 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -216,7 +216,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, if (!head_rev) die(_("Couldn't look up commit object for HEAD")); } - for (i = 0; i < argc; i++, strbuf_release(&bname)) { + for (i = 0; i < argc; i++, strbuf_reset(&bname)) { char *target = NULL; int flags = 0; @@ -281,8 +281,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, } free(name); + strbuf_release(&bname); - return(ret); + return ret; } static int calc_maxwidth(struct ref_array *refs, int remote_bonus) @@ -383,7 +384,7 @@ static char *build_format(struct ref_filter *filter, int maxwidth, const char *r return strbuf_detach(&fmt, NULL); } -static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, const char *format) +static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, struct ref_format *format) { int i; struct ref_array array; @@ -407,14 +408,17 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin if (filter->verbose) maxwidth = calc_maxwidth(&array, strlen(remote_prefix)); - if (!format) - format = to_free = build_format(filter, maxwidth, remote_prefix); - verify_ref_format(format); + if (!format->format) + format->format = to_free = build_format(filter, maxwidth, remote_prefix); + format->use_color = branch_use_color; + + if (verify_ref_format(format)) + die(_("unable to parse format string")); ref_array_sort(sorting, &array); for (i = 0; i < array.nr; i++) { - format_ref_array_item(array.items[i], format, 0, &out); + format_ref_array_item(array.items[i], format, &out); if (column_active(colopts)) { assert(!filter->verbose && "--column and --verbose are incompatible"); /* format to a string_list to let print_columns() do its job */ @@ -549,7 +553,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) struct ref_filter filter; int icase = 0; static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting; - const char *format = NULL; + struct ref_format format = REF_FORMAT_INIT; struct option options[] = { OPT_GROUP(N_("Generic options")), @@ -593,7 +597,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) N_("print only branches of the object"), 0, parse_opt_object_name }, OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")), - OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")), + OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")), OPT_END(), }; @@ -667,7 +671,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!sorting) sorting = ref_default_sorting(); sorting->ignore_case = icase; - print_ref_list(&filter, sorting, format); + print_ref_list(&filter, sorting, &format); print_columns(&output, colopts, NULL); string_list_clear(&output, 0); return 0; diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 96b786e489..188ddc3e50 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -96,7 +96,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, return !has_object_file(&oid); case 'w': - if (!path[0]) + if (!path) die("git cat-file --filters %s: <object> must be " "<sha1:path>", obj_name); @@ -106,7 +106,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, break; case 'c': - if (!path[0]) + if (!path) die("git cat-file --textconv %s: <object> must be <sha1:path>", obj_name); diff --git a/builtin/checkout.c b/builtin/checkout.c index 9661e1bcba..2d75ac66c7 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -358,6 +358,8 @@ static int checkout_paths(const struct checkout_opts *opts, state.force = 1; state.refresh_cache = 1; state.istate = &the_index; + + enable_delayed_checkout(&state); for (pos = 0; pos < active_nr; pos++) { struct cache_entry *ce = active_cache[pos]; if (ce->ce_flags & CE_MATCHED) { @@ -372,6 +374,7 @@ static int checkout_paths(const struct checkout_opts *opts, pos = skip_same_name(ce, pos) - 1; } } + errs |= finish_delayed_checkout(&state); if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); diff --git a/builtin/clone.c b/builtin/clone.c index 08b5cc433c..f7e17d2295 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -768,6 +768,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-tree.c b/builtin/commit-tree.c index a4a923d7c0..c1de41c67f 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -102,7 +102,6 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) if (fd && close(fd)) die_errno("git commit-tree: failed to close '%s'", argv[i]); - strbuf_complete_line(&buffer); continue; } diff --git a/builtin/commit.c b/builtin/commit.c index 8e93802511..1a0da71a43 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1739,17 +1739,17 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (verbose || /* Truncate the message just before the diff, if any. */ cleanup_mode == CLEANUP_SCISSORS) strbuf_setlen(&sb, wt_status_locate_end(sb.buf, sb.len)); - if (cleanup_mode != CLEANUP_NONE) strbuf_stripspace(&sb, cleanup_mode == CLEANUP_ALL); - if (template_untouched(&sb) && !allow_empty_message) { + + if (message_is_empty(&sb) && !allow_empty_message) { rollback_index_files(); - fprintf(stderr, _("Aborting commit; you did not edit the message.\n")); + fprintf(stderr, _("Aborting commit due to empty commit message.\n")); exit(1); } - if (message_is_empty(&sb) && !allow_empty_message) { + if (template_untouched(&sb) && !allow_empty_message) { rollback_index_files(); - fprintf(stderr, _("Aborting commit due to empty commit message.\n")); + fprintf(stderr, _("Aborting commit; you did not edit the message.\n")); exit(1); } diff --git a/builtin/describe.c b/builtin/describe.c index 89ea1cdd60..94ff2fba0b 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -155,18 +155,21 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi * pattern. */ if (patterns.nr) { + int found = 0; struct string_list_item *item; if (!is_tag) return 0; for_each_string_list_item(item, &patterns) { - if (!wildmatch(item->string, path + 10, 0)) + if (!wildmatch(item->string, path + 10, 0)) { + found = 1; break; + } + } - /* If we get here, no pattern matched. */ + if (!found) return 0; - } } /* Is it annotated? */ diff --git a/builtin/fast-export.c b/builtin/fast-export.c index d412c0a8f3..da42ee5e60 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -344,6 +344,7 @@ static void show_filemodify(struct diff_queue_struct *q, struct diff_options *options, void *data) { int i; + struct string_list *changed = data; /* * Handle files below a directory first, in case they are all deleted @@ -359,20 +360,31 @@ static void show_filemodify(struct diff_queue_struct *q, case DIFF_STATUS_DELETED: printf("D "); print_path(spec->path); + string_list_insert(changed, spec->path); putchar('\n'); break; case DIFF_STATUS_COPIED: case DIFF_STATUS_RENAMED: - printf("%c ", q->queue[i]->status); - print_path(ospec->path); - putchar(' '); - print_path(spec->path); - putchar('\n'); - - if (!oidcmp(&ospec->oid, &spec->oid) && - ospec->mode == spec->mode) - break; + /* + * If a change in the file corresponding to ospec->path + * has been observed, we cannot trust its contents + * because the diff is calculated based on the prior + * contents, not the current contents. So, declare a + * copy or rename only if there was no change observed. + */ + if (!string_list_has_string(changed, ospec->path)) { + printf("%c ", q->queue[i]->status); + print_path(ospec->path); + putchar(' '); + print_path(spec->path); + string_list_insert(changed, spec->path); + putchar('\n'); + + if (!oidcmp(&ospec->oid, &spec->oid) && + ospec->mode == spec->mode) + break; + } /* fallthrough */ case DIFF_STATUS_TYPE_CHANGED: @@ -393,6 +405,7 @@ static void show_filemodify(struct diff_queue_struct *q, get_object_mark(object)); } print_path(spec->path); + string_list_insert(changed, spec->path); putchar('\n'); break; @@ -528,7 +541,8 @@ static void anonymize_ident_line(const char **beg, const char **end) *end = out->buf + out->len; } -static void handle_commit(struct commit *commit, struct rev_info *rev) +static void handle_commit(struct commit *commit, struct rev_info *rev, + struct string_list *paths_of_changed_objects) { int saved_output_format = rev->diffopt.output_format; const char *commit_buffer; @@ -615,6 +629,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev) if (full_tree) printf("deleteall\n"); log_tree_diff_flush(rev); + string_list_clear(paths_of_changed_objects, 0); rev->diffopt.output_format = saved_output_format; printf("\n"); @@ -630,14 +645,15 @@ static void *anonymize_tag(const void *old, size_t *len) return strbuf_detach(&out, len); } -static void handle_tail(struct object_array *commits, struct rev_info *revs) +static void handle_tail(struct object_array *commits, struct rev_info *revs, + struct string_list *paths_of_changed_objects) { struct commit *commit; while (commits->nr) { commit = (struct commit *)commits->objects[commits->nr - 1].item; if (has_unshown_parent(commit)) return; - handle_commit(commit, revs); + handle_commit(commit, revs, paths_of_changed_objects); commits->nr--; } } @@ -977,6 +993,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) char *export_filename = NULL, *import_filename = NULL; uint32_t lastimportid; struct string_list refspecs_list = STRING_LIST_INIT_NODUP; + struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP; struct option options[] = { OPT_INTEGER(0, "progress", &progress, N_("show progress after <n> objects")), @@ -1049,14 +1066,15 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) if (prepare_revision_walk(&revs)) die("revision walk setup failed"); revs.diffopt.format_callback = show_filemodify; + revs.diffopt.format_callback_data = &paths_of_changed_objects; DIFF_OPT_SET(&revs.diffopt, RECURSIVE); while ((commit = get_revision(&revs))) { if (has_unshown_parent(commit)) { add_object_array(&commit->object, NULL, &commits); } else { - handle_commit(commit, &revs); - handle_tail(&commits, &revs); + handle_commit(commit, &revs, &paths_of_changed_objects); + handle_tail(&commits, &revs, &paths_of_changed_objects); } } diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 10cbb43416..e99b5ddbf9 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -408,7 +408,8 @@ static void shortlog(const char *name, } static void fmt_merge_msg_title(struct strbuf *out, - const char *current_branch) { + const char *current_branch) +{ int i = 0; char *sep = ""; diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 52be99cbac..e931be9ce4 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -17,25 +17,26 @@ static char const * const for_each_ref_usage[] = { int cmd_for_each_ref(int argc, const char **argv, const char *prefix) { int i; - const char *format = "%(objectname) %(objecttype)\t%(refname)"; struct ref_sorting *sorting = NULL, **sorting_tail = &sorting; - int maxcount = 0, quote_style = 0, icase = 0; + int maxcount = 0, icase = 0; struct ref_array array; struct ref_filter filter; + struct ref_format format = REF_FORMAT_INIT; struct option opts[] = { - OPT_BIT('s', "shell", "e_style, + OPT_BIT('s', "shell", &format.quote_style, N_("quote placeholders suitably for shells"), QUOTE_SHELL), - OPT_BIT('p', "perl", "e_style, + OPT_BIT('p', "perl", &format.quote_style, N_("quote placeholders suitably for perl"), QUOTE_PERL), - OPT_BIT(0 , "python", "e_style, + OPT_BIT(0 , "python", &format.quote_style, N_("quote placeholders suitably for python"), QUOTE_PYTHON), - OPT_BIT(0 , "tcl", "e_style, + OPT_BIT(0 , "tcl", &format.quote_style, N_("quote placeholders suitably for Tcl"), QUOTE_TCL), OPT_GROUP(""), OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")), - OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")), + OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")), + OPT__COLOR(&format.use_color, N_("respect format colors")), OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"), N_("field name to sort on"), &parse_opt_ref_sorting), OPT_CALLBACK(0, "points-at", &filter.points_at, @@ -52,16 +53,20 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) memset(&array, 0, sizeof(array)); memset(&filter, 0, sizeof(filter)); + format.format = "%(objectname) %(objecttype)\t%(refname)"; + + git_config(git_default_config, NULL); + parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0); if (maxcount < 0) { error("invalid --count argument: `%d'", maxcount); usage_with_options(for_each_ref_usage, opts); } - if (HAS_MULTI_BITS(quote_style)) { + if (HAS_MULTI_BITS(format.quote_style)) { error("more than one quoting style?"); usage_with_options(for_each_ref_usage, opts); } - if (verify_ref_format(format)) + if (verify_ref_format(&format)) usage_with_options(for_each_ref_usage, opts); if (!sorting) @@ -69,9 +74,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) sorting->ignore_case = icase; filter.ignore_case = icase; - /* for warn_ambiguous_refs */ - git_config(git_default_config, NULL); - filter.name_patterns = argv; filter.match_as_path = 1; filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN); @@ -80,7 +82,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) if (!maxcount || array.nr < maxcount) maxcount = array.nr; for (i = 0; i < maxcount; i++) - show_ref_array_item(array.items[i], format, quote_style); + show_ref_array_item(array.items[i], &format); ref_array_clear(&array); return 0; } diff --git a/builtin/fsck.c b/builtin/fsck.c index 99dea7adf6..d18244ab54 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -19,6 +19,8 @@ #define REACHABLE 0x0001 #define SEEN 0x0002 #define HAS_OBJ 0x0004 +/* This flag is set if something points to this object. */ +#define USED 0x0008 static int show_root; static int show_tags; @@ -168,18 +170,7 @@ static void mark_object_reachable(struct object *obj) static int traverse_one_object(struct object *obj) { - int result; - struct tree *tree = NULL; - - if (obj->type == OBJ_TREE) { - tree = (struct tree *)obj; - if (parse_tree(tree) < 0) - return 1; /* error already displayed */ - } - result = fsck_walk(obj, obj, &fsck_walk_options); - if (tree) - free_tree_buffer(tree); - return result; + return fsck_walk(obj, obj, &fsck_walk_options); } static int traverse_reachable(void) @@ -206,7 +197,7 @@ static int mark_used(struct object *obj, int type, void *data, struct fsck_optio { if (!obj) return 1; - obj->used = 1; + obj->flags |= USED; return 0; } @@ -255,7 +246,7 @@ static void check_unreachable_object(struct object *obj) } /* - * "!used" means that nothing at all points to it, including + * "!USED" means that nothing at all points to it, including * other unreachable objects. In other words, it's the "tip" * of some set of unreachable objects, usually a commit that * got dropped. @@ -266,7 +257,7 @@ static void check_unreachable_object(struct object *obj) * deleted a branch by mistake, this is a prime candidate to * start looking at, for example. */ - if (!obj->used) { + if (!(obj->flags & USED)) { if (show_dangling) printf("dangling %s %s\n", printable_type(obj), describe_object(obj)); @@ -335,6 +326,8 @@ static void check_connectivity(void) static int fsck_obj(struct object *obj) { + int err; + if (obj->flags & SEEN) return 0; obj->flags |= SEEN; @@ -345,20 +338,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)); } @@ -374,7 +360,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, @@ -390,7 +381,8 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type, errors_found |= ERROR_OBJECT; return error("%s: object corrupt or missing", oid_to_hex(oid)); } - obj->flags = HAS_OBJ; + obj->flags &= ~(REACHABLE | SEEN); + obj->flags |= HAS_OBJ; return fsck_obj(obj); } @@ -408,7 +400,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, add_decoration(fsck_walk_options.object_names, obj, xstrfmt("%s@{%"PRItime"}", refname, timestamp)); - obj->used = 1; + obj->flags |= USED; mark_object_reachable(obj); } else { error("%s: invalid reflog entry %s", refname, oid_to_hex(oid)); @@ -456,7 +448,7 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid, errors_found |= ERROR_REFS; } default_refs++; - obj->used = 1; + obj->flags |= USED; if (name_objects) add_decoration(fsck_walk_options.object_names, obj, xstrdup(refname)); @@ -524,7 +516,8 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data) return 0; /* keep checking other objects */ } - obj->flags = HAS_OBJ; + obj->flags &= ~(REACHABLE | SEEN); + obj->flags |= HAS_OBJ; if (fsck_obj(obj)) errors_found |= ERROR_OBJECT; return 0; @@ -606,7 +599,7 @@ static int fsck_cache_tree(struct cache_tree *it) errors_found |= ERROR_REFS; return 1; } - obj->used = 1; + obj->flags |= USED; if (name_objects) add_decoration(fsck_walk_options.object_names, obj, xstrdup(":")); @@ -667,7 +660,7 @@ static struct option fsck_opts[] = { int cmd_fsck(int argc, const char **argv, const char *prefix) { - int i, heads; + int i; struct alternate_object_database *alt; errors_found = 0; @@ -735,7 +728,6 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) } } - heads = 0; for (i = 0; i < argc; i++) { const char *arg = argv[i]; unsigned char sha1[20]; @@ -748,12 +740,11 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) continue; } - obj->used = 1; + obj->flags |= USED; if (name_objects) add_decoration(fsck_walk_options.object_names, obj, xstrdup(arg)); mark_object_reachable(obj); - heads++; continue; } error("invalid parameter: expected sha1, got '%s'", arg); @@ -785,7 +776,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) if (!blob) continue; obj = &blob->object; - obj->used = 1; + obj->flags |= USED; if (name_objects) add_decoration(fsck_walk_options.object_names, obj, diff --git a/builtin/gc.c b/builtin/gc.c index e6b84475ae..53c19be8b2 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -257,7 +257,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) int should_exit; if (!scan_fmt) - scan_fmt = xstrfmt("%s %%%dc", "%"SCNuMAX, HOST_NAME_MAX); + scan_fmt = xstrfmt("%s %%%ds", "%"SCNuMAX, HOST_NAME_MAX); fp = fopen(pidfile_path, "r"); memset(locking_host, 0, sizeof(locking_host)); should_exit = diff --git a/builtin/log.c b/builtin/log.c index c6362cf92e..5ffc380bd7 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -372,11 +372,14 @@ static int cmd_log_walk(struct rev_info *rev) */ rev->max_count++; if (!rev->reflog_info) { - /* we allow cycles in reflog ancestry */ + /* + * We may show a given commit multiple times when + * walking the reflogs. + */ free_commit_buffer(commit); + free_commit_list(commit->parents); + commit->parents = NULL; } - free_commit_list(commit->parents); - commit->parents = NULL; if (saved_nrl < rev->diffopt.needed_rename_limit) saved_nrl = rev->diffopt.needed_rename_limit; if (rev->diffopt.degraded_cc_to_c) diff --git a/builtin/ls-files.c b/builtin/ls-files.c index b8514a0029..c6126eae55 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -362,7 +362,7 @@ static void prune_index(struct index_state *istate, int pos; unsigned int first, last; - if (!prefix) + if (!prefix || !istate->cache_nr) return; pos = index_name_pos(istate, prefix, prefixlen); if (pos < 0) @@ -378,8 +378,7 @@ static void prune_index(struct index_state *istate, } last = next; } - memmove(istate->cache, istate->cache + pos, - (last - pos) * sizeof(struct cache_entry *)); + MOVE_ARRAY(istate->cache, istate->cache + pos, last - pos); istate->cache_nr = last - pos; } diff --git a/builtin/merge.c b/builtin/merge.c index 900bafdb45..23c53a3082 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -537,7 +537,7 @@ static void parse_branch_merge_options(char *bmo) die(_("Bad branch.%s.mergeoptions string: %s"), branch, split_cmdline_strerror(argc)); REALLOC_ARRAY(argv, argc + 2); - memmove(argv + 1, argv, sizeof(*argv) * (argc + 1)); + MOVE_ARRAY(argv + 1, argv, argc + 1); argc++; argv[0] = "branch.*.mergeoptions"; parse_options(argc, argv, NULL, builtin_merge_options, @@ -756,13 +756,17 @@ 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); + 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 +908,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 +924,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 +931,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"; @@ -1117,8 +1126,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/name-rev.c b/builtin/name-rev.c index c41ea7c2a6..598da6c8bc 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -253,7 +253,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo struct commit *commit = (struct commit *)o; int from_tag = starts_with(path, "refs/tags/"); - if (taggerdate == ULONG_MAX) + if (taggerdate == TIME_MAX) taggerdate = ((struct commit *)o)->date; path = name_ref_abbrev(path, can_abbreviate_output); name_rev(commit, xstrdup(path), taggerdate, 0, 0, diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index ffb13f7800..bd391e97a4 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1289,7 +1289,7 @@ static int done_pbase_path_pos(unsigned hash) static int check_pbase_path(unsigned hash) { - int pos = (!done_pbase_paths) ? -1 : done_pbase_path_pos(hash); + int pos = done_pbase_path_pos(hash); if (0 <= pos) return 1; pos = -pos - 1; @@ -1298,9 +1298,8 @@ static int check_pbase_path(unsigned hash) done_pbase_paths_alloc); done_pbase_paths_num++; if (pos < done_pbase_paths_num) - memmove(done_pbase_paths + pos + 1, - done_pbase_paths + pos, - (done_pbase_paths_num - pos - 1) * sizeof(unsigned)); + MOVE_ARRAY(done_pbase_paths + pos + 1, done_pbase_paths + pos, + done_pbase_paths_num - pos - 1); done_pbase_paths[pos] = hash; return 0; } diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 95d84d5cda..95b4128250 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -11,6 +11,7 @@ #include "graph.h" #include "bisect.h" #include "progress.h" +#include "reflog-walk.h" static const char rev_list_usage[] = "git rev-list [OPTION] <commit-id>... [ -- paths... ]\n" @@ -122,6 +123,7 @@ static void show_commit(struct commit *commit, void *data) ctx.date_mode_explicit = revs->date_mode_explicit; ctx.fmt = revs->commit_format; ctx.output_encoding = get_log_output_encoding(); + ctx.color = revs->diffopt.use_color; pretty_print_commit(&ctx, commit, &buf); if (buf.len) { if (revs->commit_format != CMIT_FMT_ONELINE) @@ -348,9 +350,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) /* Only --header was specified */ revs.commit_format = CMIT_FMT_RAW; - if ((!revs.commits && + if ((!revs.commits && reflog_walk_empty(revs.reflog_info) && (!(revs.tag_objects || revs.tree_objects || revs.blob_objects) && - !revs.pending.nr)) || + !revs.pending.nr) && + !revs.rev_input_given) || revs.diff) usage(rev_list_usage); diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index c78b7b33d6..7f965fe74e 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -757,8 +757,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--bisect")) { - for_each_ref_in("refs/bisect/bad", show_reference, NULL); - for_each_ref_in("refs/bisect/good", anti_reference, NULL); + for_each_fullref_in("refs/bisect/bad", show_reference, NULL, 0); + for_each_fullref_in("refs/bisect/good", anti_reference, NULL, 0); continue; } if (opt_with_value(arg, "--branches", &arg)) { 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/submodule--helper.c b/builtin/submodule--helper.c index 6abdad3294..895555c93a 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -930,7 +930,7 @@ static int update_clone_task_finished(int result, const struct cache_entry *ce; struct submodule_update_clone *suc = suc_cb; - int *idxP = *(int**)idx_task_cb; + int *idxP = idx_task_cb; int idx = *idxP; free(idxP); @@ -1108,9 +1108,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 < 2) - die("submodule--helper push-check requires at least 1 argument"); + if (argc < 3) + die("submodule--helper push-check requires at least 2 arguments"); + + /* + * 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 +1152,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; } diff --git a/builtin/tag.c b/builtin/tag.c index 01154ea8dc..00382a56f5 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -32,7 +32,8 @@ static const char * const git_tag_usage[] = { static unsigned int colopts; static int force_sign_annotate; -static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, const char *format) +static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, + struct ref_format *format) { struct ref_array array; char *to_free = NULL; @@ -43,23 +44,24 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con if (filter->lines == -1) filter->lines = 0; - if (!format) { + if (!format->format) { if (filter->lines) { to_free = xstrfmt("%s %%(contents:lines=%d)", "%(align:15)%(refname:lstrip=2)%(end)", filter->lines); - format = to_free; + format->format = to_free; } else - format = "%(refname:lstrip=2)"; + format->format = "%(refname:lstrip=2)"; } - verify_ref_format(format); + if (verify_ref_format(format)) + die(_("unable to parse format string")); filter->with_commit_tag_algo = 1; filter_refs(&array, filter, FILTER_REFS_TAGS); ref_array_sort(sorting, &array); for (i = 0; i < array.nr; i++) - show_ref_array_item(array.items[i], format, 0); + show_ref_array_item(array.items[i], format); ref_array_clear(&array); free(to_free); @@ -105,17 +107,17 @@ static int verify_tag(const char *name, const char *ref, const struct object_id *oid, const void *cb_data) { int flags; - const char *fmt_pretty = cb_data; + const struct ref_format *format = cb_data; flags = GPG_VERIFY_VERBOSE; - if (fmt_pretty) + if (format->format) flags = GPG_VERIFY_OMIT_STATUS; if (gpg_verify_tag(oid->hash, name, flags)) return -1; - if (fmt_pretty) - pretty_print_ref(name, oid->hash, fmt_pretty); + if (format->format) + pretty_print_ref(name, oid->hash, format); return 0; } @@ -134,30 +136,6 @@ static const char tag_template_nocleanup[] = "Lines starting with '%c' will be kept; you may remove them" " yourself if you want to.\n"); -/* Parse arg given and add it the ref_sorting array */ -static int parse_sorting_string(const char *arg, struct ref_sorting **sorting_tail) -{ - struct ref_sorting *s; - int len; - - s = xcalloc(1, sizeof(*s)); - s->next = *sorting_tail; - *sorting_tail = s; - - if (*arg == '-') { - s->reverse = 1; - arg++; - } - if (skip_prefix(arg, "version:", &arg) || - skip_prefix(arg, "v:", &arg)) - s->version = 1; - - len = strlen(arg); - s->atom = parse_ref_filter_atom(arg, arg+len); - - return 0; -} - static int git_tag_config(const char *var, const char *value, void *cb) { int status; @@ -166,7 +144,7 @@ static int git_tag_config(const char *var, const char *value, void *cb) if (!strcmp(var, "tag.sort")) { if (!value) return config_error_nonbool(var); - parse_sorting_string(value, sorting_tail); + parse_ref_sorting(sorting_tail, value); return 0; } @@ -180,7 +158,7 @@ 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_default_config(var, value, cb); + return git_color_default_config(var, value, cb); } static void write_tag_body(int fd, const struct object_id *oid) @@ -392,7 +370,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) struct strbuf err = STRBUF_INIT; struct ref_filter filter; static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting; - const char *format = NULL; + struct ref_format format = REF_FORMAT_INIT; int icase = 0; struct option options[] = { OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'), @@ -431,7 +409,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix) N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT, parse_opt_object_name, (intptr_t) "HEAD" }, - OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")), + OPT_STRING( 0 , "format", &format.format, N_("format"), + N_("format to use for the output")), + OPT__COLOR(&format.use_color, N_("respect format colors")), OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")), OPT_END() }; @@ -461,6 +441,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix) cmdmode = 'l'; } + if (cmdmode == 'l') + setup_auto_pager("tag", 1); + if ((create_tag_object || force) && (cmdmode != 0)) usage_with_options(git_tag_usage, options); @@ -483,7 +466,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) run_column_filter(colopts, &copts); } filter.name_patterns = argv; - ret = list_tags(&filter, sorting, format); + ret = list_tags(&filter, sorting, &format); if (column_active(colopts)) stop_column_filter(); return ret; @@ -501,9 +484,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix) if (cmdmode == 'd') return for_each_tag_name(argv, delete_tag, NULL); if (cmdmode == 'v') { - if (format) - verify_ref_format(format); - return for_each_tag_name(argv, verify_tag, format); + if (format.format && verify_ref_format(&format)) + usage_with_options(git_tag_usage, options); + return for_each_tag_name(argv, verify_tag, &format); } if (msg.given || msgfile) { diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index f9a5f7535a..87d73e856a 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -32,11 +32,11 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; - char *fmt_pretty = NULL; + struct ref_format format = REF_FORMAT_INIT; const struct option verify_tag_options[] = { OPT__VERBOSE(&verbose, N_("print tag contents")), OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW), - OPT_STRING( 0 , "format", &fmt_pretty, N_("format"), N_("format to use for the output")), + OPT_STRING(0, "format", &format.format, N_("format"), N_("format to use for the output")), OPT_END() }; @@ -50,8 +50,10 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) if (verbose) flags |= GPG_VERIFY_VERBOSE; - if (fmt_pretty) { - verify_ref_format(fmt_pretty); + if (format.format) { + if (verify_ref_format(&format)) + usage_with_options(verify_tag_usage, + verify_tag_options); flags |= GPG_VERIFY_OMIT_STATUS; } @@ -68,8 +70,8 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) continue; } - if (fmt_pretty) - pretty_print_ref(name, sha1, fmt_pretty); + if (format.format) + pretty_print_ref(name, sha1, &format); } return had_error; } |