From: Junio C Hamano Date: Mon, 3 Sep 2012 22:53:06 +0000 (-0700) Subject: Merge branch 'jc/maint-config-exit-status' X-Git-Tag: v1.8.0-rc0~115 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/3e06f5ff3870279f3bf2f97d4a4256032575055e?hp=-c Merge branch 'jc/maint-config-exit-status' The exit status code from "git config" was way overspecified while being incorrect. Update the implementation to give the documented status for a case that was documented, and introduce a new code for "all other errors". * jc/maint-config-exit-status: config: "git config baa" should exit with status 1 --- 3e06f5ff3870279f3bf2f97d4a4256032575055e diff --combined Documentation/git-config.txt index 490868eb23,529395fd14..eaea079165 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@@ -54,16 -54,16 +54,16 @@@ configuration file by default, and opti '--file ' can be used to tell the command to write to that location (you can say '--local' but that is the default). - This command will fail (with exit code ret) if: + This command will fail with non-zero status upon error. Some exit + codes are: . The config file is invalid (ret=3), . can not write to the config file (ret=4), . no section or name was provided (ret=2), . the section or key is invalid (ret=1), . you try to unset an option which does not exist (ret=5), - . you try to unset/set an option for which multiple lines match (ret=5), - . you try to use an invalid regexp (ret=6), or - . you use '--global' option without $HOME being properly set (ret=128). + . you try to unset/set an option for which multiple lines match (ret=5), or + . you try to use an invalid regexp (ret=6). On success, the command returns the exit code 0. @@@ -97,11 -97,10 +97,11 @@@ OPTION --global:: For writing options: write to global ~/.gitconfig file rather than - the repository .git/config. + the repository .git/config, write to $XDG_CONFIG_HOME/git/config file + if this file exists and the ~/.gitconfig file doesn't. + -For reading options: read only from global ~/.gitconfig rather than -from all available files. +For reading options: read only from global ~/.gitconfig and from +$XDG_CONFIG_HOME/git/config rather than from all available files. + See also <>. @@@ -195,7 -194,7 +195,7 @@@ See also <> FILES ----- -If not set explicitly with '--file', there are three files where +If not set explicitly with '--file', there are four files where 'git config' will search for configuration options: $GIT_DIR/config:: @@@ -205,14 -204,6 +205,14 @@@ User-specific configuration file. Also called "global" configuration file. +$XDG_CONFIG_HOME/git/config:: + Second user-specific configuration file. If $XDG_CONFIG_HOME is not set + or empty, $HOME/.config/git/config will be used. Any single-valued + variable set in this file will be overwritten by whatever is in + ~/.gitconfig. It is a good idea not to create this file if + you sometimes use older versions of Git, as support for this + file was added fairly recently. + $(prefix)/etc/gitconfig:: System-wide configuration file. @@@ -267,7 -258,7 +267,7 @@@ Given a .git/config like this ; Proxy settings [core] - gitproxy="proxy-command" for kernel.org + gitproxy=proxy-command for kernel.org gitproxy=default-proxy ; for all the rest you can set the filemode to true with @@@ -342,7 -333,7 +342,7 @@@ To actually match only values with an e To add a new proxy, without altering any of the existing ones, use ------------ -% git config core.gitproxy '"proxy-command" for example.com' +% git config --add core.gitproxy '"proxy-command" for example.com' ------------ An example to use customized color from the configuration in your diff --combined builtin/config.c index 8cd08da991,b44277c23e..ada6e12114 --- a/builtin/config.c +++ b/builtin/config.c @@@ -160,8 -160,8 +160,8 @@@ static int show_config(const char *key_ static int get_value(const char *key_, const char *regex_) { - int ret = -1; + int ret = CONFIG_GENERIC_ERROR; - char *global = NULL, *repo_config = NULL; + char *global = NULL, *xdg = NULL, *repo_config = NULL; const char *system_wide = NULL, *local; struct config_include_data inc = CONFIG_INCLUDE_INIT; config_fn_t fn; @@@ -169,10 -169,12 +169,10 @@@ local = given_config_file; if (!local) { - const char *home = getenv("HOME"); local = repo_config = git_pathdup("config"); - if (home) - global = xstrdup(mkpath("%s/.gitconfig", home)); if (git_config_system()) system_wide = git_etc_gitconfig(); + home_config_paths(&global, &xdg, "config"); } if (use_key_regexp) { @@@ -196,11 -198,14 +196,14 @@@ if (regcomp(key_regexp, key, REG_EXTENDED)) { fprintf(stderr, "Invalid key pattern: %s\n", key_); free(key); + ret = CONFIG_INVALID_PATTERN; goto free_strings; } } else { - if (git_config_parse_key(key_, &key, NULL)) + if (git_config_parse_key(key_, &key, NULL)) { + ret = CONFIG_INVALID_KEY; goto free_strings; + } } if (regex_) { @@@ -212,6 -217,7 +215,7 @@@ regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(regexp, regex_, REG_EXTENDED)) { fprintf(stderr, "Invalid pattern: %s\n", regex_); + ret = CONFIG_INVALID_PATTERN; goto free_strings; } } @@@ -227,8 -233,6 +231,8 @@@ if (do_all && system_wide) git_config_from_file(fn, system_wide, data); + if (do_all && xdg) + git_config_from_file(fn, xdg, data); if (do_all && global) git_config_from_file(fn, global, data); if (do_all) @@@ -238,8 -242,6 +242,8 @@@ git_config_from_file(fn, local, data); if (!do_all && !seen && global) git_config_from_file(fn, global, data); + if (!do_all && !seen && xdg) + git_config_from_file(fn, xdg, data); if (!do_all && !seen && system_wide) git_config_from_file(fn, system_wide, data); @@@ -257,7 -259,6 +261,7 @@@ free_strings: free(repo_config); free(global); + free(xdg); return ret; } @@@ -382,25 -383,13 +386,25 @@@ int cmd_config(int argc, const char **a } if (use_global_config) { - char *home = getenv("HOME"); - if (home) { - char *user_config = xstrdup(mkpath("%s/.gitconfig", home)); - given_config_file = user_config; - } else { + char *user_config = NULL; + char *xdg_config = NULL; + + home_config_paths(&user_config, &xdg_config, "config"); + + if (!user_config) + /* + * It is unknown if HOME/.gitconfig exists, so + * we do not know if we should write to XDG + * location; error out even if XDG_CONFIG_HOME + * is set and points at a sane location. + */ die("$HOME not set"); - } + + if (access(user_config, R_OK) && + xdg_config && !access(xdg_config, R_OK)) + given_config_file = xdg_config; + else + given_config_file = user_config; } else if (use_system_config) given_config_file = git_etc_gitconfig(); diff --combined cache.h index 95daa690aa,96ba07320b..eb4a0316d2 --- a/cache.h +++ b/cache.h @@@ -105,9 -105,6 +105,9 @@@ struct cache_header unsigned int hdr_entries; }; +#define INDEX_FORMAT_LB 2 +#define INDEX_FORMAT_UB 4 + /* * The "cache_time" is just the low 32 bits of the * time. It doesn't matter if it overflows - we only @@@ -118,6 -115,48 +118,6 @@@ struct cache_time unsigned int nsec; }; -/* - * dev/ino/uid/gid/size are also just tracked to the low 32 bits - * Again - this is just a (very strong in practice) heuristic that - * the inode hasn't changed. - * - * We save the fields in big-endian order to allow using the - * index file over NFS transparently. - */ -struct ondisk_cache_entry { - struct cache_time ctime; - struct cache_time mtime; - unsigned int dev; - unsigned int ino; - unsigned int mode; - unsigned int uid; - unsigned int gid; - unsigned int size; - unsigned char sha1[20]; - unsigned short flags; - char name[FLEX_ARRAY]; /* more */ -}; - -/* - * This struct is used when CE_EXTENDED bit is 1 - * The struct must match ondisk_cache_entry exactly from - * ctime till flags - */ -struct ondisk_cache_entry_extended { - struct cache_time ctime; - struct cache_time mtime; - unsigned int dev; - unsigned int ino; - unsigned int mode; - unsigned int uid; - unsigned int gid; - unsigned int size; - unsigned char sha1[20]; - unsigned short flags; - unsigned short flags2; - char name[FLEX_ARRAY]; /* more */ -}; - struct cache_entry { struct cache_time ce_ctime; struct cache_time ce_mtime; @@@ -128,13 -167,13 +128,13 @@@ unsigned int ce_gid; unsigned int ce_size; unsigned int ce_flags; + unsigned int ce_namelen; unsigned char sha1[20]; struct cache_entry *next; struct cache_entry *dir_next; char name[FLEX_ARRAY]; /* more */ }; -#define CE_NAMEMASK (0x0fff) #define CE_STAGEMASK (0x3000) #define CE_EXTENDED (0x4000) #define CE_VALID (0x8000) @@@ -198,13 -237,25 +198,13 @@@ static inline void copy_cache_entry(str dst->ce_flags = (dst->ce_flags & ~CE_STATE_MASK) | state; } -static inline unsigned create_ce_flags(size_t len, unsigned stage) -{ - if (len >= CE_NAMEMASK) - len = CE_NAMEMASK; - return (len | (stage << CE_STAGESHIFT)); -} - -static inline size_t ce_namelen(const struct cache_entry *ce) +static inline unsigned create_ce_flags(unsigned stage) { - size_t len = ce->ce_flags & CE_NAMEMASK; - if (len < CE_NAMEMASK) - return len; - return strlen(ce->name + CE_NAMEMASK) + CE_NAMEMASK; + return (stage << CE_STAGESHIFT); } +#define ce_namelen(ce) ((ce)->ce_namelen) #define ce_size(ce) cache_entry_size(ce_namelen(ce)) -#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \ - ondisk_cache_entry_extended_size(ce_namelen(ce)) : \ - ondisk_cache_entry_size(ce_namelen(ce))) #define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT) #define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE) #define ce_skip_worktree(ce) ((ce)->ce_flags & CE_SKIP_WORKTREE) @@@ -255,11 -306,13 +255,11 @@@ static inline unsigned int canon_mode(u return S_IFGITLINK; } -#define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7) #define cache_entry_size(len) (offsetof(struct cache_entry,name) + (len) + 1) -#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len) -#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len) struct index_state { struct cache_entry **cache; + unsigned int version; unsigned int cache_nr, cache_alloc, cache_changed; struct string_list *resolve_undo; struct cache_tree *cache_tree; @@@ -400,11 -453,8 +400,11 @@@ extern const char *setup_git_directory( extern char *prefix_path(const char *prefix, int len, const char *path); extern const char *prefix_filename(const char *prefix, int len, const char *path); extern int check_filename(const char *prefix, const char *name); -extern void verify_filename(const char *prefix, const char *name); +extern void verify_filename(const char *prefix, + const char *name, + int diagnose_misspelt_rev); extern void verify_non_filename(const char *prefix, const char *name); +extern int path_inside_repo(const char *prefix, const char *path); #define INIT_DB_QUIET 0x0001 @@@ -442,7 -492,6 +442,7 @@@ extern int discard_index(struct index_s extern int unmerged_index(const struct index_state *); extern int verify_path(const char *path); extern struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int igncase); +extern int index_name_stage_pos(const struct index_state *, const char *name, int namelen, int stage); extern int index_name_pos(const struct index_state *, const char *name, int namelen); #define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */ #define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */ @@@ -555,7 -604,6 +555,7 @@@ extern int read_replace_refs extern int fsync_object_files; extern int core_preload_index; extern int core_apply_sparse_checkout; +extern int precomposed_unicode; enum branch_track { BRANCH_TRACK_UNSPECIFIED = -1, @@@ -576,7 -624,6 +576,7 @@@ enum rebase_setup_type enum push_default_type { PUSH_DEFAULT_NOTHING = 0, PUSH_DEFAULT_MATCHING, + PUSH_DEFAULT_SIMPLE, PUSH_DEFAULT_UPSTREAM, PUSH_DEFAULT_CURRENT, PUSH_DEFAULT_UNSPECIFIED @@@ -615,8 -662,6 +615,8 @@@ extern char *git_snpath(char *buf, size __attribute__((format (printf, 3, 4))); extern char *git_pathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +extern char *mkpathdup(const char *fmt, ...) + __attribute__((format (printf, 1, 2))); /* Return a statically allocated filename matching the sha1 signature */ extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); @@@ -706,7 -751,6 +706,7 @@@ int set_shared_perm(const char *path, i int safe_create_leading_directories(char *path); int safe_create_leading_directories_const(const char *path); int mkdir_in_gitdir(const char *path); +extern void home_config_paths(char **global, char **xdg, char *file); extern char *expand_user_path(const char *path); const char *enter_repo(const char *path, int strict); static inline int is_absolute_path(const char *path) @@@ -782,25 -826,17 +782,25 @@@ struct object_context unsigned mode; }; +#define GET_SHA1_QUIETLY 01 +#define GET_SHA1_COMMIT 02 +#define GET_SHA1_COMMITTISH 04 +#define GET_SHA1_TREE 010 +#define GET_SHA1_TREEISH 020 +#define GET_SHA1_BLOB 040 +#define GET_SHA1_ONLY_TO_DIE 04000 + extern int get_sha1(const char *str, unsigned char *sha1); -extern int get_sha1_with_mode_1(const char *str, unsigned char *sha1, unsigned *mode, int only_to_die, const char *prefix); -static inline int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode) -{ - return get_sha1_with_mode_1(str, sha1, mode, 0, NULL); -} -extern int get_sha1_with_context_1(const char *name, unsigned char *sha1, struct object_context *orc, int only_to_die, const char *prefix); -static inline int get_sha1_with_context(const char *str, unsigned char *sha1, struct object_context *orc) -{ - return get_sha1_with_context_1(str, sha1, orc, 0, NULL); -} +extern int get_sha1_commit(const char *str, unsigned char *sha1); +extern int get_sha1_committish(const char *str, unsigned char *sha1); +extern int get_sha1_tree(const char *str, unsigned char *sha1); +extern int get_sha1_treeish(const char *str, unsigned char *sha1); +extern int get_sha1_blob(const char *str, unsigned char *sha1); +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); + +typedef int each_abbrev_fn(const unsigned char *sha1, void *); +extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *); /* * Try to read a SHA1 in hexadecimal format from the 40 characters @@@ -864,7 -900,6 +864,7 @@@ extern int validate_headref(const char extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); extern int df_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2); +extern int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2); extern void *read_object_with_reference(const unsigned char *sha1, const char *required_type, @@@ -885,8 -920,10 +885,8 @@@ enum date_mode }; const char *show_date(unsigned long time, int timezone, enum date_mode mode); -const char *show_date_relative(unsigned long time, int tz, - const struct timeval *now, - char *timebuf, - size_t timebuf_size); +void show_date_relative(unsigned long time, int tz, const struct timeval *now, + struct strbuf *timebuf); int parse_date(const char *date, char *buf, int bufsize); int parse_date_basic(const char *date, unsigned long *timestamp, int *offset); void datestamp(char *buf, int bufsize); @@@ -895,19 -932,15 +895,19 @@@ unsigned long approxidate_careful(cons unsigned long approxidate_relative(const char *date, const struct timeval *now); enum date_mode parse_date_format(const char *format); -#define IDENT_WARN_ON_NO_NAME 1 -#define IDENT_ERROR_ON_NO_NAME 2 -#define IDENT_NO_DATE 4 +#define IDENT_STRICT 1 +#define IDENT_NO_DATE 2 +#define IDENT_NO_NAME 4 extern const char *git_author_info(int); extern const char *git_committer_info(int); extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int); extern const char *fmt_name(const char *name, const char *email); +extern const char *ident_default_name(void); +extern const char *ident_default_email(void); +extern const char *ident_default_date(void); extern const char *git_editor(void); extern const char *git_pager(int stdout_is_tty); +extern int git_ident_config(const char *, const char *, void *); struct ident_split { const char *name_begin; @@@ -1038,9 -1071,7 +1038,9 @@@ struct extra_have_objects }; extern struct ref **get_remote_heads(int in, struct ref **list, unsigned int flags, struct extra_have_objects *); extern int server_supports(const char *feature); -extern const char *parse_feature_request(const char *features, const char *feature); +extern int parse_feature_request(const char *features, const char *feature); +extern const char *server_feature_value(const char *feature, int *len_ret); +extern const char *parse_feature_value(const char *feature_list, const char *feature, int *len_ret); extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path); @@@ -1110,6 -1141,7 +1110,7 @@@ extern int update_server_info(int) #define CONFIG_NO_WRITE 4 #define CONFIG_NOTHING_SET 5 #define CONFIG_INVALID_PATTERN 6 + #define CONFIG_GENERIC_ERROR 7 typedef int (*config_fn_t)(const char *, const char *, void *); extern int git_default_config(const char *, const char *, void *); @@@ -1153,6 -1185,9 +1154,6 @@@ struct config_include_data #define CONFIG_INCLUDE_INIT { 0 } extern int git_config_include(const char *name, const char *value, void *data); -#define MAX_GITNAME (1000) -extern char git_default_email[MAX_GITNAME]; -extern char git_default_name[MAX_GITNAME]; #define IDENT_NAME_GIVEN 01 #define IDENT_MAIL_GIVEN 02 #define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN)