From: Junio C Hamano Date: Tue, 17 May 2016 21:38:17 +0000 (-0700) Subject: Merge branch 'ab/hooks' X-Git-Tag: v2.9.0-rc0~44 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/6675f501f6b987dbdb0dbeb1d2efeb5a27fc41a7?hp=-c Merge branch 'ab/hooks' A new configuration variable core.hooksPath allows customizing where the hook directory is. * ab/hooks: hooks: allow customizing where the hook directory is githooks.txt: minor improvements to the grammar & phrasing githooks.txt: amend dangerous advice about 'update' hook ACL githooks.txt: improve the intro section --- 6675f501f6b987dbdb0dbeb1d2efeb5a27fc41a7 diff --combined Documentation/config.txt index ece0acdbab,7f8c119b2f..6e97e1e05e --- a/Documentation/config.txt +++ b/Documentation/config.txt @@@ -618,6 -618,23 +618,23 @@@ core.attributesFile: $XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/attributes is used instead. + core.hooksPath:: + By default Git will look for your hooks in the + '$GIT_DIR/hooks' directory. Set this to different path, + e.g. '/etc/git/hooks', and Git will try to find your hooks in + that directory, e.g. '/etc/git/hooks/pre-receive' instead of + in '$GIT_DIR/hooks/pre-receive'. + + + The path can be either absolute or relative. A relative path is + taken as relative to the directory where the hooks are run (see + the "DESCRIPTION" section of linkgit:githooks[5]). + + + This configuration variable is useful in cases where you'd like to + centrally configure your Git hooks instead of configuring them on a + per-repository basis, or as a more flexible and centralized + alternative to having an `init.templateDir` where you've changed + default hooks. + core.editor:: Commands such as `commit` and `tag` that lets you edit messages by launching an editor uses the value of this @@@ -1113,9 -1130,8 +1130,9 @@@ commit.template: credential.helper:: Specify an external helper to be called when a username or password credential is needed; the helper may consult external - storage to avoid prompting the user for the credentials. See - linkgit:gitcredentials[7] for details. + storage to avoid prompting the user for the credentials. Note + that multiple helpers may be defined. See linkgit:gitcredentials[7] + for details. credential.useHttpPath:: When acquiring credentials, consider the "path" component of an http @@@ -1655,12 -1671,6 +1672,12 @@@ http.emptyAuth: a username in the URL, as libcurl normally requires a username for authentication. +http.extraHeader:: + Pass an additional HTTP header when communicating with a server. If + more than one such entry exists, all of them are added as extra + headers. To allow overriding the settings inherited from the system + config, an empty value will reset the extra headers to the empty list. + http.cookieFile:: File containing previously stored cookie lines which should be used in the Git http session, if they match the server. The file format @@@ -1893,14 -1903,6 +1910,14 @@@ interactive.singleKey: setting is silently ignored if portable keystroke input is not available; requires the Perl module Term::ReadKey. +interactive.diffFilter:: + When an interactive command (such as `git add --patch`) shows + a colorized diff, git will pipe the diff through the shell + command defined by this configuration variable. The command may + mark up the diff further for human consumption, provided that it + retains a one-to-one correspondence with the lines in the + original diff. Defaults to disabled (no filtering). + log.abbrevCommit:: If true, makes linkgit:git-log[1], linkgit:git-show[1], and linkgit:git-whatchanged[1] assume `--abbrev-commit`. You may @@@ -2162,11 -2164,8 +2179,11 @@@ pack.packSizeLimit: The maximum size of a pack. This setting only affects packing to a file when repacking, i.e. the git:// protocol is unaffected. It can be overridden by the `--max-pack-size` - option of linkgit:git-repack[1]. The minimum size allowed is - limited to 1 MiB. The default is unlimited. + option of linkgit:git-repack[1]. Reaching this limit results + in the creation of multiple packfiles; which in turn prevents + bitmaps from being created. + The minimum size allowed is limited to 1 MiB. + The default is unlimited. Common unit suffixes of 'k', 'm', or 'g' are supported. @@@ -2566,9 -2565,8 +2583,9 @@@ repack.writeBitmaps: objects to disk (e.g., when `git repack -a` is run). This index can speed up the "counting objects" phase of subsequent packs created for clones and fetches, at the cost of some disk - space and extra time spent on the initial repack. Defaults to - false. + space and extra time spent on the initial repack. This has + no effect if multiple packfiles are created. + Defaults to false. rerere.autoUpdate:: When set to true, `git-rerere` updates the index with the @@@ -2748,17 -2746,6 +2765,17 @@@ submodule..ignore: "--ignore-submodules" option. The 'git submodule' commands are not affected by this setting. +submodule.fetchJobs:: + Specifies how many submodules are fetched/cloned at the same time. + A positive integer allows up to that number of submodules fetched + in parallel. A value of 0 will give some reasonable default. + If unset, it defaults to 1. + +tag.forceSignAnnotated:: + A boolean to specify whether annotated tags created should be GPG signed. + If `--annotate` is specified on the command line, it takes + precedence over this option. + tag.sort:: This variable controls the sort ordering of tags when displayed by linkgit:git-tag[1]. Without the "--sort=" option provided, the diff --combined cache.h index 160f8e32e3,a7529b0233..eddf3e8b0c --- a/cache.h +++ b/cache.h @@@ -651,9 -651,11 +651,10 @@@ extern int prefer_symlink_refs extern int log_all_ref_updates; extern int warn_ambiguous_refs; extern int warn_on_object_refname_ambiguity; -extern int shared_repository; extern const char *apply_default_whitespace; extern const char *apply_default_ignorewhitespace; extern const char *git_attributes_file; + extern const char *git_hooks_path; extern int zlib_compression_level; extern int core_compression_level; extern int core_compression_seen; @@@ -663,9 -665,6 +664,9 @@@ extern size_t delta_base_cache_limit extern unsigned long big_file_threshold; extern unsigned long pack_size_limit_cfg; +void set_shared_repository(int value); +int get_shared_repository(void); + /* * Do replace refs need to be checked this run? This variable is * initialized to true unless --no-replace-object is used or @@@ -747,39 -746,9 +748,39 @@@ extern int grafts_replace_parents */ #define GIT_REPO_VERSION 0 #define GIT_REPO_VERSION_READ 1 -extern int repository_format_version; extern int repository_format_precious_objects; -extern int check_repository_format(void); + +struct repository_format { + int version; + int precious_objects; + int is_bare; + char *work_tree; + struct string_list unknown_extensions; +}; + +/* + * Read the repository format characteristics from the config file "path" into + * "format" struct. Returns the numeric version. On error, -1 is returned, + * format->version is set to -1, and all other fields in the struct are + * undefined. + */ +int read_repository_format(struct repository_format *format, const char *path); + +/* + * Verify that the repository described by repository_format is something we + * can read. If it is, return 0. Otherwise, return -1, and "err" will describe + * any errors encountered. + */ +int verify_repository_format(const struct repository_format *format, + struct strbuf *err); + +/* + * Check the repository format version in the path found in get_git_dir(), + * and die if it is a version we don't understand. Generally one would + * set_git_dir() before calling this, and use it only for "are we in a valid + * repo?". + */ +extern void check_repository_format(void); #define MTIME_CHANGED 0x0001 #define CTIME_CHANGED 0x0002 @@@ -958,6 -927,8 +959,6 @@@ static inline int is_empty_blob_sha1(co int git_mkstemp(char *path, size_t n, const char *template); -int git_mkstemps(char *path, size_t n, const char *template, int suffix_len); - /* set default permissions by passing mode arguments to open(2) */ int git_mkstemps_mode(char *pattern, int suffix_len, int mode); int git_mkstemp_mode(char *pattern, int mode); @@@ -1154,8 -1125,6 +1155,8 @@@ extern int get_sha1_blob(const char *st extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix); extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc); +extern int get_oid(const char *str, struct object_id *oid); + typedef int each_abbrev_fn(const unsigned char *sha1, void *); extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *); @@@ -1558,6 -1527,7 +1559,6 @@@ extern void git_config(config_fn_t fn, extern int git_config_with_options(config_fn_t fn, void *, struct git_config_source *config_source, int respect_includes); -extern int git_config_early(config_fn_t fn, void *, const char *repo_config); extern int git_parse_ulong(const char *, unsigned long *); extern int git_parse_maybe_bool(const char *); extern int git_config_int(const char *, const char *); @@@ -1581,6 -1551,7 +1582,6 @@@ extern void git_config_set_multivar_in_ extern int git_config_rename_section(const char *, const char *); extern int git_config_rename_section_in_file(const char *, const char *, const char *); extern const char *git_etc_gitconfig(void); -extern int check_repository_format_version(const char *var, const char *value, void *cb); extern int git_env_bool(const char *, int); extern unsigned long git_env_ulong(const char *, unsigned long); extern int git_config_system(void); @@@ -1766,8 -1737,8 +1767,8 @@@ int add_files_to_cache(const char *pref extern int diff_auto_refresh_index; /* match-trees.c */ -void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int); -void shift_tree_by(const unsigned char *, const unsigned char *, unsigned char *, const char *); +void shift_tree(const struct object_id *, const struct object_id *, struct object_id *, int); +void shift_tree_by(const struct object_id *, const struct object_id *, struct object_id *, const char *); /* * whitespace rules. @@@ -1801,7 -1772,7 +1802,7 @@@ int split_cmdline(char *cmdline, const /* Takes a negative value returned by split_cmdline */ const char *split_cmdline_strerror(int cmdline_errno); -/* git.c */ +/* setup.c */ struct startup_info { int have_repository; const char *prefix; diff --combined config.c index 262d8d7489,9ef5fde785..13fb508777 --- a/config.c +++ b/config.c @@@ -108,7 -108,7 +108,7 @@@ static int handle_path_include(const ch expanded = expand_user_path(path); if (!expanded) - return error("Could not expand include path '%s'", path); + return error("could not expand include path '%s'", path); path = expanded; /* @@@ -162,7 -162,7 +162,7 @@@ void git_config_push_parameter(const ch { struct strbuf env = STRBUF_INIT; const char *old = getenv(CONFIG_DATA_ENVIRONMENT); - if (old) { + if (old && *old) { strbuf_addstr(&env, old); strbuf_addch(&env, ' '); } @@@ -717,6 -717,9 +717,9 @@@ static int git_default_core_config(cons if (!strcmp(var, "core.attributesfile")) return git_config_pathname(&git_attributes_file, var, value); + if (!strcmp(var, "core.hookspath")) + return git_config_pathname(&git_hooks_path, var, value); + if (!strcmp(var, "core.bare")) { is_bare_repository_cfg = git_config_bool(var, value); return 0; @@@ -950,7 -953,7 +953,7 @@@ static int git_default_branch_config(co else if (!strcmp(value, "always")) autorebase = AUTOREBASE_ALWAYS; else - return error("Malformed value for %s", var); + return error("malformed value for %s", var); return 0; } @@@ -976,7 -979,7 +979,7 @@@ static int git_default_push_config(cons else if (!strcmp(value, "current")) push_default = PUSH_DEFAULT_CURRENT; else { - error("Malformed value for %s: %s", var, value); + error("malformed value for %s: %s", var, value); return error("Must be one of nothing, matching, simple, " "upstream or current."); } @@@ -1188,12 -1191,11 +1191,12 @@@ int git_config_system(void return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0); } -int git_config_early(config_fn_t fn, void *data, const char *repo_config) +static int do_git_config_sequence(config_fn_t fn, void *data) { int ret = 0, found = 0; char *xdg_config = xdg_config_home("config"); char *user_config = expand_user_path("~/.gitconfig"); + char *repo_config = git_pathdup("config"); if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) { ret += git_config_from_file(fn, git_etc_gitconfig(), @@@ -1229,7 -1231,6 +1232,7 @@@ free(xdg_config); free(user_config); + free(repo_config); return ret == 0 ? found : ret; } @@@ -1237,6 -1238,8 +1240,6 @@@ int git_config_with_options(config_fn_ struct git_config_source *config_source, int respect_includes) { - char *repo_config = NULL; - int ret; struct config_include_data inc = CONFIG_INCLUDE_INIT; if (respect_includes) { @@@ -1257,7 -1260,11 +1260,7 @@@ else if (config_source && config_source->blob) return git_config_from_blob_ref(fn, config_source->blob, data); - repo_config = git_pathdup("config"); - ret = git_config_early(fn, data, repo_config); - if (repo_config) - free(repo_config); - return ret; + return do_git_config_sequence(fn, data); } static void git_config_raw(config_fn_t fn, void *data) @@@ -1309,11 -1316,14 +1312,11 @@@ static struct config_set_element *confi struct config_set_element k; struct config_set_element *found_entry; char *normalized_key; - int ret; /* * `key` may come from the user, so normalize it before using it * for querying entries from the hashmap. */ - ret = git_config_parse_key(key, &normalized_key, NULL); - - if (ret) + if (git_config_parse_key(key, &normalized_key, NULL)) return NULL; hashmap_entry_init(&k, strhash(normalized_key)); @@@ -2214,13 -2224,9 +2217,13 @@@ void git_config_set_multivar_in_file(co const char *key, const char *value, const char *value_regex, int multi_replace) { - if (git_config_set_multivar_in_file_gently(config_filename, key, value, - value_regex, multi_replace) < 0) - die(_("Could not set '%s' to '%s'"), key, value); + if (!git_config_set_multivar_in_file_gently(config_filename, key, value, + value_regex, multi_replace)) + return; + if (value) + die(_("could not set '%s' to '%s'"), key, value); + else + die(_("could not unset '%s'"), key); } int git_config_set_multivar_gently(const char *key, const char *value, @@@ -2401,7 -2407,7 +2404,7 @@@ int git_config_rename_section(const cha #undef config_error_nonbool int config_error_nonbool(const char *var) { - return error("Missing value for '%s'", var); + return error("missing value for '%s'", var); } int parse_config_key(const char *var, diff --combined environment.c index 57acb2fe2a,a14d115023..2857e3f366 --- a/environment.c +++ b/environment.c @@@ -25,12 -25,15 +25,13 @@@ int log_all_ref_updates = -1; /* unspec int warn_ambiguous_refs = 1; int warn_on_object_refname_ambiguity = 1; int ref_paranoia = -1; -int repository_format_version; int repository_format_precious_objects; const char *git_commit_encoding; const char *git_log_output_encoding; -int shared_repository = PERM_UMASK; const char *apply_default_whitespace; const char *apply_default_ignorewhitespace; const char *git_attributes_file; + const char *git_hooks_path; int zlib_compression_level = Z_BEST_SPEED; int core_compression_level; int core_compression_seen; @@@ -62,6 -65,7 +63,6 @@@ int grafts_replace_parents = 1 int core_apply_sparse_checkout; int merge_log_config = -1; int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */ -struct startup_info *startup_info; unsigned long pack_size_limit_cfg; #ifndef PROTECT_HFS_DEFAULT @@@ -322,24 -326,3 +323,24 @@@ const char *get_commit_output_encoding( { return git_commit_encoding ? git_commit_encoding : "UTF-8"; } + +static int the_shared_repository = PERM_UMASK; +static int need_shared_repository_from_config = 1; + +void set_shared_repository(int value) +{ + the_shared_repository = value; + need_shared_repository_from_config = 0; +} + +int get_shared_repository(void) +{ + if (need_shared_repository_from_config) { + const char *var = "core.sharedrepository"; + const char *value; + if (!git_config_get_value(var, &value)) + the_shared_repository = git_config_perm(var, value); + need_shared_repository_from_config = 0; + } + return the_shared_repository; +} diff --combined run-command.c index e4593cd99b,aa85cd5c3c..f5c57a5fc7 --- a/run-command.c +++ b/run-command.c @@@ -590,16 -590,6 +590,16 @@@ static void *run_thread(void *data struct async *async = data; intptr_t ret; + if (async->isolate_sigpipe) { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGPIPE); + if (pthread_sigmask(SIG_BLOCK, &mask, NULL) < 0) { + ret = error("unable to block SIGPIPE in async thread"); + return (void *)ret; + } + } + pthread_setspecific(async_key, async); ret = async->proc(async->proc_in, async->proc_out, async->data); return (void *)ret; @@@ -825,7 -815,10 +825,10 @@@ const char *find_hook(const char *name static struct strbuf path = STRBUF_INIT; strbuf_reset(&path); - strbuf_git_path(&path, "hooks/%s", name); + if (git_hooks_path) + strbuf_addf(&path, "%s/%s", git_hooks_path, name); + else + strbuf_git_path(&path, "hooks/%s", name); if (access(path.buf, X_OK) < 0) return NULL; return path.buf; @@@ -912,7 -905,7 +915,7 @@@ struct parallel_processes struct strbuf buffered_output; /* of finished children */ }; -static int default_start_failure(struct strbuf *err, +static int default_start_failure(struct strbuf *out, void *pp_cb, void *pp_task_cb) { @@@ -920,7 -913,7 +923,7 @@@ } static int default_task_finished(int result, - struct strbuf *err, + struct strbuf *out, void *pp_cb, void *pp_task_cb) { @@@ -1004,7 -997,7 +1007,7 @@@ static void pp_cleanup(struct parallel_ * When get_next_task added messages to the buffer in its last * iteration, the buffered output is non empty. */ - fputs(pp->buffered_output.buf, stderr); + strbuf_write(&pp->buffered_output, stderr); strbuf_release(&pp->buffered_output); sigchain_pop_common(); @@@ -1089,7 -1082,7 +1092,7 @@@ static void pp_output(struct parallel_p int i = pp->output_owner; if (pp->children[i].state == GIT_CP_WORKING && pp->children[i].err.len) { - fputs(pp->children[i].err.buf, stderr); + strbuf_write(&pp->children[i].err, stderr); strbuf_reset(&pp->children[i].err); } } @@@ -1127,11 -1120,11 +1130,11 @@@ static int pp_collect_finished(struct p strbuf_addbuf(&pp->buffered_output, &pp->children[i].err); strbuf_reset(&pp->children[i].err); } else { - fputs(pp->children[i].err.buf, stderr); + strbuf_write(&pp->children[i].err, stderr); strbuf_reset(&pp->children[i].err); /* Output all other finished child processes */ - fputs(pp->buffered_output.buf, stderr); + strbuf_write(&pp->buffered_output, stderr); strbuf_reset(&pp->buffered_output); /*