From: Junio C Hamano Date: Mon, 31 Aug 2015 22:38:57 +0000 (-0700) Subject: Merge branch 'jk/fix-alias-pager-config-key-warnings' X-Git-Tag: v2.6.0-rc0~22 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/7b7c10bf5e38ca8fe06ab80b073408e1dc6761d7?ds=inline;hp=-c Merge branch 'jk/fix-alias-pager-config-key-warnings' Because the configuration system does not allow "alias.0foo" and "pager.0foo" as the configuration key, the user cannot use '0foo' as a custom command name anyway, but "git 0foo" tried to look these keys up and emitted useless warnings before saying '0foo is not a git command'. These warning messages have been squelched. * jk/fix-alias-pager-config-key-warnings: config: silence warnings for command names with invalid keys --- 7b7c10bf5e38ca8fe06ab80b073408e1dc6761d7 diff --combined cache.h index 4e25271e59,1121bbd230..8de519a40e --- a/cache.h +++ b/cache.h @@@ -43,14 -43,6 +43,14 @@@ int git_deflate_end_gently(git_zstream int git_deflate(git_zstream *, int flush); unsigned long git_deflate_bound(git_zstream *, unsigned long); +/* The length in bytes and in hex digits of an object name (SHA-1 value). */ +#define GIT_SHA1_RAWSZ 20 +#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ) + +struct object_id { + unsigned char hash[GIT_SHA1_RAWSZ]; +}; + #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT) #define DTYPE(de) ((de)->d_type) #else @@@ -73,6 -65,13 +73,6 @@@ * * The value 0160000 is not normally a valid mode, and * also just happens to be S_IFDIR + S_IFLNK - * - * NOTE! We *really* shouldn't depend on the S_IFxxx macros - * always having the same values everywhere. We should use - * our internal git values for these things, and then we can - * translate that to the OS-specific value. It just so - * happens that everybody shares the same bit representation - * in the UNIX world (and apparently wider too..) */ #define S_IFGITLINK 0160000 #define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK) @@@ -297,11 -296,8 +297,11 @@@ static inline unsigned int canon_mode(u #define RESOLVE_UNDO_CHANGED (1 << 4) #define CACHE_TREE_CHANGED (1 << 5) #define SPLIT_INDEX_ORDERED (1 << 6) +#define UNTRACKED_CHANGED (1 << 7) struct split_index; +struct untracked_cache; + struct index_state { struct cache_entry **cache; unsigned int version; @@@ -315,7 -311,6 +315,7 @@@ struct hashmap name_hash; struct hashmap dir_hash; unsigned char sha1[20]; + struct untracked_cache *untracked; }; extern struct index_state the_index; @@@ -382,7 -377,6 +382,7 @@@ static inline enum object_type object_t /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR" +#define GIT_COMMON_DIR_ENVIRONMENT "GIT_COMMON_DIR" #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE" #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE" #define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX" @@@ -397,7 -391,6 +397,7 @@@ #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH" #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES" #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS" +#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE" #define GITATTRIBUTES_FILE ".gitattributes" #define INFOATTRIBUTES_FILE "info/attributes" #define ATTRIBUTE_MACRO_PREFIX "[attr]" @@@ -437,27 -430,15 +437,27 @@@ extern int is_inside_git_dir(void) extern char *git_work_tree_cfg; extern int is_inside_work_tree(void); extern const char *get_git_dir(void); +extern const char *get_git_common_dir(void); extern int is_git_directory(const char *path); extern char *get_object_directory(void); extern char *get_index_file(void); extern char *get_graft_file(void); extern int set_git_dir(const char *path); +extern int get_common_dir(struct strbuf *sb, const char *gitdir); extern const char *get_git_namespace(void); extern const char *strip_namespace(const char *namespaced_ref); extern const char *get_git_work_tree(void); -extern const char *read_gitfile(const char *path); + +#define READ_GITFILE_ERR_STAT_FAILED 1 +#define READ_GITFILE_ERR_NOT_A_FILE 2 +#define READ_GITFILE_ERR_OPEN_FAILED 3 +#define READ_GITFILE_ERR_READ_FAILED 4 +#define READ_GITFILE_ERR_INVALID_FORMAT 5 +#define READ_GITFILE_ERR_NO_PATH 6 +#define READ_GITFILE_ERR_NOT_A_REPO 7 +#define READ_GITFILE_ERR_TOO_LARGE 8 +extern const char *read_gitfile_gently(const char *path, int *return_error_code); +#define read_gitfile(path) read_gitfile_gently((path), NULL) extern const char *resolve_gitdir(const char *suspect); extern void set_git_work_tree(const char *tree); @@@ -578,8 -559,6 +578,8 @@@ extern void fill_stat_data(struct stat_ * INODE_CHANGED, and DATA_CHANGED. */ extern int match_stat_data(const struct stat_data *sd, struct stat *st); +extern int match_stat_data_racy(const struct index_state *istate, + const struct stat_data *sd, struct stat *st); extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); @@@ -596,6 -575,8 +596,6 @@@ extern void update_index_if_able(struc extern int hold_locked_index(struct lock_file *, int); extern void set_alternate_index_output(const char *); -extern int delete_ref(const char *, const unsigned char *sha1, int delopt); - /* Environment bits from configuration mechanism */ extern int trust_executable_bit; extern int trust_ctime; @@@ -631,7 -612,6 +631,7 @@@ extern unsigned long pack_size_limit_cf * been sought but there were none. */ extern int check_replace_refs; +extern char *git_replace_ref_base; extern int fsync_object_files; extern int core_preload_index; @@@ -639,15 -619,6 +639,15 @@@ extern int core_apply_sparse_checkout extern int precomposed_unicode; extern int protect_hfs; extern int protect_ntfs; +extern int git_db_env, git_index_env, git_graft_env, git_common_dir_env; + +/* + * Include broken refs in all ref iterations, which will + * generally choke dangerous operations rather than letting + * them silently proceed without taking the broken ref into + * account. + */ +extern int ref_paranoia; /* * The character that begins a commented line in user-editable file @@@ -708,59 -679,21 +708,59 @@@ extern int check_repository_format(void #define DATA_CHANGED 0x0020 #define TYPE_CHANGED 0x0040 +/* + * Return a statically allocated filename, either generically (mkpath), in + * the repository directory (git_path), or in a submodule's repository + * directory (git_path_submodule). In all cases, note that the result + * may be overwritten by another call to _any_ of the functions. Consider + * using the safer "dup" or "strbuf" formats below (in some cases, the + * unsafe versions have already been removed). + */ +extern const char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +extern const char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); + extern char *mksnpath(char *buf, size_t n, const char *fmt, ...) __attribute__((format (printf, 3, 4))); -extern char *git_snpath(char *buf, size_t n, const char *fmt, ...) +extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) + __attribute__((format (printf, 2, 3))); +extern void strbuf_git_path_submodule(struct strbuf *sb, const char *path, + const char *fmt, ...) __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))); -extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); -extern char *git_path_submodule(const char *path, const char *fmt, ...) +extern char *git_pathdup_submodule(const char *path, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +extern void report_linked_checkout_garbage(void); + +/* + * You can define a static memoized git path like: + * + * static GIT_PATH_FUNC(git_path_foo, "FOO"); + * + * or use one of the global ones below. + */ +#define GIT_PATH_FUNC(func, filename) \ + const char *func(void) \ + { \ + static char *ret; \ + if (!ret) \ + ret = git_pathdup(filename); \ + return ret; \ + } + +const char *git_path_cherry_pick_head(void); +const char *git_path_revert_head(void); +const char *git_path_squash_msg(void); +const char *git_path_merge_msg(void); +const char *git_path_merge_rr(void); +const char *git_path_merge_mode(void); +const char *git_path_merge_head(void); +const char *git_path_fetch_head(void); +const char *git_path_shallow(void); + /* * Return the name of the file in the local object database that would * be used to store a loose object with the specified sha1. The @@@ -784,13 -717,13 +784,13 @@@ extern char *sha1_pack_name(const unsig extern char *sha1_pack_index_name(const unsigned char *sha1); extern const char *find_unique_abbrev(const unsigned char *sha1, int); -extern const unsigned char null_sha1[20]; +extern const unsigned char null_sha1[GIT_SHA1_RAWSZ]; static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2) { int i; - for (i = 0; i < 20; i++, sha1++, sha2++) { + for (i = 0; i < GIT_SHA1_RAWSZ; i++, sha1++, sha2++) { if (*sha1 != *sha2) return *sha1 - *sha2; } @@@ -798,42 -731,20 +798,42 @@@ return 0; } +static inline int oidcmp(const struct object_id *oid1, const struct object_id *oid2) +{ + return hashcmp(oid1->hash, oid2->hash); +} + static inline int is_null_sha1(const unsigned char *sha1) { return !hashcmp(sha1, null_sha1); } +static inline int is_null_oid(const struct object_id *oid) +{ + return !hashcmp(oid->hash, null_sha1); +} + static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src) { - memcpy(sha_dst, sha_src, 20); + memcpy(sha_dst, sha_src, GIT_SHA1_RAWSZ); +} + +static inline void oidcpy(struct object_id *dst, const struct object_id *src) +{ + hashcpy(dst->hash, src->hash); } + static inline void hashclr(unsigned char *hash) { - memset(hash, 0, 20); + memset(hash, 0, GIT_SHA1_RAWSZ); +} + +static inline void oidclr(struct object_id *oid) +{ + hashclr(oid->hash); } + #define EMPTY_TREE_SHA1_HEX \ "4b825dc642cb6eb9a060e54bf8d69288fbee4904" #define EMPTY_TREE_SHA1_BIN_LITERAL \ @@@ -904,6 -815,7 +904,6 @@@ enum scld_error safe_create_leading_dir enum scld_error 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) @@@ -923,16 -835,8 +923,16 @@@ char *strip_path_suffix(const char *pat int daemon_avoid_alias(const char *path); extern int is_ntfs_dotgit(const char *name); +/** + * Return a newly allocated string with the evaluation of + * "$XDG_CONFIG_HOME/git/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise + * "$HOME/.config/git/$filename". Return NULL upon error. + */ +extern char *xdg_config_home(const char *filename); + /* object replacement */ #define LOOKUP_REPLACE_OBJECT 1 +#define LOOKUP_UNKNOWN_OBJECT 2 extern void *read_sha1_file_extended(const unsigned char *sha1, enum object_type *type, unsigned long *size, unsigned flag); static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size) { @@@ -969,7 -873,6 +969,7 @@@ static inline const unsigned char *look extern int sha1_object_info(const unsigned char *, unsigned long *); extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1); extern int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *return_sha1); +extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags); extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); extern int force_object_loose(const unsigned char *sha1, time_t mtime); extern int git_open_noatime(const char *name); @@@ -982,7 -885,7 +982,7 @@@ extern int do_check_packed_object_crc extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type); -extern int move_temp_to_file(const char *tmpfile, const char *filename); +extern int finalize_object_file(const char *tmpfile, const char *filename); extern int has_sha1_pack(const unsigned char *sha1); @@@ -990,17 -893,8 +990,17 @@@ * Return true iff we have an object named sha1, whether local or in * an alternate object database, and whether packed or loose. This * function does not respect replace references. + * + * If the QUICK flag is set, do not re-check the pack directory + * when we cannot find the object (this means we may give a false + * negative answer if another process is simultaneously repacking). */ -extern int has_sha1_file(const unsigned char *sha1); +#define HAS_SHA1_QUICK 0x1 +extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags); +static inline int has_sha1_file(const unsigned char *sha1) +{ + return has_sha1_file_with_flags(sha1, 0); +} /* * Return true iff an alternate object database has a loose object @@@ -1027,21 -921,15 +1027,21 @@@ struct object_context unsigned char tree[20]; char path[PATH_MAX]; unsigned mode; + /* + * symlink_path is only used by get_tree_entry_follow_symlinks, + * and only for symlinks that point outside the repository. + */ + struct strbuf symlink_path; }; -#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 +#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_FOLLOW_SYMLINKS 0100 +#define GET_SHA1_ONLY_TO_DIE 04000 extern int get_sha1(const char *str, unsigned char *sha1); extern int get_sha1_commit(const char *str, unsigned char *sha1); @@@ -1063,14 -951,78 +1063,14 @@@ extern int for_each_abbrev(const char * * null-terminated string. */ extern int get_sha1_hex(const char *hex, unsigned char *sha1); +extern int get_oid_hex(const char *hex, struct object_id *sha1); extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ -extern int read_ref_full(const char *refname, int resolve_flags, - unsigned char *sha1, int *flags); -extern int read_ref(const char *refname, unsigned char *sha1); +extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */ -/* - * Resolve a reference, recursively following symbolic refererences. - * - * Store the referred-to object's name in sha1 and return the name of - * the non-symbolic reference that ultimately pointed at it. The - * return value, if not NULL, is a pointer into either a static buffer - * or the input ref. - * - * If the reference cannot be resolved to an object, the behavior - * depends on the RESOLVE_REF_READING flag: - * - * - If RESOLVE_REF_READING is set, return NULL. - * - * - If RESOLVE_REF_READING is not set, clear sha1 and return the name of - * the last reference name in the chain, which will either be a non-symbolic - * reference or an undefined reference. If this is a prelude to - * "writing" to the ref, the return value is the name of the ref - * that will actually be created or changed. - * - * If the RESOLVE_REF_NO_RECURSE flag is passed, only resolves one - * level of symbolic reference. The value stored in sha1 for a symbolic - * reference will always be null_sha1 in this case, and the return - * value is the reference that the symref refers to directly. - * - * If flags is non-NULL, set the value that it points to the - * combination of REF_ISPACKED (if the reference was found among the - * packed references), REF_ISSYMREF (if the initial reference was a - * symbolic reference), REF_BAD_NAME (if the reference name is ill - * formed --- see RESOLVE_REF_ALLOW_BAD_NAME below), and REF_ISBROKEN - * (if the ref is malformed or has a bad name). See refs.h for more detail - * on each flag. - * - * If ref is not a properly-formatted, normalized reference, return - * NULL. If more than MAXDEPTH recursive symbolic lookups are needed, - * give up and return NULL. - * - * RESOLVE_REF_ALLOW_BAD_NAME allows resolving refs even when their - * name is invalid according to git-check-ref-format(1). If the name - * is bad then the value stored in sha1 will be null_sha1 and the two - * flags REF_ISBROKEN and REF_BAD_NAME will be set. - * - * Even with RESOLVE_REF_ALLOW_BAD_NAME, names that escape the refs/ - * directory and do not consist of all caps and underscores cannot be - * resolved. The function returns NULL for such ref names. - * Caps and underscores refers to the special refs, such as HEAD, - * FETCH_HEAD and friends, that all live outside of the refs/ directory. - */ -#define RESOLVE_REF_READING 0x01 -#define RESOLVE_REF_NO_RECURSE 0x02 -#define RESOLVE_REF_ALLOW_BAD_NAME 0x04 -extern const char *resolve_ref_unsafe(const char *ref, int resolve_flags, unsigned char *sha1, int *flags); -extern char *resolve_refdup(const char *ref, int resolve_flags, unsigned char *sha1, int *flags); - -extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref); -extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref); extern int interpret_branch_name(const char *str, int len, struct strbuf *); extern int get_sha1_mb(const char *str, unsigned char *sha1); -/* - * Return true iff abbrev_name is a possible abbreviation for - * full_name according to the rules defined by ref_rev_parse_rules in - * refs.c. - */ -extern int refname_match(const char *abbrev_name, const char *full_name); - -extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg); extern int validate_headref(const char *ref); extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); @@@ -1086,30 -1038,18 +1086,30 @@@ extern void *read_object_with_reference extern struct object *peel_to_type(const char *name, int namelen, struct object *o, enum object_type); -enum date_mode { - DATE_NORMAL = 0, - DATE_RELATIVE, - DATE_SHORT, - DATE_LOCAL, - DATE_ISO8601, - DATE_ISO8601_STRICT, - DATE_RFC2822, - DATE_RAW +struct date_mode { + enum date_mode_type { + DATE_NORMAL = 0, + DATE_RELATIVE, + DATE_SHORT, + DATE_LOCAL, + DATE_ISO8601, + DATE_ISO8601_STRICT, + DATE_RFC2822, + DATE_STRFTIME, + DATE_RAW + } type; + const char *strftime_fmt; }; -const char *show_date(unsigned long time, int timezone, enum date_mode mode); +/* + * Convenience helper for passing a constant type, like: + * + * show_date(t, tz, DATE_MODE(NORMAL)); + */ +#define DATE_MODE(t) date_mode_from_type(DATE_##t) +struct date_mode *date_mode_from_type(enum date_mode_type type); + +const char *show_date(unsigned long time, int timezone, const struct date_mode *mode); void show_date_relative(unsigned long time, int tz, const struct timeval *now, struct strbuf *timebuf); int parse_date(const char *date, struct strbuf *out); @@@ -1119,7 -1059,7 +1119,7 @@@ void datestamp(struct strbuf *out) #define approxidate(s) approxidate_careful((s), NULL) unsigned long approxidate_careful(const char *, int *); unsigned long approxidate_relative(const char *date, const struct timeval *now); -enum date_mode parse_date_format(const char *format); +void parse_date_format(const char *format, struct date_mode *mode); int date_overflows(unsigned long date); #define IDENT_STRICT 1 @@@ -1156,8 -1096,7 +1156,8 @@@ extern int split_ident_line(struct iden * the ident_split. It will also sanity-check the values and produce * a well-known sentinel date if they appear bogus. */ -const char *show_ident_date(const struct ident_split *id, enum date_mode mode); +const char *show_ident_date(const struct ident_split *id, + const struct date_mode *mode); /* * Compare split idents for equality or strict ordering. Note that we @@@ -1234,7 -1173,6 +1234,7 @@@ extern struct packed_git int pack_fd; unsigned pack_local:1, pack_keep:1, + freshened:1, do_not_close:1; unsigned char sha1[20]; /* something like ".git/objects/pack/xxxxx.pack" */ @@@ -1323,10 -1261,6 +1323,10 @@@ extern int unpack_object_header(struct * * Any callback that is NULL will be ignored. Callbacks returning non-zero * will end the iteration. + * + * In the "buf" variant, "path" is a strbuf which will also be used as a + * scratch buffer, but restored to its original contents before + * the function returns. */ typedef int each_loose_object_fn(const unsigned char *sha1, const char *path, @@@ -1342,24 -1276,17 +1342,24 @@@ int for_each_loose_file_in_objdir(cons each_loose_cruft_fn cruft_cb, each_loose_subdir_fn subdir_cb, void *data); +int for_each_loose_file_in_objdir_buf(struct strbuf *path, + each_loose_object_fn obj_cb, + each_loose_cruft_fn cruft_cb, + each_loose_subdir_fn subdir_cb, + void *data); /* * Iterate over loose and packed objects in both the local - * repository and any alternates repositories. + * repository and any alternates repositories (unless the + * LOCAL_ONLY flag is set). */ +#define FOR_EACH_OBJECT_LOCAL_ONLY 0x1 typedef int each_packed_object_fn(const unsigned char *sha1, struct packed_git *pack, uint32_t pos, void *data); -extern int for_each_loose_object(each_loose_object_fn, void *); -extern int for_each_packed_object(each_packed_object_fn, void *); +extern int for_each_loose_object(each_loose_object_fn, void *, unsigned flags); +extern int for_each_packed_object(each_packed_object_fn, void *, unsigned flags); struct object_info { /* Request */ @@@ -1367,7 -1294,6 +1367,7 @@@ unsigned long *sizep; unsigned long *disk_sizep; unsigned char *delta_base_sha1; + struct strbuf *typename; /* Response */ enum { @@@ -1440,6 -1366,7 +1440,7 @@@ extern int git_config_pathname(const ch extern int git_config_set_in_file(const char *, const char *, const char *); extern int git_config_set(const char *, const char *); extern int git_config_parse_key(const char *, char **, int *); + extern int git_config_key_is_valid(const char *key); extern int git_config_set_multivar(const char *, const char *, const char *, int); extern int git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int); extern int git_config_rename_section(const char *, const char *); @@@ -1556,13 -1483,9 +1557,13 @@@ extern const char *git_mailmap_blob extern void maybe_flush_or_die(FILE *, const char *); __attribute__((format (printf, 2, 3))) extern void fprintf_or_die(FILE *, const char *fmt, ...); + +#define COPY_READ_ERROR (-2) +#define COPY_WRITE_ERROR (-3) extern int copy_fd(int ifd, int ofd); extern int copy_file(const char *dst, const char *src, int mode); extern int copy_file_with_time(const char *dst, const char *src, int mode); + extern void write_or_die(int fd, const void *buf, size_t count); extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg); extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg); @@@ -1576,8 -1499,6 +1577,8 @@@ static inline ssize_t write_str_in_full { return write_in_full(fd, str, strlen(str)); } +__attribute__((format (printf, 3, 4))) +extern int write_file(const char *path, int fatal, const char *fmt, ...); /* pager.c */ extern void setup_pager(void); @@@ -1585,7 -1506,7 +1586,7 @@@ extern const char *pager_program extern int pager_in_use(void); extern int pager_use_color; extern int term_columns(void); -extern int decimal_width(int); +extern int decimal_width(uintmax_t); extern int check_pager_config(const char *cmd); extern const char *editor_program; @@@ -1647,6 -1568,7 +1648,6 @@@ extern int ws_blank_line(const char *li #define ws_tab_width(rule) ((rule) & WS_TAB_WIDTH_MASK) /* ls-files */ -int report_path_error(const char *ps_matched, const struct pathspec *pathspec, const char *prefix); void overlay_tree_on_cache(const char *tree_name, const char *prefix); char *alias_lookup(const char *alias); @@@ -1701,6 -1623,5 +1702,6 @@@ int stat_validity_check(struct stat_val void stat_validity_update(struct stat_validity *sv, int fd); int versioncmp(const char *s1, const char *s2); +void sleep_millisec(int millisec); #endif /* CACHE_H */ diff --combined config.c index c027e6fbe0,12692d9b6f..6c8d91a0f2 --- a/config.c +++ b/config.c @@@ -12,7 -12,6 +12,7 @@@ #include "quote.h" #include "hashmap.h" #include "string-list.h" +#include "utf8.h" struct config_source { struct config_source *prev; @@@ -50,7 -49,7 +50,7 @@@ static struct config_set the_config_set static int config_file_fgetc(struct config_source *conf) { - return fgetc(conf->u.file); + return getc_unlocked(conf->u.file); } static int config_file_ungetc(int c, struct config_source *conf) @@@ -74,12 -73,8 +74,12 @@@ static int config_buf_fgetc(struct conf static int config_buf_ungetc(int c, struct config_source *conf) { - if (conf->u.buf.pos > 0) - return conf->u.buf.buf[--conf->u.buf.pos]; + if (conf->u.buf.pos > 0) { + conf->u.buf.pos--; + if (conf->u.buf.buf[conf->u.buf.pos] != c) + die("BUG: config_buf can only ungetc the same character"); + return c; + } return EOF; } @@@ -240,8 -235,7 +240,8 @@@ static int get_next_char(void /* DOS like systems */ c = cf->do_fgetc(cf); if (c != '\n') { - cf->do_ungetc(c, cf); + if (c != EOF) + cf->do_ungetc(c, cf); c = '\r'; } } @@@ -418,7 -412,8 +418,7 @@@ static int git_parse_source(config_fn_ struct strbuf *var = &cf->var; /* U+FEFF Byte Order Mark in UTF8 */ - static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf"; - const unsigned char *bomptr = utf8_bom; + const char *bomptr = utf8_bom; for (;;) { int c = get_next_char(); @@@ -426,7 -421,7 +426,7 @@@ /* We are at the file beginning; skip UTF8-encoded BOM * if present. Sane editors won't put this in on their * own, but e.g. Windows Notepad will do it happily. */ - if ((unsigned char) c == *bomptr) { + if (c == (*bomptr & 0377)) { bomptr++; continue; } else { @@@ -1088,9 -1083,7 +1088,9 @@@ int git_config_from_file(config_fn_t fn f = fopen(filename, "r"); if (f) { + flockfile(f); ret = do_config_from_file(fn, filename, filename, f, data); + funlockfile(f); fclose(f); } return ret; @@@ -1187,8 -1180,10 +1187,8 @@@ int git_config_system(void int git_config_early(config_fn_t fn, void *data, const char *repo_config) { int ret = 0, found = 0; - char *xdg_config = NULL; - char *user_config = NULL; - - home_config_paths(&user_config, &xdg_config, "config"); + char *xdg_config = xdg_config_home("config"); + char *user_config = expand_user_path("~/.gitconfig"); if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) { ret += git_config_from_file(fn, git_etc_gitconfig(), @@@ -1345,7 -1340,7 +1345,7 @@@ static int configset_add_value(struct c string_list_init(&e->value_list, 1); hashmap_add(&cs->config_hash, e); } - si = string_list_append_nodup(&e->value_list, value ? xstrdup(value) : NULL); + si = string_list_append_nodup(&e->value_list, xstrdup_or_null(value)); ALLOC_GROW(cs->list.items, cs->list.nr + 1, cs->list.alloc); l_item = &cs->list.items[cs->list.nr++]; @@@ -1848,7 -1843,7 +1848,7 @@@ int git_config_set(const char *key, con * baselen - pointer to int which will hold the length of the * section + subsection part, can be NULL */ - int git_config_parse_key(const char *key, char **store_key, int *baselen_) + static int git_config_parse_key_1(const char *key, char **store_key, int *baselen_, int quiet) { int i, dot, baselen; const char *last_dot = strrchr(key, '.'); @@@ -1859,12 -1854,14 +1859,14 @@@ */ if (last_dot == NULL || last_dot == key) { - error("key does not contain a section: %s", key); + if (!quiet) + error("key does not contain a section: %s", key); return -CONFIG_NO_SECTION_OR_NAME; } if (!last_dot[1]) { - error("key does not contain variable name: %s", key); + if (!quiet) + error("key does not contain variable name: %s", key); return -CONFIG_NO_SECTION_OR_NAME; } @@@ -1875,7 -1872,8 +1877,8 @@@ /* * Validate the key and while at it, lower case it for matching. */ - *store_key = xmalloc(strlen(key) + 1); + if (store_key) + *store_key = xmalloc(strlen(key) + 1); dot = 0; for (i = 0; key[i]; i++) { @@@ -1886,26 -1884,42 +1889,42 @@@ if (!dot || i > baselen) { if (!iskeychar(c) || (i == baselen + 1 && !isalpha(c))) { - error("invalid key: %s", key); + if (!quiet) + error("invalid key: %s", key); goto out_free_ret_1; } c = tolower(c); } else if (c == '\n') { - error("invalid key (newline): %s", key); + if (!quiet) + error("invalid key (newline): %s", key); goto out_free_ret_1; } - (*store_key)[i] = c; + if (store_key) + (*store_key)[i] = c; } - (*store_key)[i] = 0; + if (store_key) + (*store_key)[i] = 0; return 0; out_free_ret_1: - free(*store_key); - *store_key = NULL; + if (store_key) { + free(*store_key); + *store_key = NULL; + } return -CONFIG_INVALID_KEY; } + int git_config_parse_key(const char *key, char **store_key, int *baselen) + { + return git_config_parse_key_1(key, store_key, baselen, 0); + } + + int git_config_key_is_valid(const char *key) + { + return !git_config_parse_key_1(key, NULL, NULL, 1); + } + /* * If value==NULL, unset in (remove from) config, * if value_regex!=NULL, disregard key/value pairs where value does not match. @@@ -1935,12 -1949,10 +1954,12 @@@ int git_config_set_multivar_in_file(con const char *key, const char *value, const char *value_regex, int multi_replace) { - int fd = -1, in_fd; + int fd = -1, in_fd = -1; int ret; struct lock_file *lock = NULL; char *filename_buf = NULL; + char *contents = NULL; + size_t contents_sz; /* parse-key returns negative; flip the sign to feed exit(3) */ ret = 0 - git_config_parse_key(key, &store.key, &store.baselen); @@@ -1990,7 -2002,8 +2009,7 @@@ goto write_err_out; } else { struct stat st; - char *contents; - size_t contents_sz, copy_begin, copy_end; + size_t copy_begin, copy_end; int i, new_line = 0; if (value_regex == NULL) @@@ -2053,23 -2066,13 +2072,23 @@@ fstat(in_fd, &st); contents_sz = xsize_t(st.st_size); - contents = xmmap(NULL, contents_sz, PROT_READ, - MAP_PRIVATE, in_fd, 0); + contents = xmmap_gently(NULL, contents_sz, PROT_READ, + MAP_PRIVATE, in_fd, 0); + if (contents == MAP_FAILED) { + if (errno == ENODEV && S_ISDIR(st.st_mode)) + errno = EISDIR; + error("unable to mmap '%s': %s", + config_filename, strerror(errno)); + ret = CONFIG_INVALID_FILE; + contents = NULL; + goto out_free; + } close(in_fd); + in_fd = -1; - if (chmod(lock->filename.buf, st.st_mode & 07777) < 0) { + if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) { error("chmod on %s failed: %s", - lock->filename.buf, strerror(errno)); + get_lock_file_path(lock), strerror(errno)); ret = CONFIG_NO_WRITE; goto out_free; } @@@ -2121,7 -2124,6 +2140,7 @@@ goto write_err_out; munmap(contents, contents_sz); + contents = NULL; } if (commit_lock_file(lock) < 0) { @@@ -2147,14 -2149,10 +2166,14 @@@ out_free if (lock) rollback_lock_file(lock); free(filename_buf); + if (contents) + munmap(contents, contents_sz); + if (in_fd >= 0) + close(in_fd); return ret; write_err_out: - ret = write_error(lock->filename.buf); + ret = write_error(get_lock_file_path(lock)); goto out_free; } @@@ -2255,9 -2253,9 +2274,9 @@@ int git_config_rename_section_in_file(c fstat(fileno(config_file), &st); - if (chmod(lock->filename.buf, st.st_mode & 07777) < 0) { + if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) { ret = error("chmod on %s failed: %s", - lock->filename.buf, strerror(errno)); + get_lock_file_path(lock), strerror(errno)); goto out; } @@@ -2278,7 -2276,7 +2297,7 @@@ } store.baselen = strlen(new_name); if (!store_write_section(out_fd, new_name)) { - ret = write_error(lock->filename.buf); + ret = write_error(get_lock_file_path(lock)); goto out; } /* @@@ -2304,7 -2302,7 +2323,7 @@@ continue; length = strlen(output); if (write_in_full(out_fd, output, length) != length) { - ret = write_error(lock->filename.buf); + ret = write_error(get_lock_file_path(lock)); goto out; } } diff --combined pager.c index 070dc11cb0,09c232a0b4..27d4c8a17a --- a/pager.c +++ b/pager.c @@@ -78,7 -78,6 +78,7 @@@ void setup_pager(void argv_array_push(&pager_process.env_array, "LESS=FRX"); if (!getenv("LV")) argv_array_push(&pager_process.env_array, "LV=-c"); + argv_array_push(&pager_process.env_array, "GIT_PAGER_IN_USE"); if (start_command(&pager_process)) return; @@@ -134,12 -133,12 +134,12 @@@ int term_columns(void /* * How many columns do we need to show this number in decimal? */ -int decimal_width(int number) +int decimal_width(uintmax_t number) { - int i, width; + int width; - for (width = 1, i = 10; i <= number; width++) - i *= 10; + for (width = 1; number >= 10; width++) + number /= 10; return width; } @@@ -150,7 -149,8 +150,8 @@@ int check_pager_config(const char *cmd struct strbuf key = STRBUF_INIT; const char *value = NULL; strbuf_addf(&key, "pager.%s", cmd); - if (!git_config_get_value(key.buf, &value)) { + if (git_config_key_is_valid(key.buf) && + !git_config_get_value(key.buf, &value)) { int b = git_config_maybe_bool(key.buf, value); if (b >= 0) want = b; diff --combined t/t7006-pager.sh index 947b690fd7,2dd71c055c..6ea7ac4c41 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@@ -396,7 -396,7 +396,7 @@@ test_expect_success TTY 'command-specif sane_unset PAGER GIT_PAGER && echo "foo:initial" >expect && >actual && - test_config core.pager "exit 1" + test_config core.pager "exit 1" && test_config pager.log "sed s/^/foo:/ >actual" && test_terminal git log --format=%s -1 && test_cmp expect actual @@@ -447,4 -447,13 +447,13 @@@ test_expect_success TTY 'external comma test_cmp expect actual ' + test_expect_success 'command with underscores does not complain' ' + write_script git-under_score <<-\EOF && + echo ok + EOF + git --exec-path=. under_score >actual 2>&1 && + echo ok >expect && + test_cmp expect actual + ' + test_done