From: Junio C Hamano Date: Sat, 24 Jun 2017 21:28:41 +0000 (-0700) Subject: Merge branch 'ab/free-and-null' X-Git-Tag: v2.14.0-rc0~57 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/50f03c6676ed5ea040dd53272882d3aac2ee1b48?ds=inline;hp=-c Merge branch 'ab/free-and-null' A common pattern to free a piece of memory and assign NULL to the pointer that used to point at it has been replaced with a new FREE_AND_NULL() macro. * ab/free-and-null: *.[ch] refactoring: make use of the FREE_AND_NULL() macro coccinelle: make use of the "expression" FREE_AND_NULL() rule coccinelle: add a rule to make "expression" code use FREE_AND_NULL() coccinelle: make use of the "type" FREE_AND_NULL() rule coccinelle: add a rule to make "type" code use FREE_AND_NULL() git-compat-util: add a FREE_AND_NULL() wrapper around free(ptr); ptr = NULL --- 50f03c6676ed5ea040dd53272882d3aac2ee1b48 diff --combined alias.c index de8e6a3f49,911481855f..39f622e414 --- a/alias.c +++ b/alias.c @@@ -1,29 -1,14 +1,29 @@@ #include "cache.h" +#include "config.h" + +struct config_alias_data { + const char *alias; + char *v; +}; + +static int config_alias_cb(const char *key, const char *value, void *d) +{ + struct config_alias_data *data = d; + const char *p; + + if (skip_prefix(key, "alias.", &p) && !strcmp(p, data->alias)) + return git_config_string((const char **)&data->v, key, value); + + return 0; +} char *alias_lookup(const char *alias) { - char *v = NULL; - struct strbuf key = STRBUF_INIT; - strbuf_addf(&key, "alias.%s", alias); - if (git_config_key_is_valid(key.buf)) - git_config_get_string(key.buf, &v); - strbuf_release(&key); - return v; + struct config_alias_data data = { alias, NULL }; + + read_early_config(config_alias_cb, &data); + + return data.v; } #define SPLIT_CMDLINE_BAD_ENDING 1 @@@ -62,8 -47,7 +62,7 @@@ int split_cmdline(char *cmdline, const src++; c = cmdline[src]; if (!c) { - free(*argv); - *argv = NULL; + FREE_AND_NULL(*argv); return -SPLIT_CMDLINE_BAD_ENDING; } } @@@ -75,8 -59,7 +74,7 @@@ cmdline[dst] = 0; if (quoted) { - free(*argv); - *argv = NULL; + FREE_AND_NULL(*argv); return -SPLIT_CMDLINE_UNCLOSED_QUOTE; } diff --combined apply.c index f7251ccc8b,e78de0affa..b963d7d8fb --- a/apply.c +++ b/apply.c @@@ -8,7 -8,6 +8,7 @@@ */ #include "cache.h" +#include "config.h" #include "blob.h" #include "delta.h" #include "diff.h" @@@ -763,6 -762,17 +763,6 @@@ static char *find_name_traditional(stru return find_name_common(state, line, def, p_value, line + len, 0); } -static int count_slashes(const char *cp) -{ - int cnt = 0; - char ch; - - while ((ch = *cp++)) - if (ch == '/') - cnt++; - return cnt; -} - /* * Given the string after "--- " or "+++ ", guess the appropriate * p_value for the given patch. @@@ -2257,7 -2267,7 +2257,7 @@@ static int read_old_data(struct stat *s case S_IFREG: if (strbuf_read_file(buf, path, st->st_size) != st->st_size) return error(_("unable to open or read %s"), path); - convert_to_git(path, buf->buf, buf->len, buf, 0); + convert_to_git(&the_index, path, buf->buf, buf->len, buf, 0); return 0; default: return -1; @@@ -3695,8 -3705,7 +3695,7 @@@ static int check_preimage(struct apply_ is_new: patch->is_new = 1; patch->is_delete = 0; - free(patch->old_name); - patch->old_name = NULL; + FREE_AND_NULL(patch->old_name); return 0; } diff --combined attr.c index 6e4b247acd,ebdcfb0b8a..37454999d2 --- a/attr.c +++ b/attr.c @@@ -9,7 -9,6 +9,7 @@@ #define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" +#include "config.h" #include "exec_cmd.h" #include "attr.h" #include "dir.h" @@@ -639,13 -638,11 +639,11 @@@ void attr_check_reset(struct attr_chec void attr_check_clear(struct attr_check *check) { - free(check->items); - check->items = NULL; + FREE_AND_NULL(check->items); check->alloc = 0; check->nr = 0; - free(check->all_attrs); - check->all_attrs = NULL; + FREE_AND_NULL(check->all_attrs); check->all_attrs_nr = 0; drop_attr_stack(&check->stack); diff --combined blame.c index 6d57ab9715,1183943960..91e26e93e8 --- a/blame.c +++ b/blame.c @@@ -229,7 -229,7 +229,7 @@@ static struct commit *fake_working_tree if (strbuf_read(&buf, 0, 0) < 0) die_errno("failed to read from stdin"); } - convert_to_git(path, buf.buf, buf.len, &buf, 0); + convert_to_git(&the_index, path, buf.buf, buf.len, &buf, 0); origin->file.ptr = buf.buf; origin->file.size = buf.len; pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_oid.hash); @@@ -314,8 -314,7 +314,7 @@@ static void fill_origin_blob(struct dif static void drop_origin_blob(struct blame_origin *o) { if (o->file.ptr) { - free(o->file.ptr); - o->file.ptr = NULL; + FREE_AND_NULL(o->file.ptr); } } @@@ -556,9 -555,9 +555,9 @@@ static struct blame_origin *find_origin if (is_null_oid(&origin->commit->object.oid)) do_diff_cache(&parent->tree->object.oid, &diff_opts); else - diff_tree_sha1(parent->tree->object.oid.hash, - origin->commit->tree->object.oid.hash, - "", &diff_opts); + diff_tree_oid(&parent->tree->object.oid, + &origin->commit->tree->object.oid, + "", &diff_opts); diffcore_std(&diff_opts); if (!diff_queued_diff.nr) { @@@ -625,9 -624,9 +624,9 @@@ static struct blame_origin *find_rename if (is_null_oid(&origin->commit->object.oid)) do_diff_cache(&parent->tree->object.oid, &diff_opts); else - diff_tree_sha1(parent->tree->object.oid.hash, - origin->commit->tree->object.oid.hash, - "", &diff_opts); + diff_tree_oid(&parent->tree->object.oid, + &origin->commit->tree->object.oid, + "", &diff_opts); diffcore_std(&diff_opts); for (i = 0; i < diff_queued_diff.nr; i++) { @@@ -1247,7 -1246,7 +1246,7 @@@ static void find_copy_in_parent(struct /* Try "find copies harder" on new path if requested; * we do not want to use diffcore_rename() actually to * match things up; find_copies_harder is set only to - * force diff_tree_sha1() to feed all filepairs to diff_queue, + * force diff_tree_oid() to feed all filepairs to diff_queue, * and this code needs to be after diff_setup_done(), which * usually makes find-copies-harder imply copy detection. */ @@@ -1259,9 -1258,9 +1258,9 @@@ if (is_null_oid(&target->commit->object.oid)) do_diff_cache(&parent->tree->object.oid, &diff_opts); else - diff_tree_sha1(parent->tree->object.oid.hash, - target->commit->tree->object.oid.hash, - "", &diff_opts); + diff_tree_oid(&parent->tree->object.oid, + &target->commit->tree->object.oid, + "", &diff_opts); if (!DIFF_OPT_TST(&diff_opts, FIND_COPIES_HARDER)) diffcore_std(&diff_opts); diff --combined branch.c index a8a548ccf2,2347cb8649..36541d05cd --- a/branch.c +++ b/branch.c @@@ -1,6 -1,5 +1,6 @@@ #include "git-compat-util.h" #include "cache.h" +#include "config.h" #include "branch.h" #include "refs.h" #include "remote.h" @@@ -25,8 -24,7 +25,7 @@@ static int find_tracked_branch(struct r } else { free(tracking->spec.src); if (tracking->src) { - free(tracking->src); - tracking->src = NULL; + FREE_AND_NULL(tracking->src); } } tracking->spec.src = NULL; diff --combined builtin/am.c index 7c7b916d23,80368b6fe6..c973bd96dc --- a/builtin/am.c +++ b/builtin/am.c @@@ -4,7 -4,6 +4,7 @@@ * Based on git-am.sh by Junio C Hamano. */ #include "cache.h" +#include "config.h" #include "builtin.h" #include "exec_cmd.h" #include "parse-options.h" @@@ -484,8 -483,7 +484,7 @@@ static int run_applypatch_msg_hook(stru ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL); if (!ret) { - free(state->msg); - state->msg = NULL; + FREE_AND_NULL(state->msg); if (read_commit_msg(state) < 0) die(_("'%s' was deleted by the applypatch-msg hook"), am_path(state, "final-commit")); @@@ -564,7 -562,7 +563,7 @@@ static int copy_notes_for_rebase(const goto finish; } - if (copy_note_for_rewrite(c, from_obj.hash, to_obj.hash)) + if (copy_note_for_rewrite(c, &from_obj, &to_obj)) ret = error(_("Failed to copy notes from '%s' to '%s'"), oid_to_hex(&from_obj), oid_to_hex(&to_obj)); } @@@ -1074,17 -1072,10 +1073,10 @@@ static void am_next(struct am_state *st { struct object_id head; - free(state->author_name); - state->author_name = NULL; - - free(state->author_email); - state->author_email = NULL; - - free(state->author_date); - state->author_date = NULL; - - free(state->msg); - state->msg = NULL; + FREE_AND_NULL(state->author_name); + FREE_AND_NULL(state->author_email); + FREE_AND_NULL(state->author_date); + FREE_AND_NULL(state->msg); state->msg_len = 0; unlink(am_path(state, "author-script")); diff --combined builtin/clean.c index ed954134d2,bff5a07330..057fc97fe4 --- a/builtin/clean.c +++ b/builtin/clean.c @@@ -8,7 -8,6 +8,7 @@@ #include "builtin.h" #include "cache.h" +#include "config.h" #include "dir.h" #include "parse-options.h" #include "string-list.h" @@@ -838,8 -837,7 +838,7 @@@ static void interactive_main_loop(void int ret; ret = menus[*chosen].fn(); if (ret != MENU_RETURN_NO_LOOP) { - free(chosen); - chosen = NULL; + FREE_AND_NULL(chosen); if (!del_list.nr) { clean_print_color(CLEAN_COLOR_ERROR); printf_ln(_("No more files to clean, exiting.")); @@@ -852,8 -850,7 +851,7 @@@ quit_cmd(); } - free(chosen); - chosen = NULL; + FREE_AND_NULL(chosen); break; } } diff --combined builtin/config.c index 82db29fae7,18c2158630..70ff231e9c --- a/builtin/config.c +++ b/builtin/config.c @@@ -1,6 -1,5 +1,6 @@@ #include "builtin.h" #include "cache.h" +#include "config.h" #include "color.h" #include "parse-options.h" #include "urlmatch.h" @@@ -215,8 -214,7 +215,7 @@@ static int get_value(const char *key_, key_regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(key_regexp, key, REG_EXTENDED)) { error("invalid key pattern: %s", key_); - free(key_regexp); - key_regexp = NULL; + FREE_AND_NULL(key_regexp); ret = CONFIG_INVALID_PATTERN; goto free_strings; } @@@ -236,15 -234,14 +235,14 @@@ regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(regexp, regex_, REG_EXTENDED)) { error("invalid pattern: %s", regex_); - free(regexp); - regexp = NULL; + FREE_AND_NULL(regexp); ret = CONFIG_INVALID_PATTERN; goto free_strings; } } - git_config_with_options(collect_config, &values, - &given_config_source, &config_options); + config_with_options(collect_config, &values, + &given_config_source, &config_options); ret = !values.nr; @@@ -321,8 -318,8 +319,8 @@@ static void get_color(const char *var, get_color_slot = var; get_color_found = 0; parsed_color[0] = '\0'; - git_config_with_options(git_get_color_config, NULL, - &given_config_source, &config_options); + config_with_options(git_get_color_config, NULL, + &given_config_source, &config_options); if (!get_color_found && def_color) { if (color_parse(def_color, parsed_color) < 0) @@@ -353,8 -350,8 +351,8 @@@ static int get_colorbool(const char *va get_colorbool_found = -1; get_diff_color_found = -1; get_color_ui_found = -1; - git_config_with_options(git_get_colorbool_config, NULL, - &given_config_source, &config_options); + config_with_options(git_get_colorbool_config, NULL, + &given_config_source, &config_options); if (get_colorbool_found < 0) { if (!strcmp(get_colorbool_slot, "color.diff")) @@@ -442,8 -439,8 +440,8 @@@ static int get_urlmatch(const char *var show_keys = 1; } - git_config_with_options(urlmatch_config_entry, &config, - &given_config_source, &config_options); + config_with_options(urlmatch_config_entry, &config, + &given_config_source, &config_options); ret = !values.nr; @@@ -539,10 -536,6 +537,10 @@@ int cmd_config(int argc, const char **a config_options.respect_includes = !given_config_source.file; else config_options.respect_includes = respect_includes_opt; + if (!nongit) { + config_options.commondir = get_git_common_dir(); + config_options.git_dir = get_git_dir(); + } if (end_null) { term = '\0'; @@@ -587,9 -580,9 +585,9 @@@ if (actions == ACTION_LIST) { check_argc(argc, 0, 0); - if (git_config_with_options(show_all_config, NULL, - &given_config_source, - &config_options) < 0) { + if (config_with_options(show_all_config, NULL, + &given_config_source, + &config_options) < 0) { if (given_config_source.file) die_errno("unable to read config file '%s'", given_config_source.file); diff --combined builtin/index-pack.c index edc1a91d89,f3b16520c2..ad4de35178 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@@ -1,5 -1,4 +1,5 @@@ #include "builtin.h" +#include "config.h" #include "delta.h" #include "pack.h" #include "csum-file.h" @@@ -389,8 -388,7 +389,7 @@@ static struct base_data *alloc_base_dat static void free_base_data(struct base_data *c) { if (c->data) { - free(c->data); - c->data = NULL; + FREE_AND_NULL(c->data); get_thread_data()->base_cache_used -= c->size; } } @@@ -606,8 -604,7 +605,7 @@@ static void *unpack_data(struct object_ git_inflate_end(&stream); free(inbuf); if (consume) { - free(data); - data = NULL; + FREE_AND_NULL(data); } return data; } diff --combined builtin/pack-objects.c index d5e96ed2d0,790615b2c3..f4a8441fe9 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@@ -1,6 -1,5 +1,6 @@@ #include "builtin.h" #include "cache.h" +#include "config.h" #include "attr.h" #include "object.h" #include "blob.h" @@@ -265,8 -264,7 +265,7 @@@ static unsigned long write_no_reuse_obj * make sure no cached delta data remains from a * previous attempt before a pack split occurred. */ - free(entry->delta_data); - entry->delta_data = NULL; + FREE_AND_NULL(entry->delta_data); entry->z_delta_size = 0; } else if (entry->delta_data) { size = entry->delta_size; @@@ -1376,12 -1374,10 +1375,10 @@@ static void cleanup_preferred_base(void if (!pbase_tree_cache[i]) continue; free(pbase_tree_cache[i]->tree_data); - free(pbase_tree_cache[i]); - pbase_tree_cache[i] = NULL; + FREE_AND_NULL(pbase_tree_cache[i]); } - free(done_pbase_paths); - done_pbase_paths = NULL; + FREE_AND_NULL(done_pbase_paths); done_pbase_paths_num = done_pbase_paths_alloc = 0; } @@@ -1971,8 -1967,7 +1968,7 @@@ static unsigned long free_unpacked(stru n->index = NULL; if (n->data) { freed_mem += n->entry->size; - free(n->data); - n->data = NULL; + FREE_AND_NULL(n->data); } n->entry = NULL; n->depth = 0; diff --combined builtin/unpack-objects.c index 193f8b9d57,60bfe48789..689a29fac1 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@@ -1,6 -1,5 +1,6 @@@ #include "builtin.h" #include "cache.h" +#include "config.h" #include "object.h" #include "delta.h" #include "pack.h" @@@ -113,8 -112,7 +113,7 @@@ static void *get_data(unsigned long siz break; if (ret != Z_OK) { error("inflate returned %d", ret); - free(buf); - buf = NULL; + FREE_AND_NULL(buf); if (!recover) exit(1); has_errors = 1; diff --combined builtin/worktree.c index 0c5476ee9d,41d1c007a4..c98e2ce5f5 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "builtin.h" #include "dir.h" #include "parse-options.h" @@@ -300,10 -299,8 +300,8 @@@ static int add_worktree(const char *pat } is_junk = 0; - free(junk_work_tree); - free(junk_git_dir); - junk_work_tree = NULL; - junk_git_dir = NULL; + FREE_AND_NULL(junk_work_tree); + FREE_AND_NULL(junk_git_dir); done: if (ret || !opts->keep_locked) { diff --combined config.c index 6f0f8b30f3,0501a60dd2..1cd40a5fe6 --- a/config.c +++ b/config.c @@@ -6,7 -6,6 +6,7 @@@ * */ #include "cache.h" +#include "config.h" #include "lockfile.h" #include "exec_cmd.h" #include "strbuf.h" @@@ -219,6 -218,8 +219,6 @@@ static int include_by_gitdir(const stru if (opts->git_dir) git_dir = opts->git_dir; - else if (have_git_dir()) - git_dir = get_git_dir(); else goto done; @@@ -394,8 -395,7 +394,7 @@@ static int git_config_parse_key_1(cons out_free_ret_1: if (store_key) { - free(*store_key); - *store_key = NULL; + FREE_AND_NULL(*store_key); } return -CONFIG_INVALID_KEY; } @@@ -603,8 -603,7 +602,8 @@@ static int get_value(config_fn_t fn, vo */ cf->linenr--; ret = fn(name->buf, value, data); - cf->linenr++; + if (ret >= 0) + cf->linenr++; return ret; } @@@ -1545,8 -1544,10 +1544,8 @@@ static int do_git_config_sequence(cons char *user_config = expand_user_path("~/.gitconfig", 0); char *repo_config; - if (opts->git_dir) - repo_config = mkpathdup("%s/config", opts->git_dir); - else if (have_git_dir()) - repo_config = git_pathdup("config"); + if (opts->commondir) + repo_config = mkpathdup("%s/config", opts->commondir); else repo_config = NULL; @@@ -1577,9 -1578,9 +1576,9 @@@ return ret; } -int git_config_with_options(config_fn_t fn, void *data, - struct git_config_source *config_source, - const struct config_options *opts) +int config_with_options(config_fn_t fn, void *data, + struct git_config_source *config_source, + const struct config_options *opts) { struct config_include_data inc = CONFIG_INCLUDE_INIT; @@@ -1610,14 -1611,9 +1609,14 @@@ static void git_config_raw(config_fn_t struct config_options opts = {0}; opts.respect_includes = 1; - if (git_config_with_options(fn, data, NULL, &opts) < 0) + if (have_git_dir()) { + opts.commondir = get_git_common_dir(); + opts.git_dir = get_git_dir(); + } + + if (config_with_options(fn, data, NULL, &opts) < 0) /* - * git_config_with_options() normally returns only + * config_with_options() normally returns only * zero, as most errors are fatal, and * non-fatal potential errors are guarded by "if" * statements that are entered only when no error is @@@ -1656,13 -1652,11 +1655,13 @@@ static void configset_iter(struct confi void read_early_config(config_fn_t cb, void *data) { struct config_options opts = {0}; - struct strbuf buf = STRBUF_INIT; + struct strbuf commondir = STRBUF_INIT; + struct strbuf gitdir = STRBUF_INIT; opts.respect_includes = 1; - if (have_git_dir()) + if (have_git_dir()) { + opts.commondir = get_git_common_dir(); opts.git_dir = get_git_dir(); /* * When setup_git_directory() was not yet asked to discover the @@@ -1672,15 -1666,12 +1671,15 @@@ * notably, the current working directory is still the same after the * call). */ - else if (discover_git_directory(&buf)) - opts.git_dir = buf.buf; + } else if (!discover_git_directory(&commondir, &gitdir)) { + opts.commondir = commondir.buf; + opts.git_dir = gitdir.buf; + } - git_config_with_options(cb, data, NULL, &opts); + config_with_options(cb, data, NULL, &opts); - strbuf_release(&buf); + strbuf_release(&commondir); + strbuf_release(&gitdir); } static void git_config_check_init(void); diff --combined credential.c index 67a523353b,924ab58538..9747f47b18 --- a/credential.c +++ b/credential.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "credential.h" #include "string-list.h" #include "run-command.h" @@@ -94,8 -93,7 +94,7 @@@ static void credential_apply_config(str c->configured = 1; if (!c->use_http_path && proto_is_http(c->protocol)) { - free(c->path); - c->path = NULL; + FREE_AND_NULL(c->path); } } @@@ -315,10 -313,8 +314,8 @@@ void credential_reject(struct credentia for (i = 0; i < c->helpers.nr; i++) credential_do(c, c->helpers.items[i].string, "erase"); - free(c->username); - c->username = NULL; - free(c->password); - c->password = NULL; + FREE_AND_NULL(c->username); + FREE_AND_NULL(c->password); c->approved = 0; } diff --combined diff-lib.c index 0c0e20f7c0,7528f4163f..2a52b07954 --- a/diff-lib.c +++ b/diff-lib.c @@@ -101,7 -101,7 +101,7 @@@ int run_diff_files(struct rev_info *rev struct cache_entry *ce = active_cache[i]; int changed; unsigned dirty_submodule = 0; - const unsigned char *old_sha1, *new_sha1; + const struct object_id *old_oid, *new_oid; if (diff_can_quit_early(&revs->diffopt)) break; @@@ -179,8 -179,7 +179,7 @@@ free(dpath); continue; } - free(dpath); - dpath = NULL; + FREE_AND_NULL(dpath); /* * Show the diff for the 'ce' if we found the one @@@ -210,14 -209,14 +209,14 @@@ continue; } diff_addremove(&revs->diffopt, '-', ce->ce_mode, - ce->oid.hash, + &ce->oid, !is_null_oid(&ce->oid), ce->name, 0); continue; } else if (revs->diffopt.ita_invisible_in_index && ce_intent_to_add(ce)) { diff_addremove(&revs->diffopt, '+', ce->ce_mode, - EMPTY_BLOB_SHA1_BIN, 0, + &empty_tree_oid, 0, ce->name, 0); continue; } @@@ -233,12 -232,12 +232,12 @@@ continue; } oldmode = ce->ce_mode; - old_sha1 = ce->oid.hash; - new_sha1 = changed ? null_sha1 : ce->oid.hash; + old_oid = &ce->oid; + new_oid = changed ? &null_oid : &ce->oid; diff_change(&revs->diffopt, oldmode, newmode, - old_sha1, new_sha1, - !is_null_sha1(old_sha1), - !is_null_sha1(new_sha1), + old_oid, new_oid, + !is_null_oid(old_oid), + !is_null_oid(new_oid), ce->name, 0, dirty_submodule); } @@@ -255,21 -254,21 +254,21 @@@ static void diff_index_show_file(struct rev_info *revs, const char *prefix, const struct cache_entry *ce, - const unsigned char *sha1, int sha1_valid, + const struct object_id *oid, int oid_valid, unsigned int mode, unsigned dirty_submodule) { diff_addremove(&revs->diffopt, prefix[0], mode, - sha1, sha1_valid, ce->name, dirty_submodule); + oid, oid_valid, ce->name, dirty_submodule); } static int get_stat_data(const struct cache_entry *ce, - const unsigned char **sha1p, + const struct object_id **oidp, unsigned int *modep, int cached, int match_missing, unsigned *dirty_submodule, struct diff_options *diffopt) { - const unsigned char *sha1 = ce->oid.hash; + const struct object_id *oid = &ce->oid; unsigned int mode = ce->ce_mode; if (!cached && !ce_uptodate(ce)) { @@@ -280,7 -279,7 +279,7 @@@ return -1; else if (changed) { if (match_missing) { - *sha1p = sha1; + *oidp = oid; *modep = mode; return 0; } @@@ -290,11 -289,11 +289,11 @@@ 0, dirty_submodule); if (changed) { mode = ce_mode_from_stat(ce, st.st_mode); - sha1 = null_sha1; + oid = &null_oid; } } - *sha1p = sha1; + *oidp = oid; *modep = mode; return 0; } @@@ -303,7 -302,7 +302,7 @@@ static void show_new_file(struct rev_in const struct cache_entry *new, int cached, int match_missing) { - const unsigned char *sha1; + const struct object_id *oid; unsigned int mode; unsigned dirty_submodule = 0; @@@ -311,11 -310,11 +310,11 @@@ * New file in the index: it might actually be different in * the working tree. */ - if (get_stat_data(new, &sha1, &mode, cached, match_missing, + if (get_stat_data(new, &oid, &mode, cached, match_missing, &dirty_submodule, &revs->diffopt) < 0) return; - diff_index_show_file(revs, "+", new, sha1, !is_null_sha1(sha1), mode, dirty_submodule); + diff_index_show_file(revs, "+", new, oid, !is_null_oid(oid), mode, dirty_submodule); } static int show_modified(struct rev_info *revs, @@@ -325,20 -324,20 +324,20 @@@ int cached, int match_missing) { unsigned int mode, oldmode; - const unsigned char *sha1; + const struct object_id *oid; unsigned dirty_submodule = 0; - if (get_stat_data(new, &sha1, &mode, cached, match_missing, + if (get_stat_data(new, &oid, &mode, cached, match_missing, &dirty_submodule, &revs->diffopt) < 0) { if (report_missing) diff_index_show_file(revs, "-", old, - old->oid.hash, 1, old->ce_mode, + &old->oid, 1, old->ce_mode, 0); return -1; } if (revs->combine_merges && !cached && - (hashcmp(sha1, old->oid.hash) || oidcmp(&old->oid, &new->oid))) { + (oidcmp(oid, &old->oid) || oidcmp(&old->oid, &new->oid))) { struct combine_diff_path *p; int pathlen = ce_namelen(new); @@@ -362,12 -361,12 +361,12 @@@ } oldmode = old->ce_mode; - if (mode == oldmode && !hashcmp(sha1, old->oid.hash) && !dirty_submodule && + if (mode == oldmode && !oidcmp(oid, &old->oid) && !dirty_submodule && !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER)) return 0; diff_change(&revs->diffopt, oldmode, mode, - old->oid.hash, sha1, 1, !is_null_sha1(sha1), + &old->oid, oid, 1, !is_null_oid(oid), old->name, 0, dirty_submodule); return 0; } @@@ -409,7 -408,7 +408,7 @@@ static void do_oneway_diff(struct unpac struct diff_filepair *pair; pair = diff_unmerge(&revs->diffopt, idx->name); if (tree) - fill_filespec(pair->one, tree->oid.hash, 1, + fill_filespec(pair->one, &tree->oid, 1, tree->ce_mode); return; } @@@ -426,7 -425,7 +425,7 @@@ * Something removed from the tree? */ if (!idx) { - diff_index_show_file(revs, "-", tree, tree->oid.hash, 1, + diff_index_show_file(revs, "-", tree, &tree->oid, 1, tree->ce_mode, 0); return; } diff --combined diff.c index 41295d4ea9,3561adf49f..00b4c86698 --- a/diff.c +++ b/diff.c @@@ -2,7 -2,6 +2,7 @@@ * Copyright (C) 2005 Junio C Hamano */ #include "cache.h" +#include "config.h" #include "tempfile.h" #include "quote.h" #include "diff.h" @@@ -1219,8 -1218,7 +1219,7 @@@ static void free_diff_words_data(struc regfree(ecbdata->diff_words->word_regex); free(ecbdata->diff_words->word_regex); } - free(ecbdata->diff_words); - ecbdata->diff_words = NULL; + FREE_AND_NULL(ecbdata->diff_words); } } @@@ -2703,13 -2701,13 +2702,13 @@@ void free_filespec(struct diff_filespe } } -void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, - int sha1_valid, unsigned short mode) +void fill_filespec(struct diff_filespec *spec, const struct object_id *oid, + int oid_valid, unsigned short mode) { if (mode) { spec->mode = canon_mode(mode); - hashcpy(spec->oid.hash, sha1); - spec->oid_valid = sha1_valid; + oidcpy(&spec->oid, oid); + spec->oid_valid = oid_valid; } } @@@ -2718,7 -2716,7 +2717,7 @@@ * the work tree has that object contents, return true, so that * prepare_temp_file() does not have to inflate and extract. */ -static int reuse_worktree_file(const char *name, const unsigned char *sha1, int want_file) +static int reuse_worktree_file(const char *name, const struct object_id *oid, int want_file) { const struct cache_entry *ce; struct stat st; @@@ -2749,14 -2747,14 +2748,14 @@@ * objects however would tend to be slower as they need * to be individually opened and inflated. */ - if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1)) + if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(oid->hash)) return 0; /* * Similarly, if we'd have to convert the file contents anyway, that * makes the optimization not worthwhile. */ - if (!want_file && would_convert_to_git(name)) + if (!want_file && would_convert_to_git(&the_index, name)) return 0; len = strlen(name); @@@ -2769,7 -2767,7 +2768,7 @@@ * This is not the sha1 we are looking for, or * unreusable because it is not a regular file. */ - if (hashcmp(sha1, ce->oid.hash) || !S_ISREG(ce->ce_mode)) + if (oidcmp(oid, &ce->oid) || !S_ISREG(ce->ce_mode)) return 0; /* @@@ -2843,7 -2841,7 +2842,7 @@@ int diff_populate_filespec(struct diff_ return diff_populate_gitlink(s, size_only); if (!s->oid_valid || - reuse_worktree_file(s->path, s->oid.hash, 0)) { + reuse_worktree_file(s->path, &s->oid, 0)) { struct strbuf buf = STRBUF_INIT; struct stat st; int fd; @@@ -2878,7 -2876,7 +2877,7 @@@ * point if the path requires us to run the content * conversion. */ - if (size_only && !would_convert_to_git(s->path)) + if (size_only && !would_convert_to_git(&the_index, s->path)) return 0; /* @@@ -2905,7 -2903,7 +2904,7 @@@ /* * Convert from working tree format to canonical git format */ - if (convert_to_git(s->path, s->data, s->size, &buf, crlf_warn)) { + if (convert_to_git(&the_index, s->path, s->data, s->size, &buf, crlf_warn)) { size_t size = 0; munmap(s->data, s->size); s->should_munmap = 0; @@@ -2952,8 -2950,7 +2951,7 @@@ void diff_free_filespec_blob(struct dif void diff_free_filespec_data(struct diff_filespec *s) { diff_free_filespec_blob(s); - free(s->cnt_data); - s->cnt_data = NULL; + FREE_AND_NULL(s->cnt_data); } static void prep_temp_blob(const char *path, struct diff_tempfile *temp, @@@ -3009,7 -3006,7 +3007,7 @@@ static struct diff_tempfile *prepare_te if (!S_ISGITLINK(one->mode) && (!one->oid_valid || - reuse_worktree_file(name, one->oid.hash, 1))) { + reuse_worktree_file(name, &one->oid, 1))) { struct stat st; if (lstat(name, &st) < 0) { if (errno == ENOENT) @@@ -3031,13 -3028,13 +3029,13 @@@ /* we can borrow from the file in the work tree */ temp->name = name; if (!one->oid_valid) - sha1_to_hex_r(temp->hex, null_sha1); + oid_to_hex_r(temp->hex, &null_oid); else oid_to_hex_r(temp->hex, &one->oid); /* Even though we may sometimes borrow the * contents from the work tree, we always want * one->mode. mode is trustworthy even when - * !(one->sha1_valid), as long as + * !(one->oid_valid), as long as * DIFF_FILE_VALID(one). */ xsnprintf(temp->mode, sizeof(temp->mode), "%06o", one->mode); @@@ -3240,7 -3237,7 +3238,7 @@@ static void run_diff_cmd(const char *pg fprintf(o->file, "* Unmerged path %s\n", name); } -static void diff_fill_sha1_info(struct diff_filespec *one) +static void diff_fill_oid_info(struct diff_filespec *one) { if (DIFF_FILE_VALID(one)) { if (!one->oid_valid) { @@@ -3299,8 -3296,8 +3297,8 @@@ static void run_diff(struct diff_filepa return; } - diff_fill_sha1_info(one); - diff_fill_sha1_info(two); + diff_fill_oid_info(one); + diff_fill_oid_info(two); if (!pgm && DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) && @@@ -3345,8 -3342,8 +3343,8 @@@ static void run_diffstat(struct diff_fi if (o->prefix_length) strip_prefix(o->prefix_length, &name, &other); - diff_fill_sha1_info(p->one); - diff_fill_sha1_info(p->two); + diff_fill_oid_info(p->one); + diff_fill_oid_info(p->two); builtin_diffstat(name, other, p->one, p->two, diffstat, o, p); } @@@ -3369,8 -3366,8 +3367,8 @@@ static void run_checkdiff(struct diff_f if (o->prefix_length) strip_prefix(o->prefix_length, &name, &other); - diff_fill_sha1_info(p->one); - diff_fill_sha1_info(p->two); + diff_fill_oid_info(p->one); + diff_fill_oid_info(p->two); builtin_checkdiff(name, other, attr_path, p->one, p->two, o); } @@@ -4583,7 -4580,7 +4581,7 @@@ static void patch_id_add_mode(git_SHA_C } /* returns 0 upon success, and writes result into sha1 */ -static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only) +static int diff_get_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only) { struct diff_queue_struct *q = &diff_queued_diff; int i; @@@ -4615,8 -4612,8 +4613,8 @@@ if (DIFF_PAIR_UNMERGED(p)) continue; - diff_fill_sha1_info(p->one); - diff_fill_sha1_info(p->two); + diff_fill_oid_info(p->one); + diff_fill_oid_info(p->two); len1 = remove_space(p->one->path, strlen(p->one->path)); len2 = remove_space(p->two->path, strlen(p->two->path)); @@@ -4655,9 -4652,9 +4653,9 @@@ if (diff_filespec_is_binary(p->one) || diff_filespec_is_binary(p->two)) { git_SHA1_Update(&ctx, oid_to_hex(&p->one->oid), - 40); + GIT_SHA1_HEXSZ); git_SHA1_Update(&ctx, oid_to_hex(&p->two->oid), - 40); + GIT_SHA1_HEXSZ); continue; } @@@ -4670,15 -4667,15 +4668,15 @@@ p->one->path); } - git_SHA1_Final(sha1, &ctx); + git_SHA1_Final(oid->hash, &ctx); return 0; } -int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only) +int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only) { struct diff_queue_struct *q = &diff_queued_diff; int i; - int result = diff_get_patch_id(options, sha1, diff_header_only); + int result = diff_get_patch_id(options, oid, diff_header_only); for (i = 0; i < q->nr; i++) diff_free_filepair(q->queue[i]); @@@ -5078,8 -5075,8 +5076,8 @@@ static int is_submodule_ignored(const c void diff_addremove(struct diff_options *options, int addremove, unsigned mode, - const unsigned char *sha1, - int sha1_valid, + const struct object_id *oid, + int oid_valid, const char *concatpath, unsigned dirty_submodule) { struct diff_filespec *one, *two; @@@ -5111,9 -5108,9 +5109,9 @@@ two = alloc_filespec(concatpath); if (addremove != '+') - fill_filespec(one, sha1, sha1_valid, mode); + fill_filespec(one, oid, oid_valid, mode); if (addremove != '-') { - fill_filespec(two, sha1, sha1_valid, mode); + fill_filespec(two, oid, oid_valid, mode); two->dirty_submodule = dirty_submodule; } @@@ -5124,9 -5121,9 +5122,9 @@@ void diff_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, - const unsigned char *old_sha1, - const unsigned char *new_sha1, - int old_sha1_valid, int new_sha1_valid, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, const char *concatpath, unsigned old_dirty_submodule, unsigned new_dirty_submodule) { @@@ -5139,8 -5136,8 +5137,8 @@@ if (DIFF_OPT_TST(options, REVERSE_DIFF)) { SWAP(old_mode, new_mode); - SWAP(old_sha1, new_sha1); - SWAP(old_sha1_valid, new_sha1_valid); + SWAP(old_oid, new_oid); + SWAP(old_oid_valid, new_oid_valid); SWAP(old_dirty_submodule, new_dirty_submodule); } @@@ -5150,8 -5147,8 +5148,8 @@@ one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); - fill_filespec(one, old_sha1, old_sha1_valid, old_mode); - fill_filespec(two, new_sha1, new_sha1_valid, new_mode); + fill_filespec(one, old_oid, old_oid_valid, old_mode); + fill_filespec(two, new_oid, new_oid_valid, new_mode); one->dirty_submodule = old_dirty_submodule; two->dirty_submodule = new_dirty_submodule; p = diff_queue(&diff_queued_diff, one, two); @@@ -5278,7 -5275,7 +5276,7 @@@ int textconv_object(const char *path struct userdiff_driver *textconv; df = alloc_filespec(path); - fill_filespec(df, oid->hash, oid_valid, mode); + fill_filespec(df, oid, oid_valid, mode); textconv = get_textconv(df); if (!textconv) { free_filespec(df); diff --combined diffcore-rename.c index 03d1e8d40b,6d8daf9c00..1e4678b7d7 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@@ -60,7 -60,7 +60,7 @@@ static int add_rename_dst(struct diff_f memmove(rename_dst + first + 1, rename_dst + first, (rename_dst_nr - first - 1) * sizeof(*rename_dst)); rename_dst[first].two = alloc_filespec(two->path); - fill_filespec(rename_dst[first].two, two->oid.hash, two->oid_valid, + fill_filespec(rename_dst[first].two, &two->oid, two->oid_valid, two->mode); rename_dst[first].pair = NULL; return 0; @@@ -464,7 -464,7 +464,7 @@@ void diffcore_rename(struct diff_option strcmp(options->single_follow, p->two->path)) continue; /* not interested */ else if (!DIFF_OPT_TST(options, RENAME_EMPTY) && - is_empty_blob_sha1(p->two->oid.hash)) + is_empty_blob_oid(&p->two->oid)) continue; else if (add_rename_dst(p->two) < 0) { warning("skipping rename detection, detected" @@@ -474,7 -474,7 +474,7 @@@ } } else if (!DIFF_OPT_TST(options, RENAME_EMPTY) && - is_empty_blob_sha1(p->one->oid.hash)) + is_empty_blob_oid(&p->one->oid)) continue; else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) { /* @@@ -667,11 -667,9 +667,9 @@@ for (i = 0; i < rename_dst_nr; i++) free_filespec(rename_dst[i].two); - free(rename_dst); - rename_dst = NULL; + FREE_AND_NULL(rename_dst); rename_dst_nr = rename_dst_alloc = 0; - free(rename_src); - rename_src = NULL; + FREE_AND_NULL(rename_src); rename_src_nr = rename_src_alloc = 0; return; } diff --combined dir.c index f6795473f7,7dc168b806..332f9d8095 --- a/dir.c +++ b/dir.c @@@ -9,7 -9,6 +9,7 @@@ */ #define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" +#include "config.h" #include "dir.h" #include "attr.h" #include "refs.h" @@@ -53,15 -52,6 +53,15 @@@ static enum path_treatment read_directo static int get_dtype(struct dirent *de, struct index_state *istate, const char *path, int len); +int count_slashes(const char *s) +{ + int cnt = 0; + while (*s) + if (*s++ == '/') + cnt++; + return cnt; +} + int fspathcmp(const char *a, const char *b) { return ignore_case ? strcasecmp(a, b) : strcmp(a, b); @@@ -805,7 -795,7 +805,7 @@@ static int add_excludes(const char *fna (pos = index_name_pos(istate, fname, strlen(fname))) >= 0 && !ce_stage(istate->cache[pos]) && ce_uptodate(istate->cache[pos]) && - !would_convert_to_git(fname)) + !would_convert_to_git(istate, fname)) hashcpy(sha1_stat->sha1, istate->cache[pos]->oid.hash); else @@@ -2127,8 -2117,7 +2127,7 @@@ int read_directory(struct dir_struct *d for (i = j = 0; j < dir->nr; j++) { if (i && check_dir_entry_contains(dir->entries[i - 1], dir->entries[j])) { - free(dir->entries[j]); - dir->entries[j] = NULL; + FREE_AND_NULL(dir->entries[j]); } else { dir->entries[i++] = dir->entries[j]; } @@@ -2154,8 -2143,7 +2153,7 @@@ dir->untracked->dir_invalidated)) istate->cache_changed |= UNTRACKED_CHANGED; if (dir->untracked != istate->untracked) { - free(dir->untracked); - dir->untracked = NULL; + FREE_AND_NULL(dir->untracked); } } return dir->nr; @@@ -2498,8 -2486,7 +2496,7 @@@ void write_untracked_extension(struct s strbuf_addbuf(out, &untracked->ident); strbuf_add(out, ouc, ouc_size(len)); - free(ouc); - ouc = NULL; + FREE_AND_NULL(ouc); if (!untracked->root) { varint_len = encode_varint(0, varbuf); diff --combined fast-import.c index 12b90fe9e3,eeab927d5a..a959161b46 --- a/fast-import.c +++ b/fast-import.c @@@ -154,7 -154,6 +154,7 @@@ Format of STDIN stream #include "builtin.h" #include "cache.h" +#include "config.h" #include "lockfile.h" #include "object.h" #include "blob.h" @@@ -281,7 -280,7 +281,7 @@@ struct recent_command }; /* Configured limits on output */ -static unsigned long max_depth = 10; +static unsigned long max_depth = 50; static off_t max_packsize; static int unpack_limit = 100; static int force_update; @@@ -1064,8 -1063,7 +1064,7 @@@ discard_pack close(pack_data->pack_fd); unlink_or_warn(pack_data->pack_name); } - free(pack_data); - pack_data = NULL; + FREE_AND_NULL(pack_data); running = 0; /* We can't carry a delta across packfiles. */ @@@ -1150,8 -1148,7 +1149,7 @@@ static int store_object /* We cannot carry a delta into the new pack. */ if (delta) { - free(delta); - delta = NULL; + FREE_AND_NULL(delta); git_deflate_init(&s, pack_compression_level); s.next_in = (void *)dat->buf; diff --combined gpg-interface.c index 8ab32df457,3f377f89d0..d936f3a32f --- a/gpg-interface.c +++ b/gpg-interface.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "run-command.h" #include "strbuf.h" #include "gpg-interface.h" @@@ -14,16 -13,11 +14,11 @@@ static const char *gpg_program = "gpg" void signature_check_clear(struct signature_check *sigc) { - free(sigc->payload); - free(sigc->gpg_output); - free(sigc->gpg_status); - free(sigc->signer); - free(sigc->key); - sigc->payload = NULL; - sigc->gpg_output = NULL; - sigc->gpg_status = NULL; - sigc->signer = NULL; - sigc->key = NULL; + FREE_AND_NULL(sigc->payload); + FREE_AND_NULL(sigc->gpg_output); + FREE_AND_NULL(sigc->gpg_status); + FREE_AND_NULL(sigc->signer); + FREE_AND_NULL(sigc->key); } static struct { diff --combined grep.c index 1fca83be86,909f35a984..98733db623 --- a/grep.c +++ b/grep.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "grep.h" #include "userdiff.h" #include "xdiff-interface.h" @@@ -180,37 -179,22 +180,37 @@@ static void grep_set_pattern_type_optio case GREP_PATTERN_TYPE_BRE: opt->fixed = 0; opt->pcre1 = 0; + opt->pcre2 = 0; break; case GREP_PATTERN_TYPE_ERE: opt->fixed = 0; opt->pcre1 = 0; + opt->pcre2 = 0; opt->regflags |= REG_EXTENDED; break; case GREP_PATTERN_TYPE_FIXED: opt->fixed = 1; opt->pcre1 = 0; + opt->pcre2 = 0; break; case GREP_PATTERN_TYPE_PCRE: opt->fixed = 0; +#ifdef USE_LIBPCRE2 + opt->pcre1 = 0; + opt->pcre2 = 1; +#else + /* + * It's important that pcre1 always be assigned to + * even when there's no USE_LIBPCRE* defined. We still + * call the PCRE stub function, it just dies with + * "cannot use Perl-compatible regexes[...]". + */ opt->pcre1 = 1; + opt->pcre2 = 0; +#endif break; } } @@@ -381,22 -365,9 +381,22 @@@ static void compile_pcre1_regexp(struc if (!p->pcre1_regexp) compile_regexp_failed(p, error); - p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error); + p->pcre1_extra_info = pcre_study(p->pcre1_regexp, PCRE_STUDY_JIT_COMPILE, &error); if (!p->pcre1_extra_info && error) die("%s", error); + +#ifdef GIT_PCRE1_USE_JIT + pcre_config(PCRE_CONFIG_JIT, &p->pcre1_jit_on); + if (p->pcre1_jit_on == 1) { + p->pcre1_jit_stack = pcre_jit_stack_alloc(1, 1024 * 1024); + if (!p->pcre1_jit_stack) + die("Couldn't allocate PCRE JIT stack"); + pcre_assign_jit_stack(p->pcre1_extra_info, NULL, p->pcre1_jit_stack); + } else if (p->pcre1_jit_on != 0) { + die("BUG: The pcre1_jit_on variable should be 0 or 1, not %d", + p->pcre1_jit_on); + } +#endif } static int pcre1match(struct grep_pat *p, const char *line, const char *eol, @@@ -407,19 -378,8 +407,19 @@@ if (eflags & REG_NOTBOL) flags |= PCRE_NOTBOL; - ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line, eol - line, - 0, flags, ovector, ARRAY_SIZE(ovector)); +#ifdef GIT_PCRE1_USE_JIT + if (p->pcre1_jit_on) { + ret = pcre_jit_exec(p->pcre1_regexp, p->pcre1_extra_info, line, + eol - line, 0, flags, ovector, + ARRAY_SIZE(ovector), p->pcre1_jit_stack); + } else +#endif + { + ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line, + eol - line, 0, flags, ovector, + ARRAY_SIZE(ovector)); + } + if (ret < 0 && ret != PCRE_ERROR_NOMATCH) die("pcre_exec failed with error code %d", ret); if (ret > 0) { @@@ -434,15 -394,7 +434,15 @@@ static void free_pcre1_regexp(struct grep_pat *p) { pcre_free(p->pcre1_regexp); - pcre_free(p->pcre1_extra_info); +#ifdef GIT_PCRE1_USE_JIT + if (p->pcre1_jit_on) { + pcre_free_study(p->pcre1_extra_info); + pcre_jit_stack_free(p->pcre1_jit_stack); + } else +#endif + { + pcre_free(p->pcre1_extra_info); + } pcre_free((void *)p->pcre1_tables); } #else /* !USE_LIBPCRE1 */ @@@ -462,127 -414,6 +462,127 @@@ static void free_pcre1_regexp(struct gr } #endif /* !USE_LIBPCRE1 */ +#ifdef USE_LIBPCRE2 +static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt) +{ + int error; + PCRE2_UCHAR errbuf[256]; + PCRE2_SIZE erroffset; + int options = PCRE2_MULTILINE; + const uint8_t *character_tables = NULL; + int jitret; + + assert(opt->pcre2); + + p->pcre2_compile_context = NULL; + + if (opt->ignore_case) { + if (has_non_ascii(p->pattern)) { + character_tables = pcre2_maketables(NULL); + p->pcre2_compile_context = pcre2_compile_context_create(NULL); + pcre2_set_character_tables(p->pcre2_compile_context, character_tables); + } + options |= PCRE2_CASELESS; + } + if (is_utf8_locale() && has_non_ascii(p->pattern)) + options |= PCRE2_UTF; + + p->pcre2_pattern = pcre2_compile((PCRE2_SPTR)p->pattern, + p->patternlen, options, &error, &erroffset, + p->pcre2_compile_context); + + if (p->pcre2_pattern) { + p->pcre2_match_data = pcre2_match_data_create_from_pattern(p->pcre2_pattern, NULL); + if (!p->pcre2_match_data) + die("Couldn't allocate PCRE2 match data"); + } else { + pcre2_get_error_message(error, errbuf, sizeof(errbuf)); + compile_regexp_failed(p, (const char *)&errbuf); + } + + pcre2_config(PCRE2_CONFIG_JIT, &p->pcre2_jit_on); + if (p->pcre2_jit_on == 1) { + jitret = pcre2_jit_compile(p->pcre2_pattern, PCRE2_JIT_COMPLETE); + if (jitret) + die("Couldn't JIT the PCRE2 pattern '%s', got '%d'\n", p->pattern, jitret); + p->pcre2_jit_stack = pcre2_jit_stack_create(1, 1024 * 1024, NULL); + if (!p->pcre2_jit_stack) + die("Couldn't allocate PCRE2 JIT stack"); + p->pcre2_match_context = pcre2_match_context_create(NULL); + if (!p->pcre2_match_context) + die("Couldn't allocate PCRE2 match context"); + pcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack); + } else if (p->pcre2_jit_on != 0) { + die("BUG: The pcre2_jit_on variable should be 0 or 1, not %d", + p->pcre1_jit_on); + } +} + +static int pcre2match(struct grep_pat *p, const char *line, const char *eol, + regmatch_t *match, int eflags) +{ + int ret, flags = 0; + PCRE2_SIZE *ovector; + PCRE2_UCHAR errbuf[256]; + + if (eflags & REG_NOTBOL) + flags |= PCRE2_NOTBOL; + + if (p->pcre2_jit_on) + ret = pcre2_jit_match(p->pcre2_pattern, (unsigned char *)line, + eol - line, 0, flags, p->pcre2_match_data, + NULL); + else + ret = pcre2_match(p->pcre2_pattern, (unsigned char *)line, + eol - line, 0, flags, p->pcre2_match_data, + NULL); + + if (ret < 0 && ret != PCRE2_ERROR_NOMATCH) { + pcre2_get_error_message(ret, errbuf, sizeof(errbuf)); + die("%s failed with error code %d: %s", + (p->pcre2_jit_on ? "pcre2_jit_match" : "pcre2_match"), ret, + errbuf); + } + if (ret > 0) { + ovector = pcre2_get_ovector_pointer(p->pcre2_match_data); + ret = 0; + match->rm_so = (int)ovector[0]; + match->rm_eo = (int)ovector[1]; + } + + return ret; +} + +static void free_pcre2_pattern(struct grep_pat *p) +{ + pcre2_compile_context_free(p->pcre2_compile_context); + pcre2_code_free(p->pcre2_pattern); + pcre2_match_data_free(p->pcre2_match_data); + pcre2_jit_stack_free(p->pcre2_jit_stack); + pcre2_match_context_free(p->pcre2_match_context); +} +#else /* !USE_LIBPCRE2 */ +static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt) +{ + /* + * Unreachable until USE_LIBPCRE2 becomes synonymous with + * USE_LIBPCRE. See the sibling comment in + * grep_set_pattern_type_option(). + */ + die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE"); +} + +static int pcre2match(struct grep_pat *p, const char *line, const char *eol, + regmatch_t *match, int eflags) +{ + return 1; +} + +static void free_pcre2_pattern(struct grep_pat *p) +{ +} +#endif /* !USE_LIBPCRE2 */ + static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt) { struct strbuf sb = STRBUF_INIT; @@@ -648,11 -479,6 +648,11 @@@ static void compile_regexp(struct grep_ return; } + if (opt->pcre2) { + compile_pcre2_pattern(p, opt); + return; + } + if (opt->pcre1) { compile_pcre1_regexp(p, opt); return; @@@ -1012,8 -838,6 +1012,8 @@@ void free_grep_patterns(struct grep_op kwsfree(p->kws); else if (p->pcre1_regexp) free_pcre1_regexp(p); + else if (p->pcre2_pattern) + free_pcre2_pattern(p); else regfree(&p->regexp); free(p->pattern); @@@ -1094,8 -918,6 +1094,8 @@@ static int patmatch(struct grep_pat *p hit = !fixmatch(p, line, eol, match); else if (p->pcre1_regexp) hit = !pcre1match(p, line, eol, match, eflags); + else if (p->pcre2_pattern) + hit = !pcre2match(p, line, eol, match, eflags); else hit = !regexec_buf(&p->regexp, line, eol - line, 1, match, eflags); @@@ -1585,11 -1407,11 +1585,11 @@@ static int fill_textconv_grep(struct us */ df = alloc_filespec(gs->path); switch (gs->type) { - case GREP_SOURCE_SHA1: + case GREP_SOURCE_OID: fill_filespec(df, gs->identifier, 1, 0100644); break; case GREP_SOURCE_FILE: - fill_filespec(df, null_sha1, 0, 0100644); + fill_filespec(df, &null_oid, 0, 0100644); break; default: die("BUG: attempt to textconv something without a path?"); @@@ -1929,8 -1751,9 +1929,8 @@@ void grep_source_init(struct grep_sourc * If the identifier is non-NULL (in the submodule case) it * will be a SHA1 that needs to be copied. */ - case GREP_SOURCE_SHA1: - gs->identifier = xmalloc(20); - hashcpy(gs->identifier, identifier); + case GREP_SOURCE_OID: + gs->identifier = oiddup(identifier); break; case GREP_SOURCE_BUF: gs->identifier = NULL; @@@ -1940,12 -1763,9 +1940,9 @@@ void grep_source_clear(struct grep_source *gs) { - free(gs->name); - gs->name = NULL; - free(gs->path); - gs->path = NULL; - free(gs->identifier); - gs->identifier = NULL; + FREE_AND_NULL(gs->name); + FREE_AND_NULL(gs->path); + FREE_AND_NULL(gs->identifier); grep_source_clear_data(gs); } @@@ -1953,10 -1773,9 +1950,9 @@@ void grep_source_clear_data(struct grep { switch (gs->type) { case GREP_SOURCE_FILE: - case GREP_SOURCE_SHA1: + case GREP_SOURCE_OID: case GREP_SOURCE_SUBMODULE: - free(gs->buf); - gs->buf = NULL; + FREE_AND_NULL(gs->buf); gs->size = 0; break; case GREP_SOURCE_BUF: @@@ -1965,7 -1784,7 +1961,7 @@@ } } -static int grep_source_load_sha1(struct grep_source *gs) +static int grep_source_load_oid(struct grep_source *gs) { enum object_type type; @@@ -1976,7 -1795,7 +1972,7 @@@ if (!gs->buf) return error(_("'%s': unable to read %s"), gs->name, - sha1_to_hex(gs->identifier)); + oid_to_hex(gs->identifier)); return 0; } @@@ -2022,8 -1841,8 +2018,8 @@@ static int grep_source_load(struct grep switch (gs->type) { case GREP_SOURCE_FILE: return grep_source_load_file(gs); - case GREP_SOURCE_SHA1: - return grep_source_load_sha1(gs); + case GREP_SOURCE_OID: + return grep_source_load_oid(gs); case GREP_SOURCE_BUF: return gs->buf ? 0 : -1; case GREP_SOURCE_SUBMODULE: diff --combined help.c index 8ba0777410,a2f48c0df3..07b185389d --- a/help.c +++ b/help.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "builtin.h" #include "exec_cmd.h" #include "run-command.h" @@@ -10,7 -9,6 +10,7 @@@ #include "column.h" #include "version.h" #include "refs.h" +#include "parse-options.h" void add_cmdname(struct cmdnames *cmds, const char *name, int len) { @@@ -269,9 -267,8 +269,8 @@@ static void add_cmd_list(struct cmdname for (i = 0; i < old->cnt; i++) cmds->names[cmds->cnt++] = old->names[i]; - free(old->names); + FREE_AND_NULL(old->names); old->cnt = 0; - old->names = NULL; } /* An empirically derived magic number */ @@@ -291,7 -288,7 +290,7 @@@ const char *help_unknown_cmd(const cha memset(&other_cmds, 0, sizeof(other_cmds)); memset(&aliases, 0, sizeof(aliases)); - git_config(git_unknown_cmd_config, NULL); + read_early_config(git_unknown_cmd_config, NULL); load_command_list("git-", &main_cmds, &other_cmds); @@@ -385,30 -382,16 +384,30 @@@ int cmd_version(int argc, const char **argv, const char *prefix) { + int build_options = 0; + const char * const usage[] = { + N_("git version []"), + NULL + }; + struct option options[] = { + OPT_BOOL(0, "build-options", &build_options, + "also print build options"), + OPT_END() + }; + + argc = parse_options(argc, argv, prefix, options, usage, 0); + /* * The format of this string should be kept stable for compatibility * with external projects that rely on the output of "git version". + * + * Always show the version, even if other options are given. */ printf("git version %s\n", git_version_string); - while (*++argv) { - if (!strcmp(*argv, "--build-options")) { - printf("sizeof-long: %d\n", (int)sizeof(long)); - /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */ - } + + if (build_options) { + printf("sizeof-long: %d\n", (int)sizeof(long)); + /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */ } return 0; } diff --combined http.c index 013bb0cc65,77f46bef0f..c6c010f881 --- a/http.c +++ b/http.c @@@ -1,6 -1,5 +1,6 @@@ #include "git-compat-util.h" #include "http.h" +#include "config.h" #include "pack.h" #include "sideband.h" #include "run-command.h" @@@ -1027,8 -1026,7 +1027,7 @@@ void http_cleanup(void if (proxy_auth.password) { memset(proxy_auth.password, 0, strlen(proxy_auth.password)); - free(proxy_auth.password); - proxy_auth.password = NULL; + FREE_AND_NULL(proxy_auth.password); } free((void *)curl_proxyuserpwd); @@@ -1039,13 -1037,11 +1038,11 @@@ if (cert_auth.password != NULL) { memset(cert_auth.password, 0, strlen(cert_auth.password)); - free(cert_auth.password); - cert_auth.password = NULL; + FREE_AND_NULL(cert_auth.password); } ssl_cert_password_required = 0; - free(cached_accept_language); - cached_accept_language = NULL; + FREE_AND_NULL(cached_accept_language); } struct active_request_slot *get_active_slot(void) @@@ -1897,8 -1893,7 +1894,7 @@@ static char *fetch_pack_index(unsigned if (http_get_file(url, tmp, NULL) != HTTP_OK) { error("Unable to get pack index %s", url); - free(tmp); - tmp = NULL; + FREE_AND_NULL(tmp); } free(url); @@@ -2329,8 -2324,7 +2325,7 @@@ void release_http_object_request(struc freq->localfile = -1; } if (freq->url != NULL) { - free(freq->url); - freq->url = NULL; + FREE_AND_NULL(freq->url); } if (freq->slot != NULL) { freq->slot->callback_func = NULL; diff --combined imap-send.c index 59e9b12d29,40ddb496e6..351e84aea1 --- a/imap-send.c +++ b/imap-send.c @@@ -23,7 -23,6 +23,7 @@@ */ #include "cache.h" +#include "config.h" #include "credential.h" #include "exec_cmd.h" #include "run-command.h" @@@ -777,8 -776,7 +777,7 @@@ static int get_cmd_result(struct imap_s offsetof(struct imap_cmd, next)); if (cmdp->cb.data) { n = socket_write(&imap->buf.sock, cmdp->cb.data, cmdp->cb.dlen); - free(cmdp->cb.data); - cmdp->cb.data = NULL; + FREE_AND_NULL(cmdp->cb.data); if (n != (int)cmdp->cb.dlen) return RESP_BAD; } else if (cmdp->cb.cont) { diff --combined line-log.c index 2588ce0767,2d60c347ca..ab0709f9ae --- a/line-log.c +++ b/line-log.c @@@ -34,9 -34,8 +34,8 @@@ void range_set_init(struct range_set *r void range_set_release(struct range_set *rs) { - free(rs->ranges); + FREE_AND_NULL(rs->ranges); rs->alloc = rs->nr = 0; - rs->ranges = NULL; } /* dst must be uninitialized! */ @@@ -500,12 -499,12 +499,12 @@@ static struct commit *check_single_comm static void fill_blob_sha1(struct commit *commit, struct diff_filespec *spec) { unsigned mode; - unsigned char sha1[20]; + struct object_id oid; if (get_tree_entry(commit->object.oid.hash, spec->path, - sha1, &mode)) + oid.hash, &mode)) die("There is no path %s in the commit", spec->path); - fill_filespec(spec, sha1, 1, mode); + fill_filespec(spec, &oid, 1, mode); return; } @@@ -610,8 -609,7 +609,7 @@@ parse_lines(struct commit *commit, cons line_log_data_insert(&ranges, full_name, begin, end); free_filespec(spec); - free(ends); - ends = NULL; + FREE_AND_NULL(ends); } for (p = ranges; p; p = p->next) @@@ -819,8 -817,8 +817,8 @@@ static void queue_diffs(struct line_log assert(commit); DIFF_QUEUE_CLEAR(&diff_queued_diff); - diff_tree_sha1(parent ? parent->tree->object.oid.hash : NULL, - commit->tree->object.oid.hash, "", opt); + diff_tree_oid(parent ? &parent->tree->object.oid : NULL, + &commit->tree->object.oid, "", opt); if (opt->detect_rename) { filter_diffs_for_paths(range, 1); if (diff_might_be_rename()) diff --combined ll-merge.c index b9576efe97,91ff519cef..9fb855a900 --- a/ll-merge.c +++ b/ll-merge.c @@@ -5,7 -5,6 +5,7 @@@ */ #include "cache.h" +#include "config.h" #include "attr.h" #include "xdiff-interface.h" #include "run-command.h" @@@ -210,8 -209,7 +210,7 @@@ static int ll_ext_merge(const struct ll result->size = st.st_size; result->ptr = xmallocz(result->size); if (read_in_full(fd, result->ptr, result->size) != result->size) { - free(result->ptr); - result->ptr = NULL; + FREE_AND_NULL(result->ptr); result->size = 0; } close_bad: @@@ -340,7 -338,7 +339,7 @@@ static const struct ll_merge_driver *fi static void normalize_file(mmfile_t *mm, const char *path) { struct strbuf strbuf = STRBUF_INIT; - if (renormalize_buffer(path, mm->ptr, mm->size, &strbuf)) { + if (renormalize_buffer(&the_index, path, mm->ptr, mm->size, &strbuf)) { free(mm->ptr); mm->size = strbuf.len; mm->ptr = strbuf_detach(&strbuf, NULL); diff --combined mailinfo.c index f59162453e,44f829edb1..1652ec11f5 --- a/mailinfo.c +++ b/mailinfo.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "utf8.h" #include "strbuf.h" #include "mailinfo.h" @@@ -920,8 -919,7 +920,7 @@@ again /* we hit an end boundary */ /* pop the current boundary off the stack */ strbuf_release(*(mi->content_top)); - free(*(mi->content_top)); - *(mi->content_top) = NULL; + FREE_AND_NULL(*(mi->content_top)); /* technically won't happen as is_multipart_boundary() will fail first. But just in case.. diff --combined pathspec.c index ecc5331c23,54aab8bc01..a5f4df31ea --- a/pathspec.c +++ b/pathspec.c @@@ -1,6 -1,5 +1,6 @@@ #define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" +#include "config.h" #include "dir.h" #include "pathspec.h" #include "attr.h" @@@ -663,7 -662,6 +663,6 @@@ void clear_pathspec(struct pathspec *pa attr_check_free(pathspec->items[i].attr_check); } - free(pathspec->items); - pathspec->items = NULL; + FREE_AND_NULL(pathspec->items); pathspec->nr = 0; } diff --combined read-cache.c index ad692e198d,66c413657e..3c4354ee21 --- a/read-cache.c +++ b/read-cache.c @@@ -5,7 -5,6 +5,7 @@@ */ #define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" +#include "config.h" #include "tempfile.h" #include "lockfile.h" #include "cache-tree.h" @@@ -1878,15 -1877,9 +1878,15 @@@ int discard_index(struct index_state *i { int i; - unshare_split_index(istate, 1); - for (i = 0; i < istate->cache_nr; i++) + for (i = 0; i < istate->cache_nr; i++) { + if (istate->cache[i]->index && + istate->split_index && + istate->split_index->base && + istate->cache[i]->index <= istate->split_index->base->cache_nr && + istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1]) + continue; free(istate->cache[i]); + } resolve_undo_clear_index(istate); istate->cache_nr = 0; istate->cache_changed = 0; @@@ -1895,8 -1888,7 +1895,7 @@@ free_name_hash(istate); cache_tree_free(&(istate->cache_tree)); istate->initialized = 0; - free(istate->cache); - istate->cache = NULL; + FREE_AND_NULL(istate->cache); istate->cache_alloc = 0; discard_split_index(istate); free_untracked_cache(istate->untracked); @@@ -2610,8 -2602,7 +2609,7 @@@ void *read_blob_data_from_index(const s void stat_validity_clear(struct stat_validity *sv) { - free(sv->sd); - sv->sd = NULL; + FREE_AND_NULL(sv->sd); } int stat_validity_check(struct stat_validity *sv, const char *path) diff --combined refs/files-backend.c index 621a4086c3,c1bd99d60f..5ef88eda8b --- a/refs/files-backend.c +++ b/refs/files-backend.c @@@ -1,5 -1,4 +1,5 @@@ #include "../cache.h" +#include "../config.h" #include "../refs.h" #include "refs-internal.h" #include "ref-cache.h" @@@ -2945,8 -2944,7 +2945,7 @@@ static int files_transaction_prepare(st head_oid.hash, &head_type); if (head_ref && !(head_type & REF_ISSYMREF)) { - free(head_ref); - head_ref = NULL; + FREE_AND_NULL(head_ref); } /* diff --combined remote-testsvn.c index e034ea00d4,078b0c3139..0ff4a31262 --- a/remote-testsvn.c +++ b/remote-testsvn.c @@@ -51,23 -51,22 +51,22 @@@ static void terminate_batch(void } /* NOTE: 'ref' refers to a git reference, while 'rev' refers to a svn revision. */ -static char *read_ref_note(const unsigned char sha1[20]) +static char *read_ref_note(const struct object_id *oid) { - const unsigned char *note_sha1; + const struct object_id *note_oid; char *msg = NULL; unsigned long msglen; enum object_type type; init_notes(NULL, notes_ref, NULL, 0); - if (!(note_sha1 = get_note(NULL, sha1))) + if (!(note_oid = get_note(NULL, oid))) return NULL; /* note tree not found */ - if (!(msg = read_sha1_file(note_sha1, &type, &msglen))) + if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen))) error("Empty notes tree. %s", notes_ref); else if (!msglen || type != OBJ_BLOB) { error("Note contains unusable content. " "Is something else using this notes tree? %s", notes_ref); - free(msg); - msg = NULL; + FREE_AND_NULL(msg); } free_notes(NULL); return msg; @@@ -99,8 -98,8 +98,8 @@@ static int parse_rev_note(const char *m return -1; } -static int note2mark_cb(const unsigned char *object_sha1, - const unsigned char *note_sha1, char *note_path, +static int note2mark_cb(const struct object_id *object_oid, + const struct object_id *note_oid, char *note_path, void *cb_data) { FILE *file = (FILE *)cb_data; @@@ -109,14 -108,14 +108,14 @@@ enum object_type type; struct rev_note note; - if (!(msg = read_sha1_file(note_sha1, &type, &msglen)) || + if (!(msg = read_sha1_file(note_oid->hash, &type, &msglen)) || !msglen || type != OBJ_BLOB) { free(msg); return 1; } if (parse_rev_note(msg, ¬e)) return 2; - if (fprintf(file, ":%d %s\n", note.rev_nr, sha1_to_hex(object_sha1)) < 1) + if (fprintf(file, ":%d %s\n", note.rev_nr, oid_to_hex(object_oid)) < 1) return 3; return 0; } @@@ -170,15 -169,15 +169,15 @@@ static int cmd_import(const char *line int code; int dumpin_fd; char *note_msg; - unsigned char head_sha1[20]; + struct object_id head_oid; unsigned int startrev; struct child_process svndump_proc = CHILD_PROCESS_INIT; const char *command = "svnrdump"; - if (read_ref(private_ref, head_sha1)) + if (read_ref(private_ref, head_oid.hash)) startrev = 0; else { - note_msg = read_ref_note(head_sha1); + note_msg = read_ref_note(&head_oid); if(note_msg == NULL) { warning("No note found for %s.", private_ref); startrev = 0; diff --combined rerere.c index 829b3b0f08,61f3804a1e..70634d456c --- a/rerere.c +++ b/rerere.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "lockfile.h" #include "string-list.h" #include "rerere.h" @@@ -40,9 -39,8 +40,8 @@@ static void free_rerere_dirs(void free(rerere_dir[i]->status); free(rerere_dir[i]); } - free(rerere_dir); + FREE_AND_NULL(rerere_dir); rerere_dir_nr = rerere_dir_alloc = 0; - rerere_dir = NULL; } static void free_rerere_id(struct string_list_item *item) diff --combined sequencer.c index 224afe79b9,070b42f240..98cdfe74fd --- a/sequencer.c +++ b/sequencer.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "lockfile.h" #include "sequencer.h" #include "dir.h" @@@ -1212,8 -1211,7 +1212,7 @@@ struct todo_list static void todo_list_release(struct todo_list *todo_list) { strbuf_release(&todo_list->buf); - free(todo_list->items); - todo_list->items = NULL; + FREE_AND_NULL(todo_list->items); todo_list->nr = todo_list->alloc = 0; } @@@ -2131,8 -2129,8 +2130,8 @@@ cleanup_head_ref if (read_oneliner(&buf, rebase_path_orig_head(), 0) && !get_sha1(buf.buf, orig.hash) && !get_sha1("HEAD", head.hash)) { - diff_tree_sha1(orig.hash, head.hash, - "", &log_tree_opt.diffopt); + diff_tree_oid(&orig, &head, "", + &log_tree_opt.diffopt); log_tree_diff_flush(&log_tree_opt); } } diff --combined sha1_file.c index a900b28042,d67c88bb8d..fb1fd809dc --- a/sha1_file.c +++ b/sha1_file.c @@@ -7,7 -7,6 +7,7 @@@ * creation etc. */ #include "cache.h" +#include "config.h" #include "string-list.h" #include "lockfile.h" #include "delta.h" @@@ -611,8 -610,7 +611,7 @@@ char *compute_alternate_path(const cha out: if (seen_error) { - free(ref_git); - ref_git = NULL; + FREE_AND_NULL(ref_git); } return ref_git; @@@ -3547,7 -3545,7 +3546,7 @@@ static int index_mem(unsigned char *sha */ if ((type == OBJ_BLOB) && path) { struct strbuf nbuf = STRBUF_INIT; - if (convert_to_git(path, buf, size, &nbuf, + if (convert_to_git(&the_index, path, buf, size, &nbuf, write_object ? safe_crlf : SAFE_CRLF_FALSE)) { buf = strbuf_detach(&nbuf, &size); re_allocated = 1; @@@ -3581,7 -3579,7 +3580,7 @@@ static int index_stream_convert_blob(un assert(path); assert(would_convert_to_git_filter_fd(path)); - convert_to_git_filter_fd(path, fd, &sbuf, + convert_to_git_filter_fd(&the_index, path, fd, &sbuf, write_object ? safe_crlf : SAFE_CRLF_FALSE); if (write_object) @@@ -3669,7 -3667,7 +3668,7 @@@ int index_fd(unsigned char *sha1, int f else if (!S_ISREG(st->st_mode)) ret = index_pipe(sha1, fd, type, path, flags); else if (st->st_size <= big_file_threshold || type != OBJ_BLOB || - (path && would_convert_to_git(path))) + (path && would_convert_to_git(&the_index, path))) ret = index_core(sha1, fd, xsize_t(st->st_size), type, path, flags); else diff --combined split-index.c index f519e60f87,20477c6a48..83e39ec8d7 --- a/split-index.c +++ b/split-index.c @@@ -73,10 -73,17 +73,10 @@@ void move_cache_to_base_index(struct in int i; /* - * If "si" is shared with another index_state (e.g. by - * unpack-trees code), we will need to duplicate split_index - * struct. It's not happening now though, luckily. + * do not delete old si->base, its index entries may be shared + * with istate->cache[]. Accept a bit of leaking here because + * this code is only used by short-lived update-index. */ - assert(si->refcount <= 1); - - unshare_split_index(istate, 0); - if (si->base) { - discard_index(si->base); - free(si->base); - } si->base = xcalloc(1, sizeof(*si->base)); si->base->version = istate->version; /* zero timestamp disables racy test in ce_write_index() */ @@@ -167,10 -174,9 +167,9 @@@ void merge_base_index(struct index_stat ewah_free(si->delete_bitmap); ewah_free(si->replace_bitmap); - free(si->saved_cache); + FREE_AND_NULL(si->saved_cache); si->delete_bitmap = NULL; si->replace_bitmap = NULL; - si->saved_cache = NULL; si->saved_cache_nr = 0; } @@@ -275,11 -281,41 +274,11 @@@ void finish_writing_split_index(struct istate->cache_nr = si->saved_cache_nr; } -void unshare_split_index(struct index_state *istate, int discard) -{ - struct split_index *si = istate->split_index; - int i; - - if (!si || !si->base) - return; - - for (i = 0; i < istate->cache_nr; i++) { - struct cache_entry *ce = istate->cache[i]; - struct cache_entry *new = NULL; - - if (!ce->index || - ce->index > si->base->cache_nr || - ce != si->base->cache[ce->index - 1]) - continue; - - if (!discard) { - int len = ce_namelen(ce); - new = xcalloc(1, cache_entry_size(len)); - copy_cache_entry(new, ce); - memcpy(new->name, ce->name, len); - new->index = 0; - } - istate->cache[i] = new; - } -} - - void discard_split_index(struct index_state *istate) { struct split_index *si = istate->split_index; if (!si) return; - unshare_split_index(istate, 0); istate->split_index = NULL; si->refcount--; if (si->refcount) @@@ -328,14 -364,8 +327,14 @@@ void add_split_index(struct index_stat void remove_split_index(struct index_state *istate) { - if (!istate->split_index) - return; - discard_split_index(istate); - istate->cache_changed |= SOMETHING_CHANGED; + if (istate->split_index) { + /* + * can't discard_split_index(&the_index); because that + * will destroy split_index->base->cache[], which may + * be shared with the_index.cache[]. So yeah we're + * leaking a bit here. + */ + istate->split_index = NULL; + istate->cache_changed |= SOMETHING_CHANGED; + } } diff --combined transport.c index b9995306f2,cf35088001..d75ff0514d --- a/transport.c +++ b/transport.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "config.h" #include "transport.h" #include "run-command.h" #include "pkt-line.h" @@@ -1146,8 -1145,7 +1146,7 @@@ void transport_unlock_pack(struct trans { if (transport->pack_lockfile) { unlink_or_warn(transport->pack_lockfile); - free(transport->pack_lockfile); - transport->pack_lockfile = NULL; + FREE_AND_NULL(transport->pack_lockfile); } } diff --combined tree-diff.c index 467e381724,1e1b393d08..bd6d65a409 --- a/tree-diff.c +++ b/tree-diff.c @@@ -26,12 -26,11 +26,12 @@@ } while(0) static struct combine_diff_path *ll_diff_tree_paths( - struct combine_diff_path *p, const unsigned char *sha1, - const unsigned char **parents_sha1, int nparent, + struct combine_diff_path *p, const struct object_id *oid, + const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt); -static int ll_diff_tree_sha1(const unsigned char *old, const unsigned char *new, - struct strbuf *base, struct diff_options *opt); +static int ll_diff_tree_oid(const struct object_id *old_oid, + const struct object_id *new_oid, + struct strbuf *base, struct diff_options *opt); /* * Compare two tree entries, taking into account only path/S_ISDIR(mode), @@@ -75,25 -74,25 +75,25 @@@ static int emit_diff_first_parent_only( { struct combine_diff_parent *p0 = &p->parent[0]; if (p->mode && p0->mode) { - opt->change(opt, p0->mode, p->mode, p0->oid.hash, p->oid.hash, + opt->change(opt, p0->mode, p->mode, &p0->oid, &p->oid, 1, 1, p->path, 0, 0); } else { - const unsigned char *sha1; + const struct object_id *oid; unsigned int mode; int addremove; if (p->mode) { addremove = '+'; - sha1 = p->oid.hash; + oid = &p->oid; mode = p->mode; } else { addremove = '-'; - sha1 = p0->oid.hash; + oid = &p0->oid; mode = p0->mode; } - opt->add_remove(opt, addremove, mode, sha1, 1, p->path, 0); + opt->add_remove(opt, addremove, mode, oid, 1, p->path, 0); } return 0; /* we are done with p */ @@@ -132,7 -131,7 +132,7 @@@ */ static struct combine_diff_path *path_appendnew(struct combine_diff_path *last, int nparent, const struct strbuf *base, const char *path, int pathlen, - unsigned mode, const unsigned char *sha1) + unsigned mode, const struct object_id *oid) { struct combine_diff_path *p; size_t len = st_add(base->len, pathlen); @@@ -141,8 -140,7 +141,7 @@@ /* if last->next is !NULL - it is a pre-allocated memory, we can reuse */ p = last->next; if (p && (alloclen > (intptr_t)p->next)) { - free(p); - p = NULL; + FREE_AND_NULL(p); } if (!p) { @@@ -162,7 -160,7 +161,7 @@@ memcpy(p->path + base->len, path, pathlen); p->path[len] = 0; p->mode = mode; - hashcpy(p->oid.hash, sha1 ? sha1 : null_sha1); + oidcpy(&p->oid, oid ? oid : &null_oid); return p; } @@@ -184,7 -182,7 +183,7 @@@ static struct combine_diff_path *emit_p { unsigned mode; const char *path; - const unsigned char *sha1; + const struct object_id *oid; int pathlen; int old_baselen = base->len; int i, isdir, recurse = 0, emitthis = 1; @@@ -194,7 -192,7 +193,7 @@@ if (t) { /* path present in resulting tree */ - sha1 = tree_entry_extract(t, &path, &mode)->hash; + oid = tree_entry_extract(t, &path, &mode); pathlen = tree_entry_len(&t->entry); isdir = S_ISDIR(mode); } else { @@@ -209,7 -207,7 +208,7 @@@ pathlen = tree_entry_len(&tp[imin].entry); isdir = S_ISDIR(mode); - sha1 = NULL; + oid = NULL; mode = 0; } @@@ -221,7 -219,7 +220,7 @@@ if (emitthis) { int keep; struct combine_diff_path *pprev = p; - p = path_appendnew(p, nparent, base, path, pathlen, mode, sha1); + p = path_appendnew(p, nparent, base, path, pathlen, mode, oid); for (i = 0; i < nparent; ++i) { /* @@@ -230,7 -228,7 +229,7 @@@ */ int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ); - const unsigned char *sha1_i; + const struct object_id *oid_i; unsigned mode_i; p->parent[i].status = @@@ -240,16 -238,16 +239,16 @@@ DIFF_STATUS_ADDED; if (tpi_valid) { - sha1_i = tp[i].entry.oid->hash; + oid_i = tp[i].entry.oid; mode_i = tp[i].entry.mode; } else { - sha1_i = NULL; + oid_i = &null_oid; mode_i = 0; } p->parent[i].mode = mode_i; - hashcpy(p->parent[i].oid.hash, sha1_i ? sha1_i : null_sha1); + oidcpy(&p->parent[i].oid, oid_i); } keep = 1; @@@ -274,20 -272,21 +273,20 @@@ } if (recurse) { - const unsigned char **parents_sha1; + const struct object_id **parents_oid; - FAST_ARRAY_ALLOC(parents_sha1, nparent); + FAST_ARRAY_ALLOC(parents_oid, nparent); for (i = 0; i < nparent; ++i) { /* same rule as in emitthis */ int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ); - parents_sha1[i] = tpi_valid ? tp[i].entry.oid->hash - : NULL; + parents_oid[i] = tpi_valid ? tp[i].entry.oid : NULL; } strbuf_add(base, path, pathlen); strbuf_addch(base, '/'); - p = ll_diff_tree_paths(p, sha1, parents_sha1, nparent, base, opt); - FAST_ARRAY_FREE(parents_sha1, nparent); + p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt); + FAST_ARRAY_FREE(parents_oid, nparent); } strbuf_setlen(base, old_baselen); @@@ -312,7 -311,7 +311,7 @@@ static void skip_uninteresting(struct t /* - * generate paths for combined diff D(sha1,parents_sha1[]) + * generate paths for combined diff D(sha1,parents_oid[]) * * Resulting paths are appended to combine_diff_path linked list, and also, are * emitted on the go via opt->pathchange() callback, so it is possible to @@@ -404,8 -403,8 +403,8 @@@ static inline void update_tp_entries(st } static struct combine_diff_path *ll_diff_tree_paths( - struct combine_diff_path *p, const unsigned char *sha1, - const unsigned char **parents_sha1, int nparent, + struct combine_diff_path *p, const struct object_id *oid, + const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt) { struct tree_desc t, *tp; @@@ -419,11 -418,11 +418,11 @@@ * load parents first, as they are probably already cached. * * ( log_tree_diff() parses commit->parent before calling here via - * diff_tree_sha1(parent, commit) ) + * diff_tree_oid(parent, commit) ) */ for (i = 0; i < nparent; ++i) - tptree[i] = fill_tree_descriptor(&tp[i], parents_sha1[i]); - ttree = fill_tree_descriptor(&t, sha1); + tptree[i] = fill_tree_descriptor(&tp[i], parents_oid[i]->hash); + ttree = fill_tree_descriptor(&t, oid->hash); /* Enable recursion indefinitely */ opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE); @@@ -548,19 -547,18 +547,18 @@@ } struct combine_diff_path *diff_tree_paths( - struct combine_diff_path *p, const unsigned char *sha1, - const unsigned char **parents_sha1, int nparent, + struct combine_diff_path *p, const struct object_id *oid, + const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt) { - p = ll_diff_tree_paths(p, sha1, parents_sha1, nparent, base, opt); + p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt); /* * free pre-allocated last element, if any * (see path_appendnew() for details about why) */ if (p->next) { - free(p->next); - p->next = NULL; + FREE_AND_NULL(p->next); } return p; @@@ -577,9 -575,7 +575,9 @@@ static inline int diff_might_be_rename( !DIFF_FILE_VALID(diff_queued_diff.queue[0]->one); } -static void try_to_follow_renames(const unsigned char *old, const unsigned char *new, struct strbuf *base, struct diff_options *opt) +static void try_to_follow_renames(const struct object_id *old_oid, + const struct object_id *new_oid, + struct strbuf *base, struct diff_options *opt) { struct diff_options diff_opts; struct diff_queue_struct *q = &diff_queued_diff; @@@ -617,7 -613,7 +615,7 @@@ diff_opts.break_opt = opt->break_opt; diff_opts.rename_score = opt->rename_score; diff_setup_done(&diff_opts); - ll_diff_tree_sha1(old, new, base, &diff_opts); + ll_diff_tree_oid(old_oid, new_oid, base, &diff_opts); diffcore_std(&diff_opts); clear_pathspec(&diff_opts.pathspec); @@@ -676,16 -672,15 +674,16 @@@ q->nr = 1; } -static int ll_diff_tree_sha1(const unsigned char *old, const unsigned char *new, - struct strbuf *base, struct diff_options *opt) +static int ll_diff_tree_oid(const struct object_id *old_oid, + const struct object_id *new_oid, + struct strbuf *base, struct diff_options *opt) { struct combine_diff_path phead, *p; pathchange_fn_t pathchange_old = opt->pathchange; phead.next = NULL; opt->pathchange = emit_diff_first_parent_only; - diff_tree_paths(&phead, new, &old, 1, base, opt); + diff_tree_paths(&phead, new_oid, &old_oid, 1, base, opt); for (p = phead.next; p;) { struct combine_diff_path *pprev = p; @@@ -697,9 -692,7 +695,9 @@@ return 0; } -int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base_str, struct diff_options *opt) +int diff_tree_oid(const struct object_id *old_oid, + const struct object_id *new_oid, + const char *base_str, struct diff_options *opt) { struct strbuf base; int retval; @@@ -707,16 -700,16 +705,16 @@@ strbuf_init(&base, PATH_MAX); strbuf_addstr(&base, base_str); - retval = ll_diff_tree_sha1(old, new, &base, opt); + retval = ll_diff_tree_oid(old_oid, new_oid, &base, opt); if (!*base_str && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) - try_to_follow_renames(old, new, &base, opt); + try_to_follow_renames(old_oid, new_oid, &base, opt); strbuf_release(&base); return retval; } -int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt) +int diff_root_tree_oid(const struct object_id *new_oid, const char *base, struct diff_options *opt) { - return diff_tree_sha1(NULL, new, base, opt); + return diff_tree_oid(NULL, new_oid, base, opt); } diff --combined tree.c index dd69423d9a,614f91586d..b224115e0f --- a/tree.c +++ b/tree.c @@@ -1,4 -1,3 +1,4 @@@ +#define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "cache-tree.h" #include "tree.h" @@@ -9,11 -8,7 +9,11 @@@ const char *tree_type = "tree"; -static int read_one_entry_opt(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, int opt) +static int read_one_entry_opt(struct index_state *istate, + const unsigned char *sha1, + const char *base, int baselen, + const char *pathname, + unsigned mode, int stage, int opt) { int len; unsigned int size; @@@ -32,15 -27,14 +32,15 @@@ memcpy(ce->name, base, baselen); memcpy(ce->name + baselen, pathname, len+1); hashcpy(ce->oid.hash, sha1); - return add_cache_entry(ce, opt); + return add_index_entry(istate, ce, opt); } static int read_one_entry(const unsigned char *sha1, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *context) { - return read_one_entry_opt(sha1, base->buf, base->len, pathname, + struct index_state *istate = context; + return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname, mode, stage, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); } @@@ -53,8 -47,7 +53,8 @@@ static int read_one_entry_quick(const u const char *pathname, unsigned mode, int stage, void *context) { - return read_one_entry_opt(sha1, base->buf, base->len, pathname, + struct index_state *istate = context; + return read_one_entry_opt(istate, sha1, base->buf, base->len, pathname, mode, stage, ADD_CACHE_JUST_APPEND); } @@@ -151,8 -144,7 +151,8 @@@ static int cmp_cache_name_compare(cons ce2->name, ce2->ce_namelen, ce_stage(ce2)); } -int read_tree(struct tree *tree, int stage, struct pathspec *match) +int read_tree(struct tree *tree, int stage, struct pathspec *match, + struct index_state *istate) { read_tree_fn_t fn = NULL; int i, err; @@@ -172,23 -164,23 +172,23 @@@ * do it the original slow way, otherwise, append and then * sort at the end. */ - for (i = 0; !fn && i < active_nr; i++) { - const struct cache_entry *ce = active_cache[i]; + for (i = 0; !fn && i < istate->cache_nr; i++) { + const struct cache_entry *ce = istate->cache[i]; if (ce_stage(ce) == stage) fn = read_one_entry; } if (!fn) fn = read_one_entry_quick; - err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL); + err = read_tree_recursive(tree, "", 0, stage, match, fn, istate); if (fn == read_one_entry || err) return err; /* * Sort the cache entry -- we need to nuke the cache tree, though. */ - cache_tree_free(&active_cache_tree); - QSORT(active_cache, active_nr, cmp_cache_name_compare); + cache_tree_free(&istate->cache_tree); + QSORT(istate->cache, istate->cache_nr, cmp_cache_name_compare); return 0; } @@@ -234,8 -226,7 +234,7 @@@ int parse_tree_gently(struct tree *item void free_tree_buffer(struct tree *tree) { - free(tree->buffer); - tree->buffer = NULL; + FREE_AND_NULL(tree->buffer); tree->size = 0; tree->object.parsed = 0; }