diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-04-14 12:47:44 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-04-14 12:47:45 -0700 |
commit | ee30f17805f51d372ff9c5036f1d142c167e5e34 (patch) | |
tree | f47b60cb10efd46b82c067b3e17a25004808a1c5 /builtin | |
parent | 7307dd898988c79fc687051e783b3cac8488a559 (diff) | |
parent | 2ab56603bffb7aed6ec6d2a36deddfdf49cfd5ad (diff) | |
download | git-ee30f17805f51d372ff9c5036f1d142c167e5e34.tar.gz |
Merge branch 'sb/submodule-path-misc-bugs' into sb/submodule-init
"git submodule" reports the paths of submodules the command
recurses into, but this was incorrect when the command was not run
from the root level of the superproject.
Any further comments? Otherwise will merge to 'next'.
* sb/submodule-path-misc-bugs: (600 commits)
t7407: make expectation as clear as possible
submodule update: test recursive path reporting from subdirectory
submodule update: align reporting path for custom command execution
submodule status: correct path handling in recursive submodules
submodule update --init: correct path handling in recursive submodules
submodule foreach: correct path display in recursive submodules
Git 2.8
Documentation: fix git-p4 AsciiDoc formatting
mingw: skip some tests in t9115 due to file name issues
t1300: fix the new --show-origin tests on Windows
t1300-repo-config: make it resilient to being run via 'sh -x'
config --show-origin: report paths with forward slashes
submodule: fix regression for deinit without submodules
l10n: pt_PT: Update and add new translations
l10n: ca.po: update translation
Git 2.8-rc4
Documentation: fix broken linkgit to git-config
Documentation: use ASCII quotation marks in git-p4
Revert "config.mak.uname: use clang for Mac OS X 10.6"
git-compat-util: st_add4: work around gcc 4.2.x compiler crash
...
Diffstat (limited to 'builtin')
55 files changed, 689 insertions, 706 deletions
diff --git a/builtin/am.c b/builtin/am.c index 9fb42fdd71..d003939bc5 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -46,21 +46,6 @@ static int is_empty_file(const char *filename) } /** - * Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators. - */ -static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp) -{ - if (strbuf_getwholeline(sb, fp, '\n')) - return EOF; - if (sb->buf[sb->len - 1] == '\n') { - strbuf_setlen(sb, sb->len - 1); - if (sb->len > 0 && sb->buf[sb->len - 1] == '\r') - strbuf_setlen(sb, sb->len - 1); - } - return 0; -} - -/** * Returns the length of the first line of msg. */ static int linelen(const char *msg) @@ -284,7 +269,7 @@ static char *read_shell_var(FILE *fp, const char *key) struct strbuf sb = STRBUF_INIT; const char *str; - if (strbuf_getline(&sb, fp, '\n')) + if (strbuf_getline_lf(&sb, fp)) goto fail; if (!skip_prefix(sb.buf, key, &str)) @@ -573,7 +558,7 @@ static int copy_notes_for_rebase(const struct am_state *state) fp = xfopen(am_path(state, "rewritten"), "r"); - while (!strbuf_getline(&sb, fp, '\n')) { + while (!strbuf_getline_lf(&sb, fp)) { unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ]; if (sb.len != GIT_SHA1_HEXSZ * 2 + 1) { @@ -628,7 +613,7 @@ static int is_mail(FILE *fp) if (regcomp(®ex, header_regex, REG_NOSUB | REG_EXTENDED)) die("invalid pattern: %s", header_regex); - while (!strbuf_getline_crlf(&sb, fp)) { + while (!strbuf_getline(&sb, fp)) { if (!sb.len) break; /* End of header */ @@ -675,7 +660,7 @@ static int detect_patch_format(const char **paths) fp = xfopen(*paths, "r"); - while (!strbuf_getline_crlf(&l1, fp)) { + while (!strbuf_getline(&l1, fp)) { if (l1.len) break; } @@ -696,9 +681,9 @@ static int detect_patch_format(const char **paths) } strbuf_reset(&l2); - strbuf_getline_crlf(&l2, fp); + strbuf_getline(&l2, fp); strbuf_reset(&l3); - strbuf_getline_crlf(&l3, fp); + strbuf_getline(&l3, fp); /* * If the second line is empty and the third is a From, Author or Date @@ -817,7 +802,7 @@ static int stgit_patch_to_mail(FILE *out, FILE *in, int keep_cr) struct strbuf sb = STRBUF_INIT; int subject_printed = 0; - while (!strbuf_getline(&sb, in, '\n')) { + while (!strbuf_getline_lf(&sb, in)) { const char *str; if (str_isspace(sb.buf)) @@ -875,7 +860,7 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths, return error(_("could not open '%s' for reading: %s"), *paths, strerror(errno)); - while (!strbuf_getline(&sb, fp, '\n')) { + while (!strbuf_getline_lf(&sb, fp)) { if (*sb.buf == '#') continue; /* skip comment lines */ @@ -900,7 +885,7 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr) { struct strbuf sb = STRBUF_INIT; - while (!strbuf_getline(&sb, in, '\n')) { + while (!strbuf_getline_lf(&sb, in)) { const char *str; if (skip_prefix(sb.buf, "# User ", &str)) @@ -1317,7 +1302,7 @@ static int parse_mail(struct am_state *state, const char *mail) /* Extract message and author information */ fp = xfopen(am_path(state, "info"), "r"); - while (!strbuf_getline(&sb, fp, '\n')) { + while (!strbuf_getline_lf(&sb, fp)) { const char *x; if (skip_prefix(sb.buf, "Subject: ", &x)) { @@ -1383,7 +1368,7 @@ static int get_mail_commit_sha1(unsigned char *commit_id, const char *mail) FILE *fp = xfopen(mail, "r"); const char *x; - if (strbuf_getline(&sb, fp, '\n')) + if (strbuf_getline_lf(&sb, fp)) return -1; if (!skip_prefix(sb.buf, "From ", &x)) @@ -1657,7 +1642,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa init_revisions(&rev_info, NULL); rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS; - diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1); + diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix); add_pending_sha1(&rev_info, "HEAD", our_tree, 0); diff_setup_done(&rev_info.diffopt); run_diff_index(&rev_info, 1); @@ -1821,7 +1806,7 @@ static int do_interactive(struct am_state *state) if (!pager) pager = "cat"; - argv_array_push(&cp.args, pager); + prepare_pager_args(&cp, pager); argv_array_push(&cp.args, am_path(state, "patch")); run_command(&cp); } @@ -1939,6 +1924,7 @@ next: */ if (!state->rebasing) { am_destroy(state); + close_all_packs(); run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); } } diff --git a/builtin/apply.c b/builtin/apply.c index deb1364fa8..42c610e2ec 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2632,7 +2632,7 @@ static void update_image(struct image *img, insert_count = postimage->len; /* Adjust the contents */ - result = xmalloc(img->len + insert_count - remove_count + 1); + result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1)); memcpy(result, img->buf, applied_at); memcpy(result + applied_at, postimage->buf, postimage->len); memcpy(result + applied_at + postimage->len, @@ -4464,16 +4464,6 @@ static int option_parse_p(const struct option *opt, return 0; } -static int option_parse_z(const struct option *opt, - const char *arg, int unset) -{ - if (unset) - line_termination = '\n'; - else - line_termination = 0; - return 0; -} - static int option_parse_space_change(const struct option *opt, const char *arg, int unset) { @@ -4546,9 +4536,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix_) N_( "attempt three-way merge if a patch does not apply")), OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor, N_("build a temporary index based on embedded index information")), - { OPTION_CALLBACK, 'z', NULL, NULL, NULL, - N_("paths are separated with NUL character"), - PARSE_OPT_NOARG, option_parse_z }, + /* Think twice before adding "--nul" synonym to this */ + OPT_SET_INT('z', NULL, &line_termination, + N_("paths are separated with NUL character"), '\0'), OPT_INTEGER('C', NULL, &p_context, N_("ensure at least <n> lines of context match")), { OPTION_CALLBACK, 0, "whitespace", &whitespace_option, N_("action"), diff --git a/builtin/blame.c b/builtin/blame.c index 1df13cf7f4..e982fb8137 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -28,6 +28,7 @@ #include "line-range.h" #include "line-log.h" #include "dir.h" +#include "progress.h" static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"); @@ -50,6 +51,7 @@ static int incremental; static int xdl_opts; static int abbrev = -1; static int no_whole_file_rename; +static int show_progress; static struct date_mode blame_date_mode = { DATE_ISO8601 }; static size_t blame_date_width; @@ -127,6 +129,11 @@ struct origin { char path[FLEX_ARRAY]; }; +struct progress_info { + struct progress *progress; + int blamed_lines; +}; + static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen, xdl_emit_hunk_consume_func_t hunk_func, void *cb_data) { @@ -459,13 +466,11 @@ static void queue_blames(struct scoreboard *sb, struct origin *porigin, static struct origin *make_origin(struct commit *commit, const char *path) { struct origin *o; - size_t pathlen = strlen(path) + 1; - o = xcalloc(1, sizeof(*o) + pathlen); + FLEX_ALLOC_STR(o, path, path); o->commit = commit; o->refcnt = 1; o->next = commit->util; commit->util = o; - memcpy(o->path, path, pathlen); /* includes NUL */ return o; } @@ -1746,7 +1751,8 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat) * The blame_entry is found to be guilty for the range. * Show it in incremental output. */ -static void found_guilty_entry(struct blame_entry *ent) +static void found_guilty_entry(struct blame_entry *ent, + struct progress_info *pi) { if (incremental) { struct origin *suspect = ent->suspect; @@ -1758,6 +1764,8 @@ static void found_guilty_entry(struct blame_entry *ent) write_filename_info(suspect->path); maybe_flush_or_die(stdout, "stdout"); } + pi->blamed_lines += ent->num_lines; + display_progress(pi->progress, pi->blamed_lines); } /* @@ -1768,6 +1776,11 @@ static void assign_blame(struct scoreboard *sb, int opt) { struct rev_info *revs = sb->revs; struct commit *commit = prio_queue_get(&sb->commits); + struct progress_info pi = { NULL, 0 }; + + if (show_progress) + pi.progress = start_progress_delay(_("Blaming lines"), + sb->num_lines, 50, 1); while (commit) { struct blame_entry *ent; @@ -1809,7 +1822,7 @@ static void assign_blame(struct scoreboard *sb, int opt) suspect->guilty = 1; for (;;) { struct blame_entry *next = ent->next; - found_guilty_entry(ent); + found_guilty_entry(ent, &pi); if (next) { ent = next; continue; @@ -1825,6 +1838,8 @@ static void assign_blame(struct scoreboard *sb, int opt) if (DEBUG) /* sanity */ sanity_check_refcnt(sb); } + + stop_progress(&pi.progress); } static const char *format_time(unsigned long time, const char *tz_str, @@ -2042,7 +2057,8 @@ static int prepare_lines(struct scoreboard *sb) for (p = buf; p < end; p = get_next_line(p, end)) num++; - sb->lineno = lineno = xmalloc(sizeof(*sb->lineno) * (num + 1)); + ALLOC_ARRAY(sb->lineno, num + 1); + lineno = sb->lineno; for (p = buf; p < end; p = get_next_line(p, end)) *lineno++ = p - buf; @@ -2392,11 +2408,6 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, ce->ce_mode = create_ce_mode(mode); add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); - /* - * We are not going to write this out, so this does not matter - * right now, but someday we might optimize diff-index --cached - * with cache-tree information. - */ cache_tree_invalidate_path(&the_index, path); return commit; @@ -2520,6 +2531,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")), OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")), OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")), + OPT_BOOL(0, "progress", &show_progress, N_("Force progress reporting")), OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE), OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME), OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER), @@ -2555,6 +2567,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) save_commit_buffer = 0; dashdash_pos = 0; + show_progress = -1; parse_options_start(&ctx, argc, argv, prefix, options, PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0); @@ -2579,6 +2592,13 @@ parse_done: DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES); argc = parse_options_end(&ctx); + if (incremental || (output_option & OUTPUT_PORCELAIN)) { + if (show_progress > 0) + die("--progress can't be used with --incremental or porcelain formats"); + show_progress = 0; + } else if (show_progress < 0) + show_progress = isatty(2); + if (0 < abbrev) /* one more abbrev length is needed for the boundary commit */ abbrev++; @@ -2828,11 +2848,11 @@ parse_done: read_mailmap(&mailmap, NULL); + assign_blame(&sb, opt); + if (!incremental) setup_pager(); - assign_blame(&sb, opt); - free(final_commit_name); if (incremental) diff --git a/builtin/branch.c b/builtin/branch.c index 3f6c825db1..7b45b6bd6b 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -570,7 +570,6 @@ static const char edit_description[] = "BRANCH_DESCRIPTION"; static int edit_branch_description(const char *branch_name) { - int status; struct strbuf buf = STRBUF_INIT; struct strbuf name = STRBUF_INIT; @@ -595,11 +594,11 @@ static int edit_branch_description(const char *branch_name) strbuf_stripspace(&buf, 1); strbuf_addf(&name, "branch.%s.description", branch_name); - status = git_config_set(name.buf, buf.len ? buf.buf : NULL); + git_config_set(name.buf, buf.len ? buf.buf : NULL); strbuf_release(&name); strbuf_release(&buf); - return status; + return 0; } int cmd_branch(int argc, const char **argv, const char *prefix) diff --git a/builtin/cat-file.c b/builtin/cat-file.c index c0fd8dbb1c..54db1184a0 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -401,7 +401,7 @@ static int batch_objects(struct batch_options *opt) save_warning = warn_on_object_refname_ambiguity; warn_on_object_refname_ambiguity = 0; - while (strbuf_getline(&buf, stdin, '\n') != EOF) { + while (strbuf_getline(&buf, stdin) != EOF) { if (data.split_on_whitespace) { /* * Split at first whitespace, tying off the beginning diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 265c9ba022..53a5a18c16 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -72,23 +72,23 @@ static void check_attr(const char *prefix, int cnt, static void check_attr_stdin_paths(const char *prefix, int cnt, struct git_attr_check *check) { - struct strbuf buf, nbuf; - int line_termination = nul_term_line ? 0 : '\n'; - - strbuf_init(&buf, 0); - strbuf_init(&nbuf, 0); - while (strbuf_getline(&buf, stdin, line_termination) != EOF) { - if (line_termination && buf.buf[0] == '"') { - strbuf_reset(&nbuf); - if (unquote_c_style(&nbuf, buf.buf, NULL)) + struct strbuf buf = STRBUF_INIT; + struct strbuf unquoted = STRBUF_INIT; + strbuf_getline_fn getline_fn; + + getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf; + while (getline_fn(&buf, stdin) != EOF) { + if (!nul_term_line && buf.buf[0] == '"') { + strbuf_reset(&unquoted); + if (unquote_c_style(&unquoted, buf.buf, NULL)) die("line is badly quoted"); - strbuf_swap(&buf, &nbuf); + strbuf_swap(&buf, &unquoted); } check_attr(prefix, cnt, check, buf.buf); maybe_flush_or_die(stdout, "attribute to stdout"); } strbuf_release(&buf); - strbuf_release(&nbuf); + strbuf_release(&unquoted); } static NORETURN void error_with_usage(const char *msg) diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index 43f361797a..1d73d3ca3d 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -115,19 +115,19 @@ static int check_ignore(struct dir_struct *dir, static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix) { - struct strbuf buf, nbuf; + struct strbuf buf = STRBUF_INIT; + struct strbuf unquoted = STRBUF_INIT; char *pathspec[2] = { NULL, NULL }; - int line_termination = nul_term_line ? 0 : '\n'; + strbuf_getline_fn getline_fn; int num_ignored = 0; - strbuf_init(&buf, 0); - strbuf_init(&nbuf, 0); - while (strbuf_getline(&buf, stdin, line_termination) != EOF) { - if (line_termination && buf.buf[0] == '"') { - strbuf_reset(&nbuf); - if (unquote_c_style(&nbuf, buf.buf, NULL)) + getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf; + while (getline_fn(&buf, stdin) != EOF) { + if (!nul_term_line && buf.buf[0] == '"') { + strbuf_reset(&unquoted); + if (unquote_c_style(&unquoted, buf.buf, NULL)) die("line is badly quoted"); - strbuf_swap(&buf, &nbuf); + strbuf_swap(&buf, &unquoted); } pathspec[0] = buf.buf; num_ignored += check_ignore(dir, prefix, @@ -135,7 +135,7 @@ static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix) maybe_flush_or_die(stdout, "check-ignore to stdout"); } strbuf_release(&buf); - strbuf_release(&nbuf); + strbuf_release(&unquoted); return num_ignored; } diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c index eaaea546d3..cf0f54f6b9 100644 --- a/builtin/check-mailmap.c +++ b/builtin/check-mailmap.c @@ -54,7 +54,7 @@ int cmd_check_mailmap(int argc, const char **argv, const char *prefix) if (use_stdin) { struct strbuf buf = STRBUF_INIT; - while (strbuf_getline(&buf, stdin, '\n') != EOF) { + while (strbuf_getline_lf(&buf, stdin) != EOF) { check_mailmap(&mailmap, buf.buf); maybe_flush_or_die(stdout, "stdout"); } diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index fd915d5984..eac499450f 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -20,7 +20,7 @@ static const char builtin_check_ref_format_usage[] = */ static char *collapse_slashes(const char *refname) { - char *ret = xmalloc(strlen(refname) + 1); + char *ret = xmallocz(strlen(refname)); char ch; char prev = '/'; char *cp = ret; diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 8028c3768f..92c69672e9 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -11,7 +11,7 @@ #include "parse-options.h" #define CHECKOUT_ALL 4 -static int line_termination = '\n'; +static int nul_term_line; static int checkout_stage; /* default to checkout stage0 */ static int to_tempfile; static char topath[4][TEMPORARY_FILENAME_LENGTH + 1]; @@ -35,7 +35,8 @@ static void write_tempfile_record(const char *name, const char *prefix) fputs(topath[checkout_stage], stdout); putchar('\t'); - write_name_quoted_relative(name, prefix, stdout, line_termination); + write_name_quoted_relative(name, prefix, stdout, + nul_term_line ? '\0' : '\n'); for (i = 0; i < 4; i++) { topath[i][0] = 0; @@ -129,36 +130,6 @@ static const char * const builtin_checkout_index_usage[] = { static struct lock_file lock_file; -static int option_parse_u(const struct option *opt, - const char *arg, int unset) -{ - int *newfd = opt->value; - - state.refresh_cache = 1; - state.istate = &the_index; - if (*newfd < 0) - *newfd = hold_locked_index(&lock_file, 1); - return 0; -} - -static int option_parse_z(const struct option *opt, - const char *arg, int unset) -{ - if (unset) - line_termination = '\n'; - else - line_termination = 0; - return 0; -} - -static int option_parse_prefix(const struct option *opt, - const char *arg, int unset) -{ - state.base_dir = arg; - state.base_dir_len = strlen(arg); - return 0; -} - static int option_parse_stage(const struct option *opt, const char *arg, int unset) { @@ -170,7 +141,7 @@ static int option_parse_stage(const struct option *opt, if ('1' <= ch && ch <= '3') checkout_stage = arg[0] - '0'; else - die("stage should be between 1 and 3 or all"); + die(_("stage should be between 1 and 3 or all")); } return 0; } @@ -183,6 +154,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) int read_from_stdin = 0; int prefix_length; int force = 0, quiet = 0, not_new = 0; + int index_opt = 0; struct option builtin_checkout_index_options[] = { OPT_BOOL('a', "all", &all, N_("check out all files in the index")), @@ -191,22 +163,19 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) N_("no warning for existing files and files not in index")), OPT_BOOL('n', "no-create", ¬_new, N_("don't checkout new files")), - { OPTION_CALLBACK, 'u', "index", &newfd, NULL, - N_("update stat information in the index file"), - PARSE_OPT_NOARG, option_parse_u }, - { OPTION_CALLBACK, 'z', NULL, NULL, NULL, - N_("paths are separated with NUL character"), - PARSE_OPT_NOARG, option_parse_z }, + OPT_BOOL('u', "index", &index_opt, + N_("update stat information in the index file")), + OPT_BOOL('z', NULL, &nul_term_line, + N_("paths are separated with NUL character")), OPT_BOOL(0, "stdin", &read_from_stdin, N_("read list of paths from the standard input")), OPT_BOOL(0, "temp", &to_tempfile, N_("write the content to temporary files")), - OPT_CALLBACK(0, "prefix", NULL, N_("string"), - N_("when creating files, prepend <string>"), - option_parse_prefix), - OPT_CALLBACK(0, "stage", NULL, NULL, + OPT_STRING(0, "prefix", &state.base_dir, N_("string"), + N_("when creating files, prepend <string>")), + { OPTION_CALLBACK, 0, "stage", NULL, "1-3|all", N_("copy out the files from named stage"), - option_parse_stage), + PARSE_OPT_NONEG, option_parse_stage }, OPT_END() }; @@ -214,7 +183,6 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) usage_with_options(builtin_checkout_index_usage, builtin_checkout_index_options); git_config(git_default_config, NULL); - state.base_dir = ""; prefix_length = prefix ? strlen(prefix) : 0; if (read_cache() < 0) { @@ -227,15 +195,17 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) state.quiet = quiet; state.not_new = not_new; - if (state.base_dir_len || to_tempfile) { - /* when --prefix is specified we do not - * want to update cache. - */ - if (state.refresh_cache) { - rollback_lock_file(&lock_file); - newfd = -1; - } - state.refresh_cache = 0; + if (!state.base_dir) + state.base_dir = ""; + state.base_dir_len = strlen(state.base_dir); + + /* + * when --prefix is specified we do not want to update cache. + */ + if (index_opt && !state.base_dir_len && !to_tempfile) { + state.refresh_cache = 1; + state.istate = &the_index; + newfd = hold_locked_index(&lock_file, 1); } /* Check out named files first */ @@ -253,24 +223,27 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) } if (read_from_stdin) { - struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; + struct strbuf unquoted = STRBUF_INIT; + strbuf_getline_fn getline_fn; if (all) die("git checkout-index: don't mix '--all' and '--stdin'"); - while (strbuf_getline(&buf, stdin, line_termination) != EOF) { + getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf; + while (getline_fn(&buf, stdin) != EOF) { char *p; - if (line_termination && buf.buf[0] == '"') { - strbuf_reset(&nbuf); - if (unquote_c_style(&nbuf, buf.buf, NULL)) + if (!nul_term_line && buf.buf[0] == '"') { + strbuf_reset(&unquoted); + if (unquote_c_style(&unquoted, buf.buf, NULL)) die("line is badly quoted"); - strbuf_swap(&buf, &nbuf); + strbuf_swap(&buf, &unquoted); } p = prefix_path(prefix, prefix_length, buf.buf); checkout_file(p, prefix); free(p); } - strbuf_release(&nbuf); + strbuf_release(&unquoted); strbuf_release(&buf); } diff --git a/builtin/checkout.c b/builtin/checkout.c index e8110a9243..efcbd8f6b5 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -661,7 +661,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts, describe_detached_head(_("HEAD is now at"), new->commit); } } else if (new->path) { /* Switch branches. */ - create_symref("HEAD", new->path, msg.buf); + if (create_symref("HEAD", new->path, msg.buf) < 0) + die(_("unable to update HEAD")); if (!opts->quiet) { if (old->path && !strcmp(new->path, old->path)) { if (opts->new_branch_force) @@ -981,7 +982,8 @@ static int parse_branchname_arg(int argc, const char **argv, */ int recover_with_dwim = dwim_new_local_branch_ok; - if (check_filename(NULL, arg) && !has_dash_dash) + if (!has_dash_dash && + (check_filename(NULL, arg) || !no_wildcard(arg))) recover_with_dwim = 0; /* * Accept "git checkout foo" and "git checkout foo --" diff --git a/builtin/clean.c b/builtin/clean.c index d7acb94a95..0371010afb 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -147,30 +147,6 @@ static int exclude_cb(const struct option *opt, const char *arg, int unset) return 0; } -/* - * Return 1 if the given path is the root of a git repository or - * submodule else 0. Will not return 1 for bare repositories with the - * exception of creating a bare repository in "foo/.git" and calling - * is_git_repository("foo"). - */ -static int is_git_repository(struct strbuf *path) -{ - int ret = 0; - int gitfile_error; - size_t orig_path_len = path->len; - assert(orig_path_len != 0); - strbuf_complete(path, '/'); - strbuf_addstr(path, ".git"); - if (read_gitfile_gently(path->buf, &gitfile_error) || is_git_directory(path->buf)) - ret = 1; - if (gitfile_error == READ_GITFILE_ERR_OPEN_FAILED || - gitfile_error == READ_GITFILE_ERR_READ_FAILED) - ret = 1; /* This could be a real .git file, take the - * safe option and avoid cleaning */ - strbuf_setlen(path, orig_path_len); - return ret; -} - static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, int dry_run, int quiet, int *dir_gone) { @@ -182,7 +158,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, *dir_gone = 1; - if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_git_repository(path)) { + if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_nonbare_repository_dir(path)) { if (!quiet) { quote_path_relative(path->buf, prefix, "ed); printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir), @@ -567,7 +543,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff) int eof = 0; int i; - chosen = xmalloc(sizeof(int) * stuff->nr); + ALLOC_ARRAY(chosen, stuff->nr); /* set chosen as uninitialized */ for (i = 0; i < stuff->nr; i++) chosen[i] = -1; @@ -594,7 +570,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff) clean_get_color(CLEAN_COLOR_RESET)); } - if (strbuf_getline(&choice, stdin, '\n') != EOF) { + if (strbuf_getline_lf(&choice, stdin) != EOF) { strbuf_trim(&choice); } else { eof = 1; @@ -639,7 +615,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff) nr += chosen[i]; } - result = xcalloc(nr + 1, sizeof(int)); + result = xcalloc(st_add(nr, 1), sizeof(int)); for (i = 0; i < stuff->nr && j < nr; i++) { if (chosen[i]) result[j++] = i; @@ -676,7 +652,7 @@ static int filter_by_patterns_cmd(void) clean_print_color(CLEAN_COLOR_PROMPT); printf(_("Input ignore patterns>> ")); clean_print_color(CLEAN_COLOR_RESET); - if (strbuf_getline(&confirm, stdin, '\n') != EOF) + if (strbuf_getline_lf(&confirm, stdin) != EOF) strbuf_trim(&confirm); else putchar('\n'); @@ -774,7 +750,7 @@ static int ask_each_cmd(void) qname = quote_path_relative(item->string, NULL, &buf); /* TRANSLATORS: Make sure to keep [y/N] as is */ printf(_("Remove %s [y/N]? "), qname); - if (strbuf_getline(&confirm, stdin, '\n') != EOF) { + if (strbuf_getline_lf(&confirm, stdin) != EOF) { strbuf_trim(&confirm); } else { putchar('\n'); diff --git a/builtin/clone.c b/builtin/clone.c index b004fb4e00..6576ecf343 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -47,6 +47,7 @@ static const char *real_git_dir; static char *option_upload_pack = "git-upload-pack"; static int option_verbosity; static int option_progress = -1; +static enum transport_family family; static struct string_list option_config; static struct string_list option_reference; static int option_dissociate; @@ -95,6 +96,10 @@ static struct option builtin_clone_options[] = { N_("separate git dir from working tree")), OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), N_("set config inside the new repository")), + OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), + TRANSPORT_FAMILY_IPV4), + OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), + TRANSPORT_FAMILY_IPV6), OPT_END() }; @@ -230,8 +235,8 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare) strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git"); if (!len || (len == 1 && *start == '/')) - die("No directory name could be guessed.\n" - "Please specify a directory on the command line"); + die(_("No directory name could be guessed.\n" + "Please specify a directory on the command line")); if (is_bare) dir = xstrfmt("%.*s.git", (int)len, start); @@ -338,7 +343,7 @@ static void copy_alternates(struct strbuf *src, struct strbuf *dst, FILE *in = fopen(src->buf, "r"); struct strbuf line = STRBUF_INIT; - while (strbuf_getline(&line, in, '\n') != EOF) { + while (strbuf_getline(&line, in) != EOF) { char *abs_path; if (!line.len || line.buf[0] == '#') continue; @@ -635,9 +640,11 @@ static void update_remote_refs(const struct ref *refs, struct strbuf head_ref = STRBUF_INIT; strbuf_addstr(&head_ref, branch_top); strbuf_addstr(&head_ref, "HEAD"); - create_symref(head_ref.buf, - remote_head_points_at->peer_ref->name, - msg); + if (create_symref(head_ref.buf, + remote_head_points_at->peer_ref->name, + msg) < 0) + die(_("unable to update %s"), head_ref.buf); + strbuf_release(&head_ref); } } @@ -647,7 +654,8 @@ static void update_head(const struct ref *our, const struct ref *remote, const char *head; if (our && skip_prefix(our->name, "refs/heads/", &head)) { /* Local default branch link */ - create_symref("HEAD", our->name, NULL); + if (create_symref("HEAD", our->name, NULL) < 0) + die(_("unable to update HEAD")); if (!option_bare) { update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); @@ -739,7 +747,7 @@ static int checkout(void) static int write_one_config(const char *key, const char *value, void *data) { - return git_config_set_multivar(key, value ? value : "true", "^$", 0); + return git_config_set_multivar_gently(key, value ? value : "true", "^$", 0); } static void write_config(struct string_list *config) @@ -749,7 +757,7 @@ static void write_config(struct string_list *config) for (i = 0; i < config->nr; i++) { if (git_config_parse_parameter(config->items[i].string, write_one_config, NULL) < 0) - die("unable to write parameters to config file"); + die(_("unable to write parameters to config file")); } } @@ -974,6 +982,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) remote = remote_get(option_origin); transport = transport_get(remote, remote->url[0]); transport_set_verbosity(transport, option_verbosity, option_progress); + transport->family = family; path = get_repo_path(remote->url[0], &is_bundle); is_local = option_local != 0 && path && !is_bundle; diff --git a/builtin/column.c b/builtin/column.c index 449413c8a8..33314b4d71 100644 --- a/builtin/column.c +++ b/builtin/column.c @@ -51,7 +51,7 @@ int cmd_column(int argc, const char **argv, const char *prefix) die(_("--command must be the first argument")); } finalize_colopts(&colopts, -1); - while (!strbuf_getline(&sb, stdin, '\n')) + while (!strbuf_getline(&sb, stdin)) string_list_append(&list, sb.buf); print_columns(&list, colopts, &copts); diff --git a/builtin/commit.c b/builtin/commit.c index d054f84960..b3bd2d4181 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -761,7 +761,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, hook_arg2 = ""; } - s->fp = fopen(git_path(commit_editmsg), "w"); + s->fp = fopen_for_writing(git_path(commit_editmsg)); if (s->fp == NULL) die_errno(_("could not open '%s'"), git_path(commit_editmsg)); @@ -1690,7 +1690,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (fp == NULL) die_errno(_("could not open '%s' for reading"), git_path_merge_head()); - while (strbuf_getline(&m, fp, '\n') != EOF) { + while (strbuf_getline_lf(&m, fp) != EOF) { struct commit *parent; parent = get_merge_parent(m.buf); diff --git a/builtin/config.c b/builtin/config.c index adc772786a..ca9f834ae6 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -3,6 +3,7 @@ #include "color.h" #include "parse-options.h" #include "urlmatch.h" +#include "quote.h" static const char *const builtin_config_usage[] = { N_("git config [<options>]"), @@ -27,6 +28,7 @@ static int actions, types; static const char *get_color_slot, *get_colorbool_slot; static int end_null; static int respect_includes = -1; +static int show_origin; #define ACTION_GET (1<<0) #define ACTION_GET_ALL (1<<1) @@ -81,6 +83,7 @@ static struct option builtin_config_options[] = { OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")), OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")), OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")), + OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")), OPT_END(), }; @@ -91,8 +94,28 @@ static void check_argc(int argc, int min, int max) { usage_with_options(builtin_config_usage, builtin_config_options); } +static void show_config_origin(struct strbuf *buf) +{ + const char term = end_null ? '\0' : '\t'; + + strbuf_addstr(buf, current_config_origin_type()); + strbuf_addch(buf, ':'); + if (end_null) + strbuf_addstr(buf, current_config_name()); + else + quote_c_style(current_config_name(), buf, NULL, 0); + strbuf_addch(buf, term); +} + static int show_all_config(const char *key_, const char *value_, void *cb) { + if (show_origin) { + struct strbuf buf = STRBUF_INIT; + show_config_origin(&buf); + /* Use fwrite as "buf" can contain \0's if "end_null" is set. */ + fwrite(buf.buf, 1, buf.len, stdout); + strbuf_release(&buf); + } if (!omit_values && value_) printf("%s%c%s%c", key_, delim, value_, term); else @@ -108,6 +131,8 @@ struct strbuf_list { static int format_config(struct strbuf *buf, const char *key_, const char *value_) { + if (show_origin) + show_config_origin(buf); if (show_keys) strbuf_addstr(buf, key_); if (!omit_values) { @@ -352,6 +377,9 @@ static int get_colorbool(const char *var, int print) static void check_write(void) { + if (!given_config_source.file && !startup_info->have_repository) + die("not in a git directory"); + if (given_config_source.use_stdin) die("writing to stdin is not supported"); @@ -538,6 +566,14 @@ int cmd_config(int argc, const char **argv, const char *prefix) error("--name-only is only applicable to --list or --get-regexp"); usage_with_options(builtin_config_usage, builtin_config_options); } + + if (show_origin && !(actions & + (ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) { + error("--show-origin is only applicable to --get, --get-all, " + "--get-regexp, and --list."); + usage_with_options(builtin_config_usage, builtin_config_options); + } + if (actions == ACTION_LIST) { check_argc(argc, 0, 0); if (git_config_with_options(show_all_config, NULL, @@ -582,7 +618,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) check_write(); check_argc(argc, 2, 2); value = normalize_value(argv[0], argv[1]); - ret = git_config_set_in_file(given_config_source.file, argv[0], value); + ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value); if (ret == CONFIG_NOTHING_SET) error("cannot overwrite multiple values with a single value\n" " Use a regexp, --add or --replace-all to change %s.", argv[0]); @@ -592,23 +628,23 @@ int cmd_config(int argc, const char **argv, const char *prefix) check_write(); check_argc(argc, 2, 3); value = normalize_value(argv[0], argv[1]); - return git_config_set_multivar_in_file(given_config_source.file, - argv[0], value, argv[2], 0); + return git_config_set_multivar_in_file_gently(given_config_source.file, + argv[0], value, argv[2], 0); } else if (actions == ACTION_ADD) { check_write(); check_argc(argc, 2, 2); value = normalize_value(argv[0], argv[1]); - return git_config_set_multivar_in_file(given_config_source.file, - argv[0], value, - CONFIG_REGEX_NONE, 0); + return git_config_set_multivar_in_file_gently(given_config_source.file, + argv[0], value, + CONFIG_REGEX_NONE, 0); } else if (actions == ACTION_REPLACE_ALL) { check_write(); check_argc(argc, 2, 3); value = normalize_value(argv[0], argv[1]); - return git_config_set_multivar_in_file(given_config_source.file, - argv[0], value, argv[2], 1); + return git_config_set_multivar_in_file_gently(given_config_source.file, + argv[0], value, argv[2], 1); } else if (actions == ACTION_GET) { check_argc(argc, 1, 2); @@ -634,17 +670,17 @@ int cmd_config(int argc, const char **argv, const char *prefix) check_write(); check_argc(argc, 1, 2); if (argc == 2) - return git_config_set_multivar_in_file(given_config_source.file, - argv[0], NULL, argv[1], 0); + return git_config_set_multivar_in_file_gently(given_config_source.file, + argv[0], NULL, argv[1], 0); else - return git_config_set_in_file(given_config_source.file, - argv[0], NULL); + return git_config_set_in_file_gently(given_config_source.file, + argv[0], NULL); } else if (actions == ACTION_UNSET_ALL) { check_write(); check_argc(argc, 1, 2); - return git_config_set_multivar_in_file(given_config_source.file, - argv[0], NULL, argv[1], 1); + return git_config_set_multivar_in_file_gently(given_config_source.file, + argv[0], NULL, argv[1], 1); } else if (actions == ACTION_RENAME_SECTION) { int ret; diff --git a/builtin/diff.c b/builtin/diff.c index ed0acca91f..52c98a9217 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -341,7 +341,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) } if (no_index) /* If this is a no-index diff, just run it and exit there. */ - diff_no_index(&rev, argc, argv, prefix); + diff_no_index(&rev, argc, argv); /* Otherwise, we are doing the usual "git" diff */ rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; diff --git a/builtin/fast-export.c b/builtin/fast-export.c index d9ac5d8410..8164b581a6 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -880,7 +880,7 @@ static void export_marks(char *file) FILE *f; int e = 0; - f = fopen(file, "w"); + f = fopen_for_writing(file); if (!f) die_errno("Unable to open marks file %s for writing.", file); @@ -1021,7 +1021,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) const char **refspecs_str; int i; - refspecs_str = xmalloc(sizeof(*refspecs_str) * refspecs_list.nr); + ALLOC_ARRAY(refspecs_str, refspecs_list.nr); for (i = 0; i < refspecs_list.nr; i++) refspecs_str[i] = refspecs_list.items[i].string; diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index cf3019e05b..79a611fda1 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -10,33 +10,24 @@ static const char fetch_pack_usage[] = "[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] " "[--no-progress] [--diag-url] [-v] [<host>:]<directory> [<refs>...]"; -static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc, - const char *name, int namelen) +static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, + const char *name) { - struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1); + struct ref *ref; struct object_id oid; - const int chunksz = GIT_SHA1_HEXSZ + 1; - if (namelen > chunksz && name[chunksz - 1] == ' ' && - !get_oid_hex(name, &oid)) { - oidcpy(&ref->old_oid, &oid); - name += chunksz; - namelen -= chunksz; - } + if (!get_oid_hex(name, &oid) && name[GIT_SHA1_HEXSZ] == ' ') + name += GIT_SHA1_HEXSZ + 1; + else + oidclr(&oid); - memcpy(ref->name, name, namelen); - ref->name[namelen] = '\0'; + ref = alloc_ref(name); + oidcpy(&ref->old_oid, &oid); (*nr)++; ALLOC_GROW(*sought, *nr, *alloc); (*sought)[*nr - 1] = ref; } -static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, - const char *string) -{ - add_sought_entry_mem(sought, nr, alloc, string, strlen(string)); -} - int cmd_fetch_pack(int argc, const char **argv, const char *prefix) { int i, ret; @@ -158,7 +149,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) else { /* read from stdin one ref per line, until EOF */ struct strbuf line = STRBUF_INIT; - while (strbuf_getline(&line, stdin, '\n') != EOF) + while (strbuf_getline_lf(&line, stdin) != EOF) add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf); strbuf_release(&line); } diff --git a/builtin/fetch.c b/builtin/fetch.c index 5aa1c2de44..f8455bde7a 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -38,6 +38,7 @@ static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosit static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; static int tags = TAGS_DEFAULT, unshallow, update_shallow; static int max_children = -1; +static enum transport_family family; static const char *depth; static const char *upload_pack; static struct strbuf default_rla = STRBUF_INIT; @@ -127,6 +128,10 @@ static struct option builtin_fetch_options[] = { N_("accept refs that update .git/shallow")), { OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"), N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg }, + OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), + TRANSPORT_FAMILY_IPV4), + OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), + TRANSPORT_FAMILY_IPV6), OPT_END() }; @@ -840,7 +845,7 @@ static void check_not_current_branch(struct ref *ref_map) static int truncate_fetch_head(void) { const char *filename = git_path_fetch_head(); - FILE *fp = fopen(filename, "w"); + FILE *fp = fopen_for_writing(filename); if (!fp) return error(_("cannot open %s: %s\n"), filename, strerror(errno)); @@ -864,6 +869,7 @@ static struct transport *prepare_transport(struct remote *remote) struct transport *transport; transport = transport_get(remote, NULL); transport_set_verbosity(transport, verbosity, progress); + transport->family = family; if (upload_pack) set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack); if (keep) @@ -1016,10 +1022,9 @@ static int add_remote_or_group(const char *name, struct string_list *list) git_config(get_remote_group, &g); if (list->nr == prev_nr) { - struct remote *remote; - if (!remote_is_configured(name)) + struct remote *remote = remote_get(name); + if (!remote_is_configured(remote)) return 0; - remote = remote_get(name); string_list_append(list, remote->name); } return 1; @@ -1110,7 +1115,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv) if (argc > 0) { int j = 0; int i; - refs = xcalloc(argc + 1, sizeof(const char *)); + refs = xcalloc(st_add(argc, 1), sizeof(const char *)); for (i = 0; i < argc; i++) { if (!strcmp(argv[i], "tag")) { i++; @@ -1225,6 +1230,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) list.strdup_strings = 1; string_list_clear(&list, 0); + close_all_packs(); + argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL); if (verbosity < 0) argv_array_push(&argv_gc_auto, "--quiet"); diff --git a/builtin/grep.c b/builtin/grep.c index 4229cae390..aa7435f380 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -24,11 +24,11 @@ static char const * const grep_usage[] = { NULL }; -static int use_threads = 1; +#define GREP_NUM_THREADS_DEFAULT 8 +static int num_threads; #ifndef NO_PTHREADS -#define THREADS 8 -static pthread_t threads[THREADS]; +static pthread_t *threads; /* We use one producer thread and THREADS consumer * threads. The producer adds struct work_items to 'todo' and the @@ -63,13 +63,13 @@ static pthread_mutex_t grep_mutex; static inline void grep_lock(void) { - if (use_threads) + if (num_threads) pthread_mutex_lock(&grep_mutex); } static inline void grep_unlock(void) { - if (use_threads) + if (num_threads) pthread_mutex_unlock(&grep_mutex); } @@ -206,7 +206,8 @@ static void start_threads(struct grep_opt *opt) strbuf_init(&todo[i].out, 0); } - for (i = 0; i < ARRAY_SIZE(threads); i++) { + threads = xcalloc(num_threads, sizeof(*threads)); + for (i = 0; i < num_threads; i++) { int err; struct grep_opt *o = grep_opt_dup(opt); o->output = strbuf_out; @@ -238,12 +239,14 @@ static int wait_all(void) pthread_cond_broadcast(&cond_add); grep_unlock(); - for (i = 0; i < ARRAY_SIZE(threads); i++) { + for (i = 0; i < num_threads; i++) { void *h; pthread_join(threads[i], &h); hit |= (int) (intptr_t) h; } + free(threads); + pthread_mutex_destroy(&grep_mutex); pthread_mutex_destroy(&grep_read_mutex); pthread_mutex_destroy(&grep_attr_mutex); @@ -267,6 +270,14 @@ static int grep_cmd_config(const char *var, const char *value, void *cb) int st = grep_config(var, value, cb); if (git_color_default_config(var, value, cb) < 0) st = -1; + + if (!strcmp(var, "grep.threads")) { + num_threads = git_config_int(var, value); + if (num_threads < 0) + die(_("invalid number of threads specified (%d) for %s"), + num_threads, var); + } + return st; } @@ -294,7 +305,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, } #ifndef NO_PTHREADS - if (use_threads) { + if (num_threads) { add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1); strbuf_release(&pathbuf); return 0; @@ -323,7 +334,7 @@ static int grep_file(struct grep_opt *opt, const char *filename) strbuf_addstr(&buf, filename); #ifndef NO_PTHREADS - if (use_threads) { + if (num_threads) { add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename); strbuf_release(&buf); return 0; @@ -354,17 +365,17 @@ static void append_path(struct grep_opt *opt, const void *data, size_t len) static void run_pager(struct grep_opt *opt, const char *prefix) { struct string_list *path_list = opt->output_priv; - const char **argv = xmalloc(sizeof(const char *) * (path_list->nr + 1)); + struct child_process child = CHILD_PROCESS_INIT; int i, status; for (i = 0; i < path_list->nr; i++) - argv[i] = path_list->items[i].string; - argv[path_list->nr] = NULL; + argv_array_push(&child.args, path_list->items[i].string); + child.dir = prefix; + child.use_shell = 1; - status = run_command_v_opt_cd_env(argv, RUN_USING_SHELL, prefix, NULL); + status = run_command(&child); if (status) exit(status); - free(argv); } static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int cached) @@ -375,7 +386,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int for (nr = 0; nr < active_nr; nr++) { const struct cache_entry *ce = active_cache[nr]; - if (!S_ISREG(ce->ce_mode)) + if (!S_ISREG(ce->ce_mode) || ce_intent_to_add(ce)) continue; if (!ce_path_match(ce, pathspec, NULL)) continue; @@ -562,7 +573,7 @@ static int file_callback(const struct option *opt, const char *arg, int unset) patterns = from_stdin ? stdin : fopen(arg, "r"); if (!patterns) die_errno(_("cannot open '%s'"), arg); - while (strbuf_getline(&sb, patterns, '\n') == 0) { + while (strbuf_getline(&sb, patterns) == 0) { /* ignore empty line like grep does */ if (sb.len == 0) continue; @@ -697,6 +708,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) N_("show <n> context lines before matches")), OPT_INTEGER('A', "after-context", &opt.post_context, N_("show <n> context lines after matches")), + OPT_INTEGER(0, "threads", &num_threads, + N_("use <n> worker threads")), OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"), context_callback), OPT_BOOL('p', "show-function", &opt.funcname, @@ -755,9 +768,15 @@ int cmd_grep(int argc, const char **argv, const char *prefix) PARSE_OPT_STOP_AT_NON_OPTION); grep_commit_pattern_type(pattern_type_arg, &opt); - if (use_index && !startup_info->have_repository) - /* die the same way as if we did it at the beginning */ - setup_git_directory(); + if (use_index && !startup_info->have_repository) { + int fallback = 0; + git_config_get_bool("grep.fallbacktonoindex", &fallback); + if (fallback) + use_index = 0; + else + /* die the same way as if we did it at the beginning */ + setup_git_directory(); + } /* * skip a -- separator; we know it cannot be @@ -786,7 +805,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) opt.output_priv = &path_list; opt.output = append_path; string_list_append(&path_list, show_in_pager); - use_threads = 0; } if (!opt.pattern_list) @@ -817,14 +835,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix) } #ifndef NO_PTHREADS - if (list.nr || cached || online_cpus() == 1) - use_threads = 0; + if (list.nr || cached || show_in_pager) + num_threads = 0; + else if (num_threads == 0) + num_threads = GREP_NUM_THREADS_DEFAULT; + else if (num_threads < 0) + die(_("invalid number of threads specified (%d)"), num_threads); #else - use_threads = 0; + num_threads = 0; #endif #ifndef NO_PTHREADS - if (use_threads) { + if (num_threads) { if (!(opt.name_only || opt.unmatch_name_only || opt.count) && (opt.pre_context || opt.post_context || opt.file_break || opt.funcbody)) @@ -894,7 +916,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) hit = grep_objects(&opt, &pathspec, &list); } - if (use_threads) + if (num_threads) hit |= wait_all(); if (hit && show_in_pager) run_pager(&opt, prefix); diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 43b098b76c..f7d3567dd0 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -58,20 +58,21 @@ static void hash_object(const char *path, const char *type, const char *vpath, static void hash_stdin_paths(const char *type, int no_filters, unsigned flags, int literally) { - struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; + struct strbuf unquoted = STRBUF_INIT; - while (strbuf_getline(&buf, stdin, '\n') != EOF) { + while (strbuf_getline(&buf, stdin) != EOF) { if (buf.buf[0] == '"') { - strbuf_reset(&nbuf); - if (unquote_c_style(&nbuf, buf.buf, NULL)) + strbuf_reset(&unquoted); + if (unquote_c_style(&unquoted, buf.buf, NULL)) die("line is badly quoted"); - strbuf_swap(&buf, &nbuf); + strbuf_swap(&buf, &unquoted); } hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags, literally); } strbuf_release(&buf); - strbuf_release(&nbuf); + strbuf_release(&unquoted); } int cmd_hash_object(int argc, const char **argv, const char *prefix) diff --git a/builtin/help.c b/builtin/help.c index 1cd0c1ee44..3c55ce4563 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -171,12 +171,10 @@ static void exec_man_cmd(const char *cmd, const char *page) static void add_man_viewer(const char *name) { struct man_viewer_list **p = &man_viewer_list; - size_t len = strlen(name); while (*p) p = &((*p)->next); - *p = xcalloc(1, (sizeof(**p) + len + 1)); - memcpy((*p)->name, name, len); /* NUL-terminated by xcalloc */ + FLEX_ALLOC_STR(*p, name, name); } static int supported_man_viewer(const char *name, size_t len) @@ -190,9 +188,8 @@ static void do_add_man_viewer_info(const char *name, size_t len, const char *value) { - struct man_viewer_info_list *new = xcalloc(1, sizeof(*new) + len + 1); - - memcpy(new->name, name, len); /* NUL-terminated by xcalloc */ + struct man_viewer_info_list *new; + FLEX_ALLOC_MEM(new, name, name, len); new->info = xstrdup(value); new->next = man_viewer_info_list; man_viewer_info_list = new; diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 6a01509587..45245199ae 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1346,7 +1346,7 @@ static void fix_unresolved_deltas(struct sha1file *f) * before deltas depending on them, a good heuristic is to start * resolving deltas in the same order as their position in the pack. */ - sorted_by_pos = xmalloc(nr_ref_deltas * sizeof(*sorted_by_pos)); + ALLOC_ARRAY(sorted_by_pos, nr_ref_deltas); for (i = 0; i < nr_ref_deltas; i++) sorted_by_pos[i] = &ref_deltas[i]; qsort(sorted_by_pos, nr_ref_deltas, sizeof(*sorted_by_pos), delta_pos_compare); @@ -1514,6 +1514,7 @@ static void read_v2_anomalous_offsets(struct packed_git *p, if (!(off & 0x80000000)) continue; off = off & 0x7fffffff; + check_pack_index_ptr(p, &idx2[off * 2]); if (idx2[off * 2]) continue; /* @@ -1744,9 +1745,9 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) curr_pack = open_pack_file(pack_name); parse_pack_header(); - objects = xcalloc(nr_objects + 1, sizeof(struct object_entry)); + objects = xcalloc(st_add(nr_objects, 1), sizeof(struct object_entry)); if (show_stat) - obj_stat = xcalloc(nr_objects + 1, sizeof(struct object_stat)); + obj_stat = xcalloc(st_add(nr_objects, 1), sizeof(struct object_stat)); ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry)); parse_pack_objects(pack_sha1); resolve_deltas(); @@ -1759,7 +1760,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (show_stat) show_pack_info(stat_only); - idx_objects = xmalloc((nr_objects) * sizeof(struct pack_idx_entry *)); + ALLOC_ARRAY(idx_objects, nr_objects); for (i = 0; i < nr_objects; i++) idx_objects[i] = &objects[i].idx; curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_sha1); diff --git a/builtin/init-db.c b/builtin/init-db.c index 07229d60f1..6223b7d46a 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -250,7 +250,7 @@ static int create_default_files(const char *template_path) git_config_set("core.bare", "false"); /* allow template config file to override the default */ if (log_all_ref_updates == -1) - git_config_set("core.logallrefupdates", "true"); + git_config_set("core.logallrefupdates", "true"); if (needs_work_tree_config(get_git_dir(), work_tree)) git_config_set("core.worktree", work_tree); } diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 46838d24a9..b99ae4be88 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -12,16 +12,18 @@ #include "trailer.h" static const char * const git_interpret_trailers_usage[] = { - N_("git interpret-trailers [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]"), + N_("git interpret-trailers [--in-place] [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]"), NULL }; 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_DUP; 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")), @@ -34,9 +36,12 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) if (argc) { int i; for (i = 0; i < argc; i++) - process_trailers(argv[i], trim_empty, &trailers); - } else - process_trailers(NULL, trim_empty, &trailers); + process_trailers(argv[i], in_place, trim_empty, &trailers); + } else { + if (in_place) + die(_("no input file given for in-place editing")); + process_trailers(NULL, in_place, trim_empty, &trailers); + } string_list_clear(&trailers, 0); diff --git a/builtin/log.c b/builtin/log.c index 069bd3a909..0d738d6ddc 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -699,6 +699,7 @@ static int do_signoff; static const char *signature = git_version_string; static const char *signature_file; static int config_cover_letter; +static const char *config_output_directory; enum { COVER_UNSET, @@ -777,6 +778,8 @@ static int git_format_config(const char *var, const char *value, void *cb) config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF; return 0; } + if (!strcmp(var, "format.outputdirectory")) + return git_config_string(&config_output_directory, var, value); return git_log_config(var, value, cb); } @@ -1196,6 +1199,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int cover_letter = -1; int boundary_count = 0; int no_binary_diff = 0; + int zero_commit = 0; struct commit *origin = NULL; const char *in_reply_to = NULL; struct patch_ids ids; @@ -1236,6 +1240,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback }, OPT_BOOL(0, "no-binary", &no_binary_diff, N_("don't output binary diffs")), + OPT_BOOL(0, "zero-commit", &zero_commit, + N_("output all-zero hash in From header")), OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream, N_("don't include a patch matching a commit upstream")), { OPTION_SET_INT, 'p', "no-stat", &use_patch_format, NULL, @@ -1380,12 +1386,17 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* Always generate a patch */ rev.diffopt.output_format |= DIFF_FORMAT_PATCH; + rev.zero_commit = zero_commit; + if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff) DIFF_OPT_SET(&rev.diffopt, BINARY); if (rev.show_notes) init_display_notes(&rev.notes_opt); + if (!output_directory && !use_stdout) + output_directory = config_output_directory; + if (!use_stdout) output_directory = set_outdir(prefix, output_directory); else diff --git a/builtin/ls-files.c b/builtin/ls-files.c index b6a7cb0c7c..f02e3d23bb 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -27,6 +27,7 @@ static int show_killed; static int show_valid_bit; static int line_terminator = '\n'; static int debug_mode; +static int show_eol; static const char *prefix; static int max_prefix_len; @@ -47,6 +48,23 @@ static const char *tag_modified = ""; static const char *tag_skip_worktree = ""; static const char *tag_resolve_undo = ""; +static void write_eolinfo(const struct cache_entry *ce, const char *path) +{ + if (!show_eol) + return; + else { + struct stat st; + const char *i_txt = ""; + const char *w_txt = ""; + const char *a_txt = get_convert_attr_ascii(path); + if (ce && S_ISREG(ce->ce_mode)) + i_txt = get_cached_convert_stats_ascii(ce->name); + if (!lstat(path, &st) && S_ISREG(st.st_mode)) + w_txt = get_wt_convert_stats_ascii(path); + printf("i/%-5s w/%-5s attr/%-17s\t", i_txt, w_txt, a_txt); + } +} + static void write_name(const char *name) { /* @@ -68,6 +86,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent) return; fputs(tag, stdout); + write_eolinfo(NULL, ent->name); write_name(ent->name); } @@ -170,6 +189,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce) find_unique_abbrev(ce->sha1,abbrev), ce_stage(ce)); } + write_eolinfo(ce, ce->name); write_name(ce->name); if (debug_mode) { const struct stat_data *sd = &ce->ce_stat_data; @@ -359,14 +379,6 @@ static const char * const ls_files_usage[] = { NULL }; -static int option_parse_z(const struct option *opt, - const char *arg, int unset) -{ - line_terminator = unset ? '\n' : '\0'; - - return 0; -} - static int option_parse_exclude(const struct option *opt, const char *arg, int unset) { @@ -408,9 +420,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) struct exclude_list *el; struct string_list exclude_list = STRING_LIST_INIT_NODUP; struct option builtin_ls_files_options[] = { - { OPTION_CALLBACK, 'z', NULL, NULL, NULL, - N_("paths are separated with NUL character"), - PARSE_OPT_NOARG, option_parse_z }, + /* Think twice before adding "--nul" synonym to this */ + OPT_SET_INT('z', NULL, &line_terminator, + N_("paths are separated with NUL character"), '\0'), OPT_BOOL('t', NULL, &show_tag, N_("identify the file status with tags")), OPT_BOOL('v', NULL, &show_valid_bit, @@ -433,6 +445,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) OPT_BIT(0, "directory", &dir.flags, N_("show 'other' directories' names only"), DIR_SHOW_OTHER_DIRECTORIES), + OPT_BOOL(0, "eol", &show_eol, N_("show line endings of files")), OPT_NEGBIT(0, "empty-directory", &dir.flags, N_("don't show empty directories"), DIR_HIDE_EMPTY_DIRECTORIES), diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index fa65a8448a..66cdd45cc1 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -3,9 +3,12 @@ #include "transport.h" #include "remote.h" -static const char ls_remote_usage[] = -"git ls-remote [--heads] [--tags] [--upload-pack=<exec>]\n" -" [-q | --quiet] [--exit-code] [--get-url] [<repository> [<refs>...]]"; +static const char * const ls_remote_usage[] = { + N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" + " [-q | --quiet] [--exit-code] [--get-url]\n" + " [--symref] [<repository> [<refs>...]]"), + NULL +}; /* * Is there one among the list of patterns that match the tail part @@ -30,12 +33,12 @@ static int tail_match(const char **pattern, const char *path) int cmd_ls_remote(int argc, const char **argv, const char *prefix) { - int i; const char *dest = NULL; unsigned flags = 0; int get_url = 0; int quiet = 0; int status = 0; + int show_symref_target = 0; const char *uploadpack = NULL; const char **pattern = NULL; @@ -43,59 +46,36 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) struct transport *transport; const struct ref *ref; - if (argc == 2 && !strcmp("-h", argv[1])) - usage(ls_remote_usage); + struct option options[] = { + OPT__QUIET(&quiet, N_("do not print remote URL")), + OPT_STRING(0, "upload-pack", &uploadpack, N_("exec"), + N_("path of git-upload-pack on the remote host")), + { OPTION_STRING, 0, "exec", &uploadpack, N_("exec"), + N_("path of git-upload-pack on the remote host"), + PARSE_OPT_HIDDEN }, + OPT_BIT('t', "tags", &flags, N_("limit to tags"), REF_TAGS), + OPT_BIT('h', "heads", &flags, N_("limit to heads"), REF_HEADS), + OPT_BIT(0, "refs", &flags, N_("do not show peeled tags"), REF_NORMAL), + OPT_BOOL(0, "get-url", &get_url, + N_("take url.<base>.insteadOf into account")), + OPT_SET_INT(0, "exit-code", &status, + N_("exit with exit code 2 if no matching refs are found"), 2), + OPT_BOOL(0, "symref", &show_symref_target, + N_("show underlying ref in addition to the object pointed by it")), + OPT_END() + }; - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; + argc = parse_options(argc, argv, prefix, options, ls_remote_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + dest = argv[0]; - if (*arg == '-') { - if (starts_with(arg, "--upload-pack=")) { - uploadpack = arg + 14; - continue; - } - if (starts_with(arg, "--exec=")) { - uploadpack = arg + 7; - continue; - } - if (!strcmp("--tags", arg) || !strcmp("-t", arg)) { - flags |= REF_TAGS; - continue; - } - if (!strcmp("--heads", arg) || !strcmp("-h", arg)) { - flags |= REF_HEADS; - continue; - } - if (!strcmp("--refs", arg)) { - flags |= REF_NORMAL; - continue; - } - if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) { - quiet = 1; - continue; - } - if (!strcmp("--get-url", arg)) { - get_url = 1; - continue; - } - if (!strcmp("--exit-code", arg)) { - /* return this code if no refs are reported */ - status = 2; - continue; - } - usage(ls_remote_usage); - } - dest = arg; - i++; - break; + if (argc > 1) { + int i; + pattern = xcalloc(argc, sizeof(const char *)); + for (i = 1; i < argc; i++) + pattern[i - 1] = xstrfmt("*/%s", argv[i]); } - if (argv[i]) { - int j; - pattern = xcalloc(argc - i + 1, sizeof(const char *)); - for (j = i; j < argc; j++) - pattern[j - i] = xstrfmt("*/%s", argv[j]); - } remote = remote_get(dest); if (!remote) { if (dest) @@ -125,7 +105,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) continue; if (!tail_match(pattern, ref->name)) continue; - printf("%s %s\n", oid_to_hex(&ref->old_oid), ref->name); + if (show_symref_target && ref->symref) + printf("ref: %s\t%s\n", ref->symref, ref->name); + printf("%s\t%s\n", oid_to_hex(&ref->old_oid), ref->name); status = 0; /* we found something */ } return status; diff --git a/builtin/merge-base.c b/builtin/merge-base.c index a8911626c2..c0d1822eb3 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -252,7 +252,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix) if (argc < 2) usage_with_options(merge_base_usage, options); - rev = xmalloc(argc * sizeof(*rev)); + ALLOC_ARRAY(rev, argc); while (argc-- > 0) rev[rev_nr++] = get_commit_reference(*argv++); return show_merge_base(rev, rev_nr, show_all); diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index d4f0cbd451..ca570041df 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -174,7 +174,7 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsi static char *traverse_path(const struct traverse_info *info, const struct name_entry *n) { - char *path = xmalloc(traverse_path_len(info, n) + 1); + char *path = xmallocz(traverse_path_len(info, n)); return make_traverse_path(path, info, n); } diff --git a/builtin/merge.c b/builtin/merge.c index 15bf95b3ac..101ffeff4c 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -404,6 +404,7 @@ static void finish(struct commit *head_commit, * We ignore errors in 'gc --auto', since the * user should see them. */ + close_all_packs(); run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); } } @@ -938,7 +939,7 @@ static int setup_with_upstream(const char ***argv) if (!branch->merge_nr) die(_("No default upstream defined for the current branch.")); - args = xcalloc(branch->merge_nr + 1, sizeof(char *)); + args = xcalloc(st_add(branch->merge_nr, 1), sizeof(char *)); for (i = 0; i < branch->merge_nr; i++) { if (!branch->merge[i]->dst) die(_("No remote-tracking branch for %s from %s"), diff --git a/builtin/mktree.c b/builtin/mktree.c index a964d6be52..4282b62c59 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -19,16 +19,17 @@ static int alloc, used; static void append_to_tree(unsigned mode, unsigned char *sha1, char *path) { struct treeent *ent; - int len = strlen(path); + size_t len = strlen(path); if (strchr(path, '/')) die("path %s contains slash", path); - ALLOC_GROW(entries, used + 1, alloc); - ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1); + FLEX_ALLOC_MEM(ent, name, path, len); ent->mode = mode; ent->len = len; hashcpy(ent->sha1, sha1); - memcpy(ent->name, path, len+1); + + ALLOC_GROW(entries, used + 1, alloc); + entries[used++] = ent; } static int ent_compare(const void *a_, const void *b_) @@ -65,7 +66,7 @@ static const char *mktree_usage[] = { NULL }; -static void mktree_line(char *buf, size_t len, int line_termination, int allow_missing) +static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_missing) { char *ptr, *ntr; unsigned mode; @@ -97,7 +98,7 @@ static void mktree_line(char *buf, size_t len, int line_termination, int allow_m *ntr++ = 0; /* now at the beginning of SHA1 */ path = ntr + 41; /* at the beginning of name */ - if (line_termination && path[0] == '"') { + if (!nul_term_line && path[0] == '"') { struct strbuf p_uq = STRBUF_INIT; if (unquote_c_style(&p_uq, path, NULL)) die("invalid quoting"); @@ -141,23 +142,25 @@ int cmd_mktree(int ac, const char **av, const char *prefix) { struct strbuf sb = STRBUF_INIT; unsigned char sha1[20]; - int line_termination = '\n'; + int nul_term_line = 0; int allow_missing = 0; int is_batch_mode = 0; int got_eof = 0; + strbuf_getline_fn getline_fn; const struct option option[] = { - OPT_SET_INT('z', NULL, &line_termination, N_("input is NUL terminated"), '\0'), + OPT_BOOL('z', NULL, &nul_term_line, N_("input is NUL terminated")), OPT_SET_INT( 0 , "missing", &allow_missing, N_("allow missing objects"), 1), OPT_SET_INT( 0 , "batch", &is_batch_mode, N_("allow creation of more than one tree"), 1), OPT_END() }; ac = parse_options(ac, av, prefix, option, mktree_usage, 0); + getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf; while (!got_eof) { while (1) { - if (strbuf_getline(&sb, stdin, line_termination) == EOF) { + if (getline_fn(&sb, stdin) == EOF) { got_eof = 1; break; } @@ -167,7 +170,7 @@ int cmd_mktree(int ac, const char **av, const char *prefix) break; die("input format error: (blank line only valid in batch mode)"); } - mktree_line(sb.buf, sb.len, line_termination, allow_missing); + mktree_line(sb.buf, sb.len, nul_term_line, allow_missing); } if (is_batch_mode && got_eof && used < 1) { /* diff --git a/builtin/mv.c b/builtin/mv.c index d1d43168ae..aeae855e2b 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -24,7 +24,8 @@ static const char **internal_copy_pathspec(const char *prefix, int count, unsigned flags) { int i; - const char **result = xmalloc((count + 1) * sizeof(const char *)); + const char **result; + ALLOC_ARRAY(result, count + 1); memcpy(result, pathspec, count * sizeof(const char *)); result[count] = NULL; for (i = 0; i < count; i++) { @@ -47,9 +48,9 @@ static const char **internal_copy_pathspec(const char *prefix, static const char *add_slash(const char *path) { - int len = strlen(path); + size_t len = strlen(path); if (path[len - 1] != '/') { - char *with_slash = xmalloc(len + 2); + char *with_slash = xmalloc(st_add(len, 2)); memcpy(with_slash, path, len); with_slash[len++] = '/'; with_slash[len] = 0; diff --git a/builtin/notes.c b/builtin/notes.c index 52aa9af74b..ed6f2222f4 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -286,11 +286,11 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd) if (!c) return 0; } else { - init_notes(NULL, NULL, NULL, 0); + init_notes(NULL, NULL, NULL, NOTES_INIT_WRITABLE); t = &default_notes_tree; } - while (strbuf_getline(&buf, stdin, '\n') != EOF) { + while (strbuf_getline_lf(&buf, stdin) != EOF) { unsigned char from_obj[20], to_obj[20]; struct strbuf **split; int err; @@ -329,15 +329,18 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd) return ret; } -static struct notes_tree *init_notes_check(const char *subcommand) +static struct notes_tree *init_notes_check(const char *subcommand, + int flags) { struct notes_tree *t; - init_notes(NULL, NULL, NULL, 0); + const char *ref; + init_notes(NULL, NULL, NULL, flags); t = &default_notes_tree; - if (!starts_with(t->ref, "refs/notes/")) + ref = (flags & NOTES_INIT_WRITABLE) ? t->update_ref : t->ref; + if (!starts_with(ref, "refs/notes/")) die("Refusing to %s notes in %s (outside of refs/notes/)", - subcommand, t->ref); + subcommand, ref); return t; } @@ -360,7 +363,7 @@ static int list(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_list_usage, options); } - t = init_notes_check("list"); + t = init_notes_check("list", 0); if (argc) { if (get_sha1(argv[0], object)) die(_("Failed to resolve '%s' as a valid ref."), argv[0]); @@ -420,7 +423,7 @@ static int add(int argc, const char **argv, const char *prefix) if (get_sha1(object_ref, object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check("add"); + t = init_notes_check("add", NOTES_INIT_WRITABLE); note = get_note(t, object); if (note) { @@ -511,7 +514,7 @@ static int copy(int argc, const char **argv, const char *prefix) if (get_sha1(object_ref, object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check("copy"); + t = init_notes_check("copy", NOTES_INIT_WRITABLE); note = get_note(t, object); if (note) { @@ -589,7 +592,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) if (get_sha1(object_ref, object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check(argv[0]); + t = init_notes_check(argv[0], NOTES_INIT_WRITABLE); note = get_note(t, object); prepare_note_data(object, &d, edit ? note : NULL); @@ -652,7 +655,7 @@ static int show(int argc, const char **argv, const char *prefix) if (get_sha1(object_ref, object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check("show"); + t = init_notes_check("show", 0); note = get_note(t, object); if (!note) @@ -806,10 +809,10 @@ static int merge(int argc, const char **argv, const char *prefix) o.local_ref = default_notes_ref(); strbuf_addstr(&remote_ref, argv[0]); - expand_notes_ref(&remote_ref); + expand_loose_notes_ref(&remote_ref); o.remote_ref = remote_ref.buf; - t = init_notes_check("merge"); + t = init_notes_check("merge", NOTES_INIT_WRITABLE); if (strategy) { if (parse_notes_merge_strategy(strategy, &o.strategy)) { @@ -901,7 +904,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, git_notes_remove_usage, 0); - t = init_notes_check("remove"); + t = init_notes_check("remove", NOTES_INIT_WRITABLE); if (!argc && !from_stdin) { retval = remove_one_note(t, "HEAD", flag); @@ -943,7 +946,7 @@ static int prune(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_prune_usage, options); } - t = init_notes_check("prune"); + t = init_notes_check("prune", NOTES_INIT_WRITABLE); prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) | (show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) ); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 4dae5b11c2..a27de5b323 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -624,7 +624,7 @@ static struct object_entry **compute_write_order(void) { unsigned int i, wo_end, last_untagged; - struct object_entry **wo = xmalloc(to_pack.nr_objects * sizeof(*wo)); + struct object_entry **wo; struct object_entry *objects = to_pack.objects; for (i = 0; i < to_pack.nr_objects; i++) { @@ -657,6 +657,7 @@ static struct object_entry **compute_write_order(void) * Give the objects in the original recency order until * we see a tagged tip. */ + ALLOC_ARRAY(wo, to_pack.nr_objects); for (i = wo_end = 0; i < to_pack.nr_objects; i++) { if (objects[i].tagged) break; @@ -769,7 +770,7 @@ static void write_pack_file(void) if (progress > pack_to_stdout) progress_state = start_progress(_("Writing objects"), nr_result); - written_list = xmalloc(to_pack.nr_objects * sizeof(*written_list)); + ALLOC_ARRAY(written_list, to_pack.nr_objects); write_order = compute_write_order(); do { @@ -2129,7 +2130,7 @@ static void prepare_pack(int window, int depth) if (!to_pack.nr_objects || !window || !depth) return; - delta_list = xmalloc(to_pack.nr_objects * sizeof(*delta_list)); + ALLOC_ARRAY(delta_list, to_pack.nr_objects); nr_deltas = n = 0; for (i = 0; i < to_pack.nr_objects; i++) { @@ -2284,21 +2285,11 @@ static void show_commit(struct commit *commit, void *data) index_commit_for_bitmap(commit); } -static void show_object(struct object *obj, - const struct name_path *path, const char *last, - void *data) +static void show_object(struct object *obj, const char *name, void *data) { - char *name = path_name(path, last); - add_preferred_base_object(name); add_object_entry(obj->oid.hash, obj->type, name, 0); obj->flags |= OBJECT_ADDED; - - /* - * We will have generated the hash from the name, - * but not saved a pointer to it - we can free it - */ - free((char *)name); } static void show_edge(struct commit *commit) @@ -2480,8 +2471,7 @@ static int get_object_list_from_bitmap(struct rev_info *revs) } static void record_recent_object(struct object *obj, - const struct name_path *path, - const char *last, + const char *name, void *data) { sha1_array_append(&recent_objects, obj->oid.hash); diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index d0532f66b1..72c815844d 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -53,7 +53,7 @@ static inline struct llist_item *llist_item_get(void) free_nodes = free_nodes->next; } else { int i = 1; - new = xmalloc(sizeof(struct llist_item) * BLKSIZE); + ALLOC_ARRAY(new, BLKSIZE); for (; i < BLKSIZE; i++) llist_item_put(&new[i]); } diff --git a/builtin/pull.c b/builtin/pull.c index 9e3c73809f..10eff03967 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -22,7 +22,8 @@ enum rebase_type { REBASE_INVALID = -1, REBASE_FALSE = 0, REBASE_TRUE, - REBASE_PRESERVE + REBASE_PRESERVE, + REBASE_INTERACTIVE }; /** @@ -42,6 +43,8 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value, return REBASE_TRUE; else if (!strcmp(value, "preserve")) return REBASE_PRESERVE; + else if (!strcmp(value, "interactive")) + return REBASE_INTERACTIVE; if (fatal) die(_("Invalid value for %s: %s"), key, value); @@ -113,7 +116,7 @@ static struct option pull_options[] = { /* Options passed to git-merge or git-rebase */ OPT_GROUP(N_("Options related to merging")), { OPTION_CALLBACK, 'r', "rebase", &opt_rebase, - "false|true|preserve", + "false|true|preserve|interactive", N_("incorporate changes by rebasing rather than merging"), PARSE_OPT_OPTARG, parse_opt_rebase }, OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL, @@ -382,7 +385,7 @@ static void get_merge_heads(struct sha1_array *merge_heads) if (!(fp = fopen(filename, "r"))) die_errno(_("could not open '%s' for reading"), filename); - while (strbuf_getline(&sb, fp, '\n') != EOF) { + while (strbuf_getline_lf(&sb, fp) != EOF) { if (get_sha1_hex(sb.buf, sha1)) continue; /* invalid line: does not start with SHA1 */ if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t")) @@ -778,6 +781,8 @@ static int run_rebase(const unsigned char *curr_head, /* Options passed to git-rebase */ if (opt_rebase == REBASE_PRESERVE) argv_array_push(&args, "--preserve-merges"); + else if (opt_rebase == REBASE_INTERACTIVE) + argv_array_push(&args, "--interactive"); if (opt_diffstat) argv_array_push(&args, opt_diffstat); argv_array_pushv(&args, opt_strategies.argv); diff --git a/builtin/push.c b/builtin/push.c index 3bda430b6b..4e9e4dbab2 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -9,6 +9,7 @@ #include "transport.h" #include "parse-options.h" #include "submodule.h" +#include "submodule-config.h" #include "send-pack.h" static const char * const push_usage[] = { @@ -21,6 +22,8 @@ static int deleterefs; static const char *receivepack; static int verbosity; static int progress = -1; +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; +static enum transport_family family; static struct push_cas_option cas; @@ -202,37 +205,6 @@ static void setup_push_current(struct remote *remote, struct branch *branch) add_refspec(branch->name); } -static char warn_unspecified_push_default_msg[] = -N_("push.default is unset; its implicit value has changed in\n" - "Git 2.0 from 'matching' to 'simple'. To squelch this message\n" - "and maintain the traditional behavior, use:\n" - "\n" - " git config --global push.default matching\n" - "\n" - "To squelch this message and adopt the new behavior now, use:\n" - "\n" - " git config --global push.default simple\n" - "\n" - "When push.default is set to 'matching', git will push local branches\n" - "to the remote branches that already exist with the same name.\n" - "\n" - "Since Git 2.0, Git defaults to the more conservative 'simple'\n" - "behavior, which only pushes the current branch to the corresponding\n" - "remote branch that 'git pull' uses to update the current branch.\n" - "\n" - "See 'git help config' and search for 'push.default' for further information.\n" - "(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode\n" - "'current' instead of 'simple' if you sometimes use older versions of Git)"); - -static void warn_unspecified_push_default_configuration(void) -{ - static int warn_once; - - if (warn_once++) - return; - warning("%s\n", _(warn_unspecified_push_default_msg)); -} - static int is_workflow_triangular(struct remote *remote) { struct remote *fetch_remote = remote_get(NULL); @@ -251,9 +223,6 @@ static void setup_default_push_refspecs(struct remote *remote) break; case PUSH_DEFAULT_UNSPECIFIED: - warn_unspecified_push_default_configuration(); - /* fallthru */ - case PUSH_DEFAULT_SIMPLE: if (triangular) setup_push_current(remote, branch); @@ -344,6 +313,7 @@ static int push_with_options(struct transport *transport, int flags) unsigned int reject_reasons; transport_set_verbosity(transport, verbosity, progress); + transport->family = family; if (receivepack) transport_set_option(transport, @@ -452,22 +422,14 @@ static int do_push(const char *repo, int flags) static int option_parse_recurse_submodules(const struct option *opt, const char *arg, int unset) { - int *flags = opt->value; + int *recurse_submodules = opt->value; - if (*flags & (TRANSPORT_RECURSE_SUBMODULES_CHECK | - TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND)) - die("%s can only be used once.", opt->long_name); - - if (arg) { - if (!strcmp(arg, "check")) - *flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK; - else if (!strcmp(arg, "on-demand")) - *flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND; - else - die("bad %s argument: %s", opt->long_name, arg); - } else - die("option %s needs an argument (check|on-demand)", - opt->long_name); + if (unset) + *recurse_submodules = RECURSE_SUBMODULES_OFF; + else if (arg) + *recurse_submodules = parse_push_recurse_submodules_arg(opt->long_name, arg); + else + die("%s missing parameter", opt->long_name); return 0; } @@ -522,6 +484,10 @@ static int git_push_config(const char *k, const char *v, void *cb) return error("Invalid value for '%s'", k); } } + } else if (!strcmp(k, "push.recursesubmodules")) { + const char *value; + if (!git_config_get_value("push.recursesubmodules", &value)) + recurse_submodules = parse_push_recurse_submodules_arg(k, value); } return git_default_config(k, v, NULL); @@ -540,7 +506,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL), OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"), (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), - OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")), + OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")), OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")), OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN), OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN), @@ -549,7 +515,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"), N_("require old value of ref to be at this value"), PARSE_OPT_OPTARG, parseopt_push_cas_option }, - { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check|on-demand", + { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "check|on-demand|no", N_("control recursive pushing of submodules"), PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")), @@ -567,6 +533,10 @@ int cmd_push(int argc, const char **argv, const char *prefix) 0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"), PARSE_OPT_OPTARG, option_parse_push_signed }, OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC), + OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), + TRANSPORT_FAMILY_IPV4), + OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), + TRANSPORT_FAMILY_IPV6), OPT_END() }; @@ -580,6 +550,11 @@ int cmd_push(int argc, const char **argv, const char *prefix) if (deleterefs && argc < 2) die(_("--delete doesn't make sense without any refs")); + if (recurse_submodules == RECURSE_SUBMODULES_CHECK) + flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK; + else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) + flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND; + if (tags) add_refspec("refs/tags/*"); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index ca38131873..c8e32b297c 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1031,7 +1031,6 @@ static void run_update_post_hook(struct command *commands) { struct command *cmd; int argc; - const char **argv; struct child_process proc = CHILD_PROCESS_INIT; const char *hook; @@ -1044,21 +1043,16 @@ static void run_update_post_hook(struct command *commands) if (!argc || !hook) return; - argv = xmalloc(sizeof(*argv) * (2 + argc)); - argv[0] = hook; - - for (argc = 1, cmd = commands; cmd; cmd = cmd->next) { + argv_array_push(&proc.args, hook); + for (cmd = commands; cmd; cmd = cmd->next) { if (cmd->error_string || cmd->did_not_exist) continue; - argv[argc] = xstrdup(cmd->ref_name); - argc++; + argv_array_push(&proc.args, cmd->ref_name); } - argv[argc] = NULL; proc.no_stdin = 1; proc.stdout_to_stderr = 1; proc.err = use_sideband ? -1 : 0; - proc.argv = argv; if (!start_command(&proc)) { if (use_sideband) @@ -1378,7 +1372,7 @@ static struct command **queue_command(struct command **tail, refname = line + 82; reflen = linelen - 82; - cmd = xcalloc(1, sizeof(struct command) + reflen + 1); + cmd = xcalloc(1, st_add3(sizeof(struct command), reflen, 1)); hashcpy(cmd->old_sha1, old_sha1); hashcpy(cmd->new_sha1, new_sha1); memcpy(cmd->ref_name, refname, reflen); @@ -1597,8 +1591,7 @@ static void prepare_shallow_update(struct command *commands, { int i, j, k, bitmap_size = (si->ref->nr + 31) / 32; - si->used_shallow = xmalloc(sizeof(*si->used_shallow) * - si->shallow->nr); + ALLOC_ARRAY(si->used_shallow, si->shallow->nr); assign_shallow_commits_to_refs(si, si->used_shallow, NULL); si->need_reachability_test = @@ -1618,7 +1611,7 @@ static void prepare_shallow_update(struct command *commands, continue; si->need_reachability_test[i]++; for (k = 0; k < 32; k++) - if (si->used_shallow[i][j] & (1 << k)) + if (si->used_shallow[i][j] & (1U << k)) si->shallow_ref[j * 32 + k]++; } @@ -1664,7 +1657,7 @@ static void update_shallow_info(struct command *commands, return; } - ref_status = xmalloc(sizeof(*ref_status) * ref->nr); + ALLOC_ARRAY(ref_status, ref->nr); assign_shallow_commits_to_refs(si, NULL, ref_status); for (cmd = commands; cmd; cmd = cmd->next) { if (is_null_sha1(cmd->new_sha1)) @@ -1796,6 +1789,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) "gc", "--auto", "--quiet", NULL, }; int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR; + close_all_packs(); run_command_v_opt(argv_gc_auto, opt); } if (auto_update_server_info) diff --git a/builtin/reflog.c b/builtin/reflog.c index f39960e5e4..2d46b6482a 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -382,11 +382,9 @@ static int collect_reflog(const char *ref, const struct object_id *oid, int unus { struct collected_reflog *e; struct collect_reflog_cb *cb = cb_data; - size_t namelen = strlen(ref); - e = xmalloc(sizeof(*e) + namelen + 1); + FLEX_ALLOC_STR(e, reflog, ref); hashcpy(e->sha1, oid->hash); - memcpy(e->reflog, ref, namelen + 1); ALLOC_GROW(cb->e, cb->nr + 1, cb->alloc); cb->e[cb->nr++] = e; return 0; @@ -396,7 +394,6 @@ static struct reflog_expire_cfg { struct reflog_expire_cfg *next; unsigned long expire_total; unsigned long expire_unreachable; - size_t len; char pattern[FLEX_ARRAY]; } *reflog_expire_cfg, **reflog_expire_cfg_tail; @@ -408,13 +405,11 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len) reflog_expire_cfg_tail = &reflog_expire_cfg; for (ent = reflog_expire_cfg; ent; ent = ent->next) - if (ent->len == len && - !memcmp(ent->pattern, pattern, len)) + if (!strncmp(ent->pattern, pattern, len) && + ent->pattern[len] == '\0') return ent; - ent = xcalloc(1, (sizeof(*ent) + len)); - memcpy(ent->pattern, pattern, len); - ent->len = len; + FLEX_ALLOC_MEM(ent, pattern, pattern, len); *reflog_expire_cfg_tail = ent; reflog_expire_cfg_tail = &(ent->next); return ent; diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c index e3cd25d580..7457c743e8 100644 --- a/builtin/remote-ext.c +++ b/builtin/remote-ext.c @@ -114,30 +114,14 @@ static char *strip_escapes(const char *str, const char *service, } } -/* Should be enough... */ -#define MAXARGUMENTS 256 - -static const char **parse_argv(const char *arg, const char *service) +static void parse_argv(struct argv_array *out, const char *arg, const char *service) { - int arguments = 0; - int i; - const char **ret; - char *temparray[MAXARGUMENTS + 1]; - while (*arg) { - char *expanded; - if (arguments == MAXARGUMENTS) - die("remote-ext command has too many arguments"); - expanded = strip_escapes(arg, service, &arg); + char *expanded = strip_escapes(arg, service, &arg); if (expanded) - temparray[arguments++] = expanded; + argv_array_push(out, expanded); + free(expanded); } - - ret = xmalloc((arguments + 1) * sizeof(char *)); - for (i = 0; i < arguments; i++) - ret[i] = temparray[i]; - ret[arguments] = NULL; - return ret; } static void send_git_request(int stdin_fd, const char *serv, const char *repo, @@ -158,7 +142,7 @@ static int run_child(const char *arg, const char *service) child.in = -1; child.out = -1; child.err = 0; - child.argv = parse_argv(arg, service); + parse_argv(&child.args, arg, service); if (start_command(&child) < 0) die("Can't run specified command"); diff --git a/builtin/remote.c b/builtin/remote.c index 6694cf20ef..fda5c2e53d 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -108,8 +108,8 @@ enum { #define MIRROR_PUSH 2 #define MIRROR_BOTH (MIRROR_FETCH|MIRROR_PUSH) -static int add_branch(const char *key, const char *branchname, - const char *remotename, int mirror, struct strbuf *tmp) +static void add_branch(const char *key, const char *branchname, + const char *remotename, int mirror, struct strbuf *tmp) { strbuf_reset(tmp); strbuf_addch(tmp, '+'); @@ -119,7 +119,7 @@ static int add_branch(const char *key, const char *branchname, else strbuf_addf(tmp, "refs/heads/%s:refs/remotes/%s/%s", branchname, remotename, branchname); - return git_config_set_multivar(key, tmp->buf, "^$", 0); + git_config_set_multivar(key, tmp->buf, "^$", 0); } static const char mirror_advice[] = @@ -186,10 +186,7 @@ static int add(int argc, const char **argv) url = argv[1]; remote = remote_get(name); - if (remote && (remote->url_nr > 1 || - (strcmp(name, remote->url[0]) && - strcmp(url, remote->url[0])) || - remote->fetch_refspec_nr)) + if (remote_is_configured(remote)) die(_("remote %s already exists."), name); strbuf_addf(&buf2, "refs/heads/test:refs/remotes/%s/test", name); @@ -197,8 +194,7 @@ static int add(int argc, const char **argv) die(_("'%s' is not a valid remote name"), name); strbuf_addf(&buf, "remote.%s.url", name); - if (git_config_set(buf.buf, url)) - return 1; + git_config_set(buf.buf, url); if (!mirror || mirror & MIRROR_FETCH) { strbuf_reset(&buf); @@ -206,25 +202,22 @@ static int add(int argc, const char **argv) if (track.nr == 0) string_list_append(&track, "*"); for (i = 0; i < track.nr; i++) { - if (add_branch(buf.buf, track.items[i].string, - name, mirror, &buf2)) - return 1; + add_branch(buf.buf, track.items[i].string, + name, mirror, &buf2); } } if (mirror & MIRROR_PUSH) { strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.mirror", name); - if (git_config_set(buf.buf, "true")) - return 1; + git_config_set(buf.buf, "true"); } if (fetch_tags != TAGS_DEFAULT) { strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.tagopt", name); - if (git_config_set(buf.buf, - fetch_tags == TAGS_SET ? "--tags" : "--no-tags")) - return 1; + git_config_set(buf.buf, + fetch_tags == TAGS_SET ? "--tags" : "--no-tags"); } if (fetch && fetch_remote(name)) @@ -251,7 +244,7 @@ static int add(int argc, const char **argv) struct branch_info { char *remote_name; struct string_list merge; - int rebase; + enum { NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE } rebase; }; static struct string_list branch_list; @@ -311,7 +304,9 @@ static int config_read_branches(const char *key, const char *value, void *cb) if (v >= 0) info->rebase = v; else if (!strcmp(value, "preserve")) - info->rebase = 1; + info->rebase = NORMAL_REBASE; + else if (!strcmp(value, "interactive")) + info->rebase = INTERACTIVE_REBASE; } } return 0; @@ -590,25 +585,20 @@ static int migrate_file(struct remote *remote) strbuf_addf(&buf, "remote.%s.url", remote->name); for (i = 0; i < remote->url_nr; i++) - if (git_config_set_multivar(buf.buf, remote->url[i], "^$", 0)) - return error(_("Could not append '%s' to '%s'"), - remote->url[i], buf.buf); + git_config_set_multivar(buf.buf, remote->url[i], "^$", 0); strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.push", remote->name); for (i = 0; i < remote->push_refspec_nr; i++) - if (git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0)) - return error(_("Could not append '%s' to '%s'"), - remote->push_refspec[i], buf.buf); + git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0); strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.fetch", remote->name); for (i = 0; i < remote->fetch_refspec_nr; i++) - if (git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0)) - return error(_("Could not append '%s' to '%s'"), - remote->fetch_refspec[i], buf.buf); + git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0); if (remote->origin == REMOTE_REMOTES) unlink_or_warn(git_path("remotes/%s", remote->name)); else if (remote->origin == REMOTE_BRANCHES) unlink_or_warn(git_path("branches/%s", remote->name)); + return 0; } @@ -632,14 +622,14 @@ static int mv(int argc, const char **argv) rename.remote_branches = &remote_branches; oldremote = remote_get(rename.old); - if (!oldremote) + if (!remote_is_configured(oldremote)) die(_("No such remote: %s"), rename.old); if (!strcmp(rename.old, rename.new) && oldremote->origin != REMOTE_CONFIG) return migrate_file(oldremote); newremote = remote_get(rename.new); - if (newremote && (newremote->url_nr > 1 || newremote->fetch_refspec_nr)) + if (remote_is_configured(newremote)) die(_("remote %s already exists."), rename.new); strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new); @@ -655,8 +645,7 @@ static int mv(int argc, const char **argv) strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.fetch", rename.new); - if (git_config_set_multivar(buf.buf, NULL, NULL, 1)) - return error(_("Could not remove config section '%s'"), buf.buf); + git_config_set_multivar(buf.buf, NULL, NULL, 1); strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old); for (i = 0; i < oldremote->fetch_refspec_nr; i++) { char *ptr; @@ -676,8 +665,7 @@ static int mv(int argc, const char **argv) "\tPlease update the configuration manually if necessary."), buf2.buf); - if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0)) - return error(_("Could not append '%s'"), buf.buf); + git_config_set_multivar(buf.buf, buf2.buf, "^$", 0); } read_branches(); @@ -687,9 +675,7 @@ static int mv(int argc, const char **argv) if (info->remote_name && !strcmp(info->remote_name, rename.old)) { strbuf_reset(&buf); strbuf_addf(&buf, "branch.%s.remote", item->string); - if (git_config_set(buf.buf, rename.new)) { - return error(_("Could not set '%s'"), buf.buf); - } + git_config_set(buf.buf, rename.new); } } @@ -771,7 +757,7 @@ static int rm(int argc, const char **argv) usage_with_options(builtin_remote_rm_usage, options); remote = remote_get(argv[1]); - if (!remote) + if (!remote_is_configured(remote)) die(_("No such remote: %s"), argv[1]); known_remotes.to_delete = remote; @@ -787,10 +773,7 @@ static int rm(int argc, const char **argv) strbuf_reset(&buf); strbuf_addf(&buf, "branch.%s.%s", item->string, *k); - if (git_config_set(buf.buf, NULL)) { - strbuf_release(&buf); - return -1; - } + git_config_set(buf.buf, NULL); } } } @@ -980,7 +963,9 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data) printf(" %-*s ", show_info->width, item->string); if (branch_info->rebase) { - printf_ln(_("rebases onto remote %s"), merge->items[0].string); + printf_ln(_(branch_info->rebase == INTERACTIVE_REBASE ? + "rebases interactively onto remote %s" : + "rebases onto remote %s"), merge->items[0].string); return 0; } else if (show_info->any_rebase) { printf_ln(_(" merges with remote %s"), merge->items[0].string); @@ -1409,24 +1394,20 @@ static int update(int argc, const char **argv) static int remove_all_fetch_refspecs(const char *remote, const char *key) { - return git_config_set_multivar(key, NULL, NULL, 1); + return git_config_set_multivar_gently(key, NULL, NULL, 1); } -static int add_branches(struct remote *remote, const char **branches, - const char *key) +static void add_branches(struct remote *remote, const char **branches, + const char *key) { const char *remotename = remote->name; int mirror = remote->mirror; struct strbuf refspec = STRBUF_INIT; for (; *branches; branches++) - if (add_branch(key, *branches, remotename, mirror, &refspec)) { - strbuf_release(&refspec); - return 1; - } + add_branch(key, *branches, remotename, mirror, &refspec); strbuf_release(&refspec); - return 0; } static int set_remote_branches(const char *remotename, const char **branches, @@ -1437,18 +1418,15 @@ static int set_remote_branches(const char *remotename, const char **branches, strbuf_addf(&key, "remote.%s.fetch", remotename); - if (!remote_is_configured(remotename)) - die(_("No such remote '%s'"), remotename); remote = remote_get(remotename); + if (!remote_is_configured(remote)) + die(_("No such remote '%s'"), remotename); if (!add_mode && remove_all_fetch_refspecs(remotename, key.buf)) { strbuf_release(&key); return 1; } - if (add_branches(remote, branches, key.buf)) { - strbuf_release(&key); - return 1; - } + add_branches(remote, branches, key.buf); strbuf_release(&key); return 0; @@ -1494,9 +1472,9 @@ static int get_url(int argc, const char **argv) remotename = argv[0]; - if (!remote_is_configured(remotename)) - die(_("No such remote '%s'"), remotename); remote = remote_get(remotename); + if (!remote_is_configured(remote)) + die(_("No such remote '%s'"), remotename); url_nr = 0; if (push_mode) { @@ -1562,9 +1540,9 @@ static int set_url(int argc, const char **argv) if (delete_mode) oldurl = newurl; - if (!remote_is_configured(remotename)) - die(_("No such remote '%s'"), remotename); remote = remote_get(remotename); + if (!remote_is_configured(remote)) + die(_("No such remote '%s'"), remotename); if (push_mode) { strbuf_addf(&name_buf, "remote.%s.pushurl", remotename); @@ -1580,10 +1558,11 @@ static int set_url(int argc, const char **argv) if ((!oldurl && !delete_mode) || add_mode) { if (add_mode) git_config_set_multivar(name_buf.buf, newurl, - "^$", 0); + "^$", 0); else git_config_set(name_buf.buf, newurl); strbuf_release(&name_buf); + return 0; } diff --git a/builtin/repack.c b/builtin/repack.c index 945611006a..858db38f52 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -266,7 +266,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) return ret; out = xfdopen(cmd.out, "r"); - while (strbuf_getline(&line, out, '\n') != EOF) { + while (strbuf_getline_lf(&line, out) != EOF) { if (line.len != 40) die("repack: Expecting 40 character sha1 lines only from pack-objects."); string_list_append(&names, line.buf); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 3aa89a1a3c..275da0d647 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -177,9 +177,7 @@ static void finish_commit(struct commit *commit, void *data) free_commit_buffer(commit); } -static void finish_object(struct object *obj, - const struct name_path *path, const char *name, - void *cb_data) +static void finish_object(struct object *obj, const char *name, void *cb_data) { struct rev_list_info *info = cb_data; if (obj->type == OBJ_BLOB && !has_object_file(&obj->oid)) @@ -188,15 +186,13 @@ static void finish_object(struct object *obj, parse_object(obj->oid.hash); } -static void show_object(struct object *obj, - const struct name_path *path, const char *component, - void *cb_data) +static void show_object(struct object *obj, const char *name, void *cb_data) { struct rev_list_info *info = cb_data; - finish_object(obj, path, component, cb_data); + finish_object(obj, name, cb_data); if (info->flags & REV_LIST_QUIET) return; - show_object_with_name(stdout, obj, path, component); + show_object_with_name(stdout, obj, name); } static void show_edge(struct commit *commit) diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 7e074aad40..cf8487b3b9 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -383,7 +383,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) /* get the usage up to the first line with a -- on it */ for (;;) { - if (strbuf_getline(&sb, stdin, '\n') == EOF) + if (strbuf_getline(&sb, stdin) == EOF) die("premature end of input"); ALLOC_GROW(usage, unb + 1, usz); if (!strcmp("--", sb.buf)) { @@ -396,7 +396,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) } /* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */ - while (strbuf_getline(&sb, stdin, '\n') != EOF) { + while (strbuf_getline(&sb, stdin) != EOF) { const char *s; const char *help; struct option *o; @@ -763,7 +763,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--git-common-dir")) { - puts(get_git_common_dir()); + const char *pfx = prefix ? prefix : ""; + puts(prefix_filename(pfx, strlen(pfx), get_git_common_dir())); continue; } if (!strcmp(arg, "--resolve-git-dir")) { diff --git a/builtin/rm.c b/builtin/rm.c index 80b972f92f..8829b09d0b 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -211,7 +211,7 @@ static int check_local_mod(unsigned char *head, int index_only) * "intent to add" entry. */ if (local_changes && staged_changes) { - if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD)) + if (!index_only || !ce_intent_to_add(ce)) string_list_append(&files_staged, name); } else if (!index_only) { diff --git a/builtin/send-pack.c b/builtin/send-pack.c index f6e5d643c1..5b9dd6a9d8 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -212,7 +212,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) argv_array_push(&all_refspecs, buf); } else { struct strbuf line = STRBUF_INIT; - while (strbuf_getline(&line, stdin, '\n') != EOF) + while (strbuf_getline(&line, stdin) != EOF) argv_array_push(&all_refspecs, line.buf); strbuf_release(&line); } diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 35ebd17f80..bfc082e584 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -14,7 +14,26 @@ static char const * const shortlog_usage[] = { NULL }; -static int compare_by_number(const void *a1, const void *a2) +/* + * The util field of our string_list_items will contain one of two things: + * + * - if --summary is not in use, it will point to a string list of the + * oneline subjects assigned to this author + * + * - if --summary is in use, we don't need that list; we only need to know + * its size. So we abuse the pointer slot to store our integer counter. + * + * This macro accesses the latter. + */ +#define UTIL_TO_INT(x) ((intptr_t)(x)->util) + +static int compare_by_counter(const void *a1, const void *a2) +{ + const struct string_list_item *i1 = a1, *i2 = a2; + return UTIL_TO_INT(i2) - UTIL_TO_INT(i1); +} + +static int compare_by_list(const void *a1, const void *a2) { const struct string_list_item *i1 = a1, *i2 = a2; const struct string_list *l1 = i1->util, *l2 = i2->util; @@ -31,13 +50,9 @@ static void insert_one_record(struct shortlog *log, const char *author, const char *oneline) { - const char *dot3 = log->common_repo_prefix; - char *buffer, *p; struct string_list_item *item; const char *mailbuf, *namebuf; size_t namelen, maillen; - const char *eol; - struct strbuf subject = STRBUF_INIT; struct strbuf namemailbuf = STRBUF_INIT; struct ident_split ident; @@ -56,98 +71,95 @@ static void insert_one_record(struct shortlog *log, strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf); item = string_list_insert(&log->list, namemailbuf.buf); - if (item->util == NULL) - item->util = xcalloc(1, sizeof(struct string_list)); - - /* Skip any leading whitespace, including any blank lines. */ - while (*oneline && isspace(*oneline)) - oneline++; - eol = strchr(oneline, '\n'); - if (!eol) - eol = oneline + strlen(oneline); - if (starts_with(oneline, "[PATCH")) { - char *eob = strchr(oneline, ']'); - if (eob && (!eol || eob < eol)) - oneline = eob + 1; - } - while (*oneline && isspace(*oneline) && *oneline != '\n') - oneline++; - format_subject(&subject, oneline, " "); - buffer = strbuf_detach(&subject, NULL); - - if (dot3) { - int dot3len = strlen(dot3); - if (dot3len > 5) { - while ((p = strstr(buffer, dot3)) != NULL) { - int taillen = strlen(p) - dot3len; - memcpy(p, "/.../", 5); - memmove(p + 5, p + dot3len, taillen + 1); + + if (log->summary) + item->util = (void *)(UTIL_TO_INT(item) + 1); + else { + const char *dot3 = log->common_repo_prefix; + char *buffer, *p; + struct strbuf subject = STRBUF_INIT; + const char *eol; + + /* Skip any leading whitespace, including any blank lines. */ + while (*oneline && isspace(*oneline)) + oneline++; + eol = strchr(oneline, '\n'); + if (!eol) + eol = oneline + strlen(oneline); + if (starts_with(oneline, "[PATCH")) { + char *eob = strchr(oneline, ']'); + if (eob && (!eol || eob < eol)) + oneline = eob + 1; + } + while (*oneline && isspace(*oneline) && *oneline != '\n') + oneline++; + format_subject(&subject, oneline, " "); + buffer = strbuf_detach(&subject, NULL); + + if (dot3) { + int dot3len = strlen(dot3); + if (dot3len > 5) { + while ((p = strstr(buffer, dot3)) != NULL) { + int taillen = strlen(p) - dot3len; + memcpy(p, "/.../", 5); + memmove(p + 5, p + dot3len, taillen + 1); + } } } - } - string_list_append(item->util, buffer); + if (item->util == NULL) + item->util = xcalloc(1, sizeof(struct string_list)); + string_list_append(item->util, buffer); + } } static void read_from_stdin(struct shortlog *log) { - char author[1024], oneline[1024]; + struct strbuf author = STRBUF_INIT; + struct strbuf oneline = STRBUF_INIT; - while (fgets(author, sizeof(author), stdin) != NULL) { - if (!(author[0] == 'A' || author[0] == 'a') || - !starts_with(author + 1, "uthor: ")) + while (strbuf_getline_lf(&author, stdin) != EOF) { + const char *v; + if (!skip_prefix(author.buf, "Author: ", &v) && + !skip_prefix(author.buf, "author ", &v)) continue; - while (fgets(oneline, sizeof(oneline), stdin) && - oneline[0] != '\n') + while (strbuf_getline_lf(&oneline, stdin) != EOF && + oneline.len) ; /* discard headers */ - while (fgets(oneline, sizeof(oneline), stdin) && - oneline[0] == '\n') + while (strbuf_getline_lf(&oneline, stdin) != EOF && + !oneline.len) ; /* discard blanks */ - insert_one_record(log, author + 8, oneline); + insert_one_record(log, v, oneline.buf); } + strbuf_release(&author); + strbuf_release(&oneline); } void shortlog_add_commit(struct shortlog *log, struct commit *commit) { - const char *author = NULL, *buffer; - struct strbuf buf = STRBUF_INIT; - struct strbuf ufbuf = STRBUF_INIT; - - pp_commit_easy(CMIT_FMT_RAW, commit, &buf); - buffer = buf.buf; - while (*buffer && *buffer != '\n') { - const char *eol = strchr(buffer, '\n'); - - if (eol == NULL) - eol = buffer + strlen(buffer); + struct strbuf author = STRBUF_INIT; + struct strbuf oneline = STRBUF_INIT; + struct pretty_print_context ctx = {0}; + + ctx.fmt = CMIT_FMT_USERFORMAT; + ctx.abbrev = log->abbrev; + ctx.subject = ""; + ctx.after_subject = ""; + ctx.date_mode.type = DATE_NORMAL; + ctx.output_encoding = get_log_output_encoding(); + + format_commit_message(commit, "%an <%ae>", &author, &ctx); + if (!log->summary) { + if (log->user_format) + pretty_print_commit(&ctx, commit, &oneline); else - eol++; - - if (starts_with(buffer, "author ")) - author = buffer + 7; - buffer = eol; - } - if (!author) { - warning(_("Missing author: %s"), - oid_to_hex(&commit->object.oid)); - return; + format_commit_message(commit, "%s", &oneline, &ctx); } - if (log->user_format) { - struct pretty_print_context ctx = {0}; - ctx.fmt = CMIT_FMT_USERFORMAT; - ctx.abbrev = log->abbrev; - ctx.subject = ""; - ctx.after_subject = ""; - ctx.date_mode.type = DATE_NORMAL; - ctx.output_encoding = get_log_output_encoding(); - pretty_print_commit(&ctx, commit, &ufbuf); - buffer = ufbuf.buf; - } else if (*buffer) { - buffer++; - } - insert_one_record(log, author, !*buffer ? "<none>" : buffer); - strbuf_release(&ufbuf); - strbuf_release(&buf); + + insert_one_record(log, author.buf, oneline.len ? oneline.buf : "<none>"); + + strbuf_release(&author); + strbuf_release(&oneline); } static void get_from_rev(struct rev_info *rev, struct shortlog *log) @@ -294,14 +306,14 @@ void shortlog_output(struct shortlog *log) if (log->sort_by_number) qsort(log->list.items, log->list.nr, sizeof(struct string_list_item), - compare_by_number); + log->summary ? compare_by_counter : compare_by_list); for (i = 0; i < log->list.nr; i++) { - struct string_list *onelines = log->list.items[i].util; - + const struct string_list_item *item = &log->list.items[i]; if (log->summary) { - printf("%6d\t%s\n", onelines->nr, log->list.items[i].string); + printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string); } else { - printf("%s (%d):\n", log->list.items[i].string, onelines->nr); + struct string_list *onelines = item->util; + printf("%s (%d):\n", item->string, onelines->nr); for (j = onelines->nr - 1; j >= 0; j--) { const char *msg = onelines->items[j].string; @@ -314,11 +326,11 @@ void shortlog_output(struct shortlog *log) printf(" %s\n", msg); } putchar('\n'); + onelines->strdup_strings = 1; + string_list_clear(onelines, 0); + free(onelines); } - onelines->strdup_strings = 1; - string_list_clear(onelines, 0); - free(onelines); log->list.items[i].util = NULL; } diff --git a/builtin/stripspace.c b/builtin/stripspace.c index 7ff8434f7c..15e716ef43 100644 --- a/builtin/stripspace.c +++ b/builtin/stripspace.c @@ -35,7 +35,7 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix) N_("skip and remove all lines starting with comment character"), STRIP_COMMENTS), OPT_CMDMODE('c', "comment-lines", &mode, - N_("prepend comment character and blank to each line"), + N_("prepend comment character and space to each line"), COMMENT_LINES), OPT_END() }; diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index a39ad1be99..864dd18786 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -22,17 +22,12 @@ static int module_list_compute(int argc, const char **argv, struct module_list *list) { int i, result = 0; - char *max_prefix, *ps_matched = NULL; - int max_prefix_len; + char *ps_matched = NULL; parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL | PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP, prefix, argv); - /* Find common prefix for all pathspec's */ - max_prefix = common_prefix(pathspec); - max_prefix_len = max_prefix ? strlen(max_prefix) : 0; - if (pathspec->nr) ps_matched = xcalloc(pathspec->nr, 1); @@ -42,9 +37,9 @@ static int module_list_compute(int argc, const char **argv, for (i = 0; i < active_nr; i++) { const struct cache_entry *ce = active_cache[i]; - if (!S_ISGITLINK(ce->ce_mode) || - !match_pathspec(pathspec, ce->name, ce_namelen(ce), - max_prefix_len, ps_matched, 1)) + if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), + 0, ps_matched, 1) || + !S_ISGITLINK(ce->ce_mode)) continue; ALLOC_GROW(list->entries, list->nr + 1, list->alloc); @@ -57,7 +52,6 @@ static int module_list_compute(int argc, const char **argv, */ i++; } - free(max_prefix); if (ps_matched && report_path_error(ps_matched, pathspec, prefix)) result = -1; diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c index ce0fde705c..9c29a64e43 100644 --- a/builtin/symbolic-ref.c +++ b/builtin/symbolic-ref.c @@ -67,7 +67,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) if (!strcmp(argv[0], "HEAD") && !starts_with(argv[1], "refs/")) die("Refusing to point HEAD outside of refs/"); - create_symref(argv[0], argv[1], msg); + ret = !!create_symref(argv[0], argv[1], msg); break; default: usage_with_options(git_symbolic_ref_usage, options); diff --git a/builtin/tag.c b/builtin/tag.c index 8db8c87e57..1705c94665 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -44,11 +44,11 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con if (!format) { if (filter->lines) { to_free = xstrfmt("%s %%(contents:lines=%d)", - "%(align:15)%(refname:short)%(end)", + "%(align:15)%(refname:strip=2)%(end)", filter->lines); format = to_free; } else - format = "%(refname:short)"; + format = "%(refname:strip=2)"; } verify_ref_format(format); diff --git a/builtin/update-index.c b/builtin/update-index.c index 7431938fa6..1c94ca59bf 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -35,6 +35,15 @@ static int mark_skip_worktree_only; #define UNMARK_FLAG 2 static struct strbuf mtime_dir = STRBUF_INIT; +/* Untracked cache mode */ +enum uc_mode { + UC_UNSPECIFIED = -1, + UC_DISABLE = 0, + UC_ENABLE, + UC_TEST, + UC_FORCE +}; + __attribute__((format (printf, 1, 2))) static void report(const char *fmt, ...) { @@ -121,7 +130,7 @@ static int test_if_untracked_cache_is_supported(void) if (!mkdtemp(mtime_dir.buf)) die_errno("Could not make temporary directory"); - fprintf(stderr, _("Testing ")); + fprintf(stderr, _("Testing mtime in '%s' "), xgetcwd()); atexit(remove_test_directory); xstat_mtime_dir(&st); fill_stat_data(&base, &st); @@ -468,12 +477,14 @@ static void update_one(const char *path) report("add '%s'", path); } -static void read_index_info(int line_termination) +static void read_index_info(int nul_term_line) { struct strbuf buf = STRBUF_INIT; struct strbuf uq = STRBUF_INIT; + strbuf_getline_fn getline_fn; - while (strbuf_getline(&buf, stdin, line_termination) != EOF) { + getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf; + while (getline_fn(&buf, stdin) != EOF) { char *ptr, *tab; char *path_name; unsigned char sha1[20]; @@ -522,7 +533,7 @@ static void read_index_info(int line_termination) goto bad_line; path_name = ptr; - if (line_termination && path_name[0] == '"') { + if (!nul_term_line && path_name[0] == '"') { strbuf_reset(&uq); if (unquote_c_style(&uq, path_name, NULL)) { die("git update-index: bad quoting of path name"); @@ -844,12 +855,12 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { - int *line_termination = opt->value; + int *nul_term_line = opt->value; if (ctx->argc != 1) return error("option '%s' must be the last argument", opt->long_name); allow_add = allow_replace = allow_remove = 1; - read_index_info(*line_termination); + read_index_info(*nul_term_line); return 0; } @@ -901,8 +912,8 @@ static int reupdate_callback(struct parse_opt_ctx_t *ctx, int cmd_update_index(int argc, const char **argv, const char *prefix) { - int newfd, entries, has_errors = 0, line_termination = '\n'; - int untracked_cache = -1; + int newfd, entries, has_errors = 0, nul_term_line = 0; + enum uc_mode untracked_cache = UC_UNSPECIFIED; int read_from_stdin = 0; int prefix_length = prefix ? strlen(prefix) : 0; int preferred_index_format = 0; @@ -912,6 +923,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) int split_index = -1; struct lock_file *lock_file; struct parse_opt_ctx_t ctx; + strbuf_getline_fn getline_fn; int parseopt_state = PARSE_OPT_UNKNOWN; struct option options[] = { OPT_BIT('q', NULL, &refresh_args.flags, @@ -963,13 +975,13 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) N_("add to index only; do not add content to object database"), 1), OPT_SET_INT(0, "force-remove", &force_remove, N_("remove named paths even if present in worktree"), 1), - OPT_SET_INT('z', NULL, &line_termination, - N_("with --stdin: input lines are terminated by null bytes"), '\0'), + OPT_BOOL('z', NULL, &nul_term_line, + N_("with --stdin: input lines are terminated by null bytes")), {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL, N_("read list of paths to be updated from standard input"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, (parse_opt_cb *) stdin_callback}, - {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &line_termination, NULL, + {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL, N_("add entries from standard input to the index"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, (parse_opt_cb *) stdin_cacheinfo_callback}, @@ -996,8 +1008,10 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) N_("enable or disable split index")), OPT_BOOL(0, "untracked-cache", &untracked_cache, N_("enable/disable untracked cache")), + OPT_SET_INT(0, "test-untracked-cache", &untracked_cache, + N_("test if the filesystem supports untracked cache"), UC_TEST), OPT_SET_INT(0, "force-untracked-cache", &untracked_cache, - N_("enable untracked cache without testing the filesystem"), 2), + N_("enable untracked cache without testing the filesystem"), UC_FORCE), OPT_END() }; @@ -1057,6 +1071,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) } } argc = parse_options_end(&ctx); + + getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf; if (preferred_index_format) { if (preferred_index_format < INDEX_FORMAT_LB || INDEX_FORMAT_UB < preferred_index_format) @@ -1070,16 +1086,17 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) } if (read_from_stdin) { - struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; + struct strbuf unquoted = STRBUF_INIT; setup_work_tree(); - while (strbuf_getline(&buf, stdin, line_termination) != EOF) { + while (getline_fn(&buf, stdin) != EOF) { char *p; - if (line_termination && buf.buf[0] == '"') { - strbuf_reset(&nbuf); - if (unquote_c_style(&nbuf, buf.buf, NULL)) + if (!nul_term_line && buf.buf[0] == '"') { + strbuf_reset(&unquoted); + if (unquote_c_style(&unquoted, buf.buf, NULL)) die("line is badly quoted"); - strbuf_swap(&buf, &nbuf); + strbuf_swap(&buf, &unquoted); } p = prefix_path(prefix, prefix_length, buf.buf); update_one(p); @@ -1087,7 +1104,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) chmod_path(set_executable_bit, p); free(p); } - strbuf_release(&nbuf); + strbuf_release(&unquoted); strbuf_release(&buf); } @@ -1104,27 +1121,32 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) the_index.split_index = NULL; the_index.cache_changed |= SOMETHING_CHANGED; } - if (untracked_cache > 0) { - struct untracked_cache *uc; - if (untracked_cache < 2) { - setup_work_tree(); - if (!test_if_untracked_cache_is_supported()) - return 1; - } - if (!the_index.untracked) { - uc = xcalloc(1, sizeof(*uc)); - strbuf_init(&uc->ident, 100); - uc->exclude_per_dir = ".gitignore"; - /* should be the same flags used by git-status */ - uc->dir_flags = DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES; - the_index.untracked = uc; - } - add_untracked_ident(the_index.untracked); - the_index.cache_changed |= UNTRACKED_CHANGED; - } else if (!untracked_cache && the_index.untracked) { - the_index.untracked = NULL; - the_index.cache_changed |= UNTRACKED_CHANGED; + switch (untracked_cache) { + case UC_UNSPECIFIED: + break; + case UC_DISABLE: + if (git_config_get_untracked_cache() == 1) + warning("core.untrackedCache is set to true; " + "remove or change it, if you really want to " + "disable the untracked cache"); + remove_untracked_cache(&the_index); + report(_("Untracked cache disabled")); + break; + case UC_TEST: + setup_work_tree(); + return !test_if_untracked_cache_is_supported(); + case UC_ENABLE: + case UC_FORCE: + if (git_config_get_untracked_cache() == 0) + warning("core.untrackedCache is set to false; " + "remove or change it, if you really want to " + "enable the untracked cache"); + add_untracked_cache(&the_index); + report(_("Untracked cache enabled for '%s'"), get_git_work_tree()); + break; + default: + die("Bug: bad untracked_cache value: %d", untracked_cache); } if (active_cache_changed) { diff --git a/builtin/worktree.c b/builtin/worktree.c index 475b9581a5..38b56096bd 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -52,7 +52,7 @@ static int prune_worktree(const char *id, struct strbuf *reason) return 1; } len = st.st_size; - path = xmalloc(len + 1); + path = xmallocz(len); read_in_full(fd, path, len); close(fd); while (len && (path[len - 1] == '\n' || path[len - 1] == '\r')) @@ -201,9 +201,7 @@ static int add_worktree(const char *path, const char *refname, die(_("'%s' already exists"), path); /* is 'refname' a branch or commit? */ - if (opts->force_new_branch) /* definitely a branch */ - ; - else if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) && + if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) && ref_exists(symref.buf)) { /* it's a branch */ if (!opts->force) die_if_checked_out(symref.buf); @@ -336,9 +334,18 @@ static int add(int ac, const char **av, const char *prefix) branch = ac < 2 ? "HEAD" : av[1]; opts.force_new_branch = !!new_branch_force; - if (opts.force_new_branch) + if (opts.force_new_branch) { + struct strbuf symref = STRBUF_INIT; + opts.new_branch = new_branch_force; + if (!opts.force && + !strbuf_check_branch_ref(&symref, opts.new_branch) && + ref_exists(symref.buf)) + die_if_checked_out(symref.buf); + strbuf_release(&symref); + } + if (ac < 2 && !opts.new_branch && !opts.detach) { int n; const char *s = worktree_basename(path, &n); |