From: Junio C Hamano Date: Fri, 22 Dec 2017 20:48:38 +0000 (-0800) Subject: Merge branch 'ew/empty-merge-with-dirty-index-maint' into ew/empty-merge-with-dirty... X-Git-Tag: v2.16.0-rc1~7^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=b6825b5c8e8b58943511f2576475accf1593486e;hp=-c;p=git-core%2Fgit.git Merge branch 'ew/empty-merge-with-dirty-index-maint' into ew/empty-merge-with-dirty-index * ew/empty-merge-with-dirty-index-maint: merge-recursive: avoid incorporating uncommitted changes in a merge move index_has_changes() from builtin/am.c to merge.c for reuse t6044: recursive can silently incorporate dirty changes in a merge --- b6825b5c8e8b58943511f2576475accf1593486e diff --combined builtin/am.c index 3d98e5208,71619f01a..a02d5186c --- a/builtin/am.c +++ b/builtin/am.c @@@ -1068,8 -1068,8 +1068,8 @@@ static void am_setup(struct am_state *s if (!get_oid("HEAD", &curr_head)) { write_state_text(state, "abort-safety", oid_to_hex(&curr_head)); if (!state->rebasing) - update_ref_oid("am", "ORIG_HEAD", &curr_head, NULL, 0, - UPDATE_REFS_DIE_ON_ERR); + update_ref("am", "ORIG_HEAD", &curr_head, NULL, 0, + UPDATE_REFS_DIE_ON_ERR); } else { write_state_text(state, "abort-safety", ""); if (!state->rebasing) @@@ -1134,52 -1134,15 +1134,15 @@@ static const char *msgnum(const struct */ static void refresh_and_write_cache(void) { - struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); + struct lock_file lock_file = LOCK_INIT; - hold_locked_index(lock_file, LOCK_DIE_ON_ERROR); + hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); refresh_cache(REFRESH_QUIET); - if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) + if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) die(_("unable to write index file")); } /** - * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn - * branch, returns 1 if there are entries in the index, 0 otherwise. If an - * strbuf is provided, the space-separated list of files that differ will be - * appended to it. - */ - static int index_has_changes(struct strbuf *sb) - { - struct object_id head; - int i; - - if (!get_oid_tree("HEAD", &head)) { - struct diff_options opt; - - diff_setup(&opt); - opt.flags.exit_with_status = 1; - if (!sb) - opt.flags.quick = 1; - do_diff_cache(&head, &opt); - diffcore_std(&opt); - for (i = 0; sb && i < diff_queued_diff.nr; i++) { - if (i) - strbuf_addch(sb, ' '); - strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path); - } - diff_flush(&opt); - return opt.flags.has_changes != 0; - } else { - for (i = 0; sb && i < active_nr; i++) { - if (i) - strbuf_addch(sb, ' '); - strbuf_addstr(sb, active_cache[i]->name); - } - return !!active_nr; - } - } - - /** * Dies with a user-friendly message on how to proceed after resolving the * problem. This message can be overridden with state->resolvemsg. */ @@@ -1409,8 -1372,8 +1372,8 @@@ static void write_commit_patch(const st rev_info.show_root_diff = 1; rev_info.diffopt.output_format = DIFF_FORMAT_PATCH; rev_info.no_commit_id = 1; - DIFF_OPT_SET(&rev_info.diffopt, BINARY); - DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX); + rev_info.diffopt.flags.binary = 1; + rev_info.diffopt.flags.full_index = 1; rev_info.diffopt.use_color = 0; rev_info.diffopt.file = fp; rev_info.diffopt.close_file = 1; @@@ -1433,7 -1396,7 +1396,7 @@@ static void write_index_patch(const str if (!get_oid_tree("HEAD", &head)) tree = lookup_tree(&head); else - tree = lookup_tree(&empty_tree_oid); + tree = lookup_tree(the_hash_algo->empty_tree); fp = xfopen(am_path(state, "patch"), "w"); init_revisions(&rev_info, NULL); @@@ -1488,10 -1451,11 +1451,10 @@@ static int run_apply(const struct am_st struct argv_array apply_opts = ARGV_ARRAY_INIT; struct apply_state apply_state; int res, opts_left; - static struct lock_file lock_file; int force_apply = 0; int options = 0; - if (init_apply_state(&apply_state, NULL, &lock_file)) + if (init_apply_state(&apply_state, NULL)) die("BUG: init_apply_state() failed"); argv_array_push(&apply_opts, "apply"); @@@ -1685,8 -1649,8 +1648,8 @@@ static void do_commit(const struct am_s strbuf_addf(&sb, "%s: %.*s", reflog_msg, linelen(state->msg), state->msg); - update_ref_oid(sb.buf, "HEAD", &commit, old_oid, 0, - UPDATE_REFS_DIE_ON_ERR); + update_ref(sb.buf, "HEAD", &commit, old_oid, 0, + UPDATE_REFS_DIE_ON_ERR); if (state->rebasing) { FILE *fp = xfopen(am_path(state, "rewritten"), "a"); @@@ -1945,14 -1909,15 +1908,14 @@@ next */ static int fast_forward_to(struct tree *head, struct tree *remote, int reset) { - struct lock_file *lock_file; + struct lock_file lock_file = LOCK_INIT; struct unpack_trees_options opts; struct tree_desc t[2]; if (parse_tree(head) || parse_tree(remote)) return -1; - lock_file = xcalloc(1, sizeof(struct lock_file)); - hold_locked_index(lock_file, LOCK_DIE_ON_ERROR); + hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); refresh_cache(REFRESH_QUIET); @@@ -1968,11 -1933,11 +1931,11 @@@ init_tree_desc(&t[1], remote->buffer, remote->size); if (unpack_trees(2, t, &opts)) { - rollback_lock_file(lock_file); + rollback_lock_file(&lock_file); return -1; } - if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) + if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); return 0; @@@ -1984,14 -1949,15 +1947,14 @@@ */ static int merge_tree(struct tree *tree) { - struct lock_file *lock_file; + struct lock_file lock_file = LOCK_INIT; struct unpack_trees_options opts; struct tree_desc t[1]; if (parse_tree(tree)) return -1; - lock_file = xcalloc(1, sizeof(struct lock_file)); - hold_locked_index(lock_file, LOCK_DIE_ON_ERROR); + hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); memset(&opts, 0, sizeof(opts)); opts.head_idx = 1; @@@ -2002,11 -1968,11 +1965,11 @@@ init_tree_desc(&t[0], tree->buffer, tree->size); if (unpack_trees(1, t, &opts)) { - rollback_lock_file(lock_file); + rollback_lock_file(&lock_file); return -1; } - if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) + if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); return 0; @@@ -2132,7 -2098,7 +2095,7 @@@ static void am_abort(struct am_state *s am_rerere_clear(); - curr_branch = resolve_refdup("HEAD", 0, curr_head.hash, NULL); + curr_branch = resolve_refdup("HEAD", 0, &curr_head, NULL); has_curr_head = curr_branch && !is_null_oid(&curr_head); if (!has_curr_head) hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN); @@@ -2144,11 -2110,11 +2107,11 @@@ clean_index(&curr_head, &orig_head); if (has_orig_head) - update_ref_oid("am --abort", "HEAD", &orig_head, - has_curr_head ? &curr_head : NULL, 0, - UPDATE_REFS_DIE_ON_ERR); + update_ref("am --abort", "HEAD", &orig_head, + has_curr_head ? &curr_head : NULL, 0, + UPDATE_REFS_DIE_ON_ERR); else if (curr_branch) - delete_ref(NULL, curr_branch, NULL, REF_NODEREF); + delete_ref(NULL, curr_branch, NULL, REF_NO_DEREF); free(curr_branch); am_destroy(state); diff --combined cache.h index a2ec8c0b5,caf610d3b..d8b975a57 --- a/cache.h +++ b/cache.h @@@ -14,7 -14,6 +14,7 @@@ #include "hash.h" #include "path.h" #include "sha1-array.h" +#include "repository.h" #ifndef platform_SHA_CTX /* @@@ -78,8 -77,6 +78,8 @@@ struct object_id unsigned char hash[GIT_MAX_RAWSZ]; }; +#define the_hash_algo the_repository->hash_algo + #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT) #define DTYPE(de) ((de)->d_type) #else @@@ -207,7 -204,6 +207,7 @@@ struct cache_entry #define CE_ADDED (1 << 19) #define CE_HASHED (1 << 20) +#define CE_FSMONITOR_VALID (1 << 21) #define CE_WT_REMOVE (1 << 22) /* remove in work directory */ #define CE_CONFLICTED (1 << 23) @@@ -331,7 -327,6 +331,7 @@@ static inline unsigned int canon_mode(u #define CACHE_TREE_CHANGED (1 << 5) #define SPLIT_INDEX_ORDERED (1 << 6) #define UNTRACKED_CHANGED (1 << 7) +#define FSMONITOR_CHANGED (1 << 8) struct split_index; struct untracked_cache; @@@ -350,8 -345,6 +350,8 @@@ struct index_state struct hashmap dir_hash; unsigned char sha1[20]; struct untracked_cache *untracked; + uint64_t fsmonitor_last_update; + struct ewah_bitmap *fsmonitor_dirty; }; extern struct index_state the_index; @@@ -454,16 -447,6 +454,16 @@@ static inline enum object_type object_t #define GIT_OPTIONAL_LOCKS_ENVIRONMENT "GIT_OPTIONAL_LOCKS" /* + * Environment variable used in handshaking the wire protocol. + * Contains a colon ':' separated list of keys with optional values + * 'key[=value]'. Presence of unknown keys and values must be + * ignored. + */ +#define GIT_PROTOCOL_ENVIRONMENT "GIT_PROTOCOL" +/* HTTP header used to handshake the wire protocol */ +#define GIT_PROTOCOL_HEADER "Git-Protocol" + +/* * This environment variable is expected to contain a boolean indicating * whether we should or should not treat: * @@@ -619,31 -602,21 +619,40 @@@ extern int do_read_index(struct index_s extern int read_index_from(struct index_state *, const char *path); extern int is_index_unborn(struct index_state *); extern int read_index_unmerged(struct index_state *); + +/* For use with `write_locked_index()`. */ #define COMMIT_LOCK (1 << 0) -#define CLOSE_LOCK (1 << 1) + +/* + * Write the index while holding an already-taken lock. Close the lock, + * and if `COMMIT_LOCK` is given, commit it. + * + * Unless a split index is in use, write the index into the lockfile. + * + * With a split index, write the shared index to a temporary file, + * adjust its permissions and rename it into place, then write the + * split index to the lockfile. If the temporary file for the shared + * index cannot be created, fall back to the behavior described in + * the previous paragraph. + * + * With `COMMIT_LOCK`, the lock is always committed or rolled back. + * Without it, the lock is closed, but neither committed nor rolled + * back. + */ extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags); + extern int discard_index(struct index_state *); extern void move_index_extensions(struct index_state *dst, struct index_state *src); extern int unmerged_index(const struct index_state *); + + /** + * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn + * branch, returns 1 if there are entries in the index, 0 otherwise. If an + * strbuf is provided, the space-separated list of files that differ will be + * appended to it. + */ + extern int index_has_changes(struct strbuf *sb); + extern int verify_path(const char *path); extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change); extern int index_dir_exists(struct index_state *istate, const char *name, int namelen); @@@ -717,14 -690,11 +726,14 @@@ extern void *read_blob_data_from_index( #define CE_MATCH_IGNORE_MISSING 0x08 /* enable stat refresh */ #define CE_MATCH_REFRESH 0x10 -extern int ie_match_stat(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int); -extern int ie_modified(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int); +/* don't refresh_fsmonitor state or do stat comparison even if CE_FSMONITOR_VALID is true */ +#define CE_MATCH_IGNORE_FSMONITOR 0X20 +extern int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int); +extern int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int); #define HASH_WRITE_OBJECT 1 #define HASH_FORMAT_CHECK 2 +#define HASH_RENORMALIZE 4 extern int index_fd(struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags); extern int index_path(struct object_id *oid, const char *path, struct stat *st, unsigned flags); @@@ -755,17 -725,12 +764,17 @@@ extern void fill_stat_cache_info(struc extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg); extern struct cache_entry *refresh_cache_entry(struct cache_entry *, unsigned int); +/* + * Opportunistically update the index but do not complain if we can't. + * The lockfile is always committed or rolled back. + */ extern void update_index_if_able(struct index_state *, struct lock_file *); extern int hold_locked_index(struct lock_file *, int); extern void set_alternate_index_output(const char *); extern int verify_index_checksum; +extern int verify_ce_order; /* Environment bits from configuration mechanism */ extern int trust_executable_bit; @@@ -819,7 -784,6 +828,7 @@@ extern int core_apply_sparse_checkout extern int precomposed_unicode; extern int protect_hfs; extern int protect_ntfs; +extern const char *core_fsmonitor; /* * Include broken refs in all ref iterations, which will @@@ -910,7 -874,6 +919,7 @@@ struct repository_format int version; int precious_objects; int is_bare; + int hash_algo; char *work_tree; struct string_list unknown_extensions; }; @@@ -1043,22 -1006,22 +1052,22 @@@ extern const struct object_id empty_blo static inline int is_empty_blob_sha1(const unsigned char *sha1) { - return !hashcmp(sha1, EMPTY_BLOB_SHA1_BIN); + return !hashcmp(sha1, the_hash_algo->empty_blob->hash); } static inline int is_empty_blob_oid(const struct object_id *oid) { - return !hashcmp(oid->hash, EMPTY_BLOB_SHA1_BIN); + return !oidcmp(oid, the_hash_algo->empty_blob); } static inline int is_empty_tree_sha1(const unsigned char *sha1) { - return !hashcmp(sha1, EMPTY_TREE_SHA1_BIN); + return !hashcmp(sha1, the_hash_algo->empty_tree->hash); } static inline int is_empty_tree_oid(const struct object_id *oid) { - return !hashcmp(oid->hash, EMPTY_TREE_SHA1_BIN); + return !oidcmp(oid, the_hash_algo->empty_tree); } /* set default permissions by passing mode arguments to open(2) */ @@@ -1364,13 -1327,6 +1373,13 @@@ extern int get_sha1_hex(const char *hex extern int get_oid_hex(const char *hex, struct object_id *sha1); /* + * Read `len` pairs of hexadecimal digits from `hex` and write the + * values to `binary` as `len` bytes. Return 0 on success, or -1 if + * the input does not consist of hex digits). + */ +extern int hex_to_bytes(unsigned char *binary, const char *hex, size_t len); + +/* * Convert a binary sha1 to its hex equivalent. The `_r` variant is reentrant, * and writes the NUL-terminated output to the buffer `out`, which must be at * least `GIT_SHA1_HEXSZ + 1` bytes, and returns a pointer to out for @@@ -1491,7 -1447,6 +1500,7 @@@ extern const char *ident_default_name(v extern const char *ident_default_email(void); extern const char *git_editor(void); extern const char *git_pager(int stdout_is_tty); +extern int is_terminal_dumb(void); extern int git_ident_config(const char *, const char *, void *); extern void reset_ident_date(void); @@@ -1973,10 -1928,4 +1982,10 @@@ void sleep_millisec(int millisec) */ void safe_create_dir(const char *dir, int share); +/* + * Should we print an ellipsis after an abbreviated SHA-1 value + * when doing diff-raw output or indicating a detached HEAD? + */ +extern int print_sha1_ellipsis(void); + #endif /* CACHE_H */ diff --combined merge-recursive.c index 2ecf495cc,be01f528c..780f81a8b --- a/merge-recursive.c +++ b/merge-recursive.c @@@ -540,8 -540,8 +540,8 @@@ static struct string_list *get_renames( return renames; diff_setup(&opts); - DIFF_OPT_SET(&opts, RECURSIVE); - DIFF_OPT_CLR(&opts, RENAME_EMPTY); + opts.flags.recursive = 1; + opts.flags.rename_empty = 0; opts.detect_rename = DIFF_DETECT_RENAME; opts.rename_limit = o->merge_rename_limit >= 0 ? o->merge_rename_limit : o->diff_rename_limit >= 0 ? o->diff_rename_limit : @@@ -646,7 -646,7 +646,7 @@@ static int remove_file(struct merge_opt if (ignore_case) { struct cache_entry *ce; ce = cache_file_exists(path, strlen(path), ignore_case); - if (ce && ce_stage(ce) == 0) + if (ce && ce_stage(ce) == 0 && strcmp(path, ce->name)) return 0; } if (remove_path(path)) @@@ -1952,6 -1952,13 +1952,13 @@@ int merge_trees(struct merge_options *o } if (oid_eq(&common->object.oid, &merge->object.oid)) { + struct strbuf sb = STRBUF_INIT; + + if (index_has_changes(&sb)) { + err(o, _("Dirty index: cannot merge (dirty: %s)"), + sb.buf); + return 0; + } output(o, 0, _("Already up to date!")); *result = head; return 1; @@@ -2082,7 -2089,7 +2089,7 @@@ int merge_recursive(struct merge_option /* if there is no common ancestor, use an empty tree */ struct tree *tree; - tree = lookup_tree(&empty_tree_oid); + tree = lookup_tree(the_hash_algo->empty_tree); merged_common_ancestors = make_virtual_commit(tree, "ancestor"); } @@@ -2163,7 -2170,7 +2170,7 @@@ int merge_recursive_generic(struct merg struct commit **result) { int clean; - struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); + struct lock_file lock = LOCK_INIT; struct commit *head_commit = get_ref(head, o->branch1); struct commit *next_commit = get_ref(merge, o->branch2); struct commit_list *ca = NULL; @@@ -2179,14 -2186,14 +2186,14 @@@ } } - hold_locked_index(lock, LOCK_DIE_ON_ERROR); + hold_locked_index(&lock, LOCK_DIE_ON_ERROR); clean = merge_recursive(o, head_commit, next_commit, ca, result); if (clean < 0) return clean; if (active_cache_changed && - write_locked_index(&the_index, lock, COMMIT_LOCK)) + write_locked_index(&the_index, &lock, COMMIT_LOCK)) return err(o, _("Unable to write index.")); return clean ? 0 : 1; @@@ -2202,7 -2209,6 +2209,7 @@@ static void merge_recursive_config(stru void init_merge_options(struct merge_options *o) { + const char *merge_verbosity; memset(o, 0, sizeof(struct merge_options)); o->verbosity = 2; o->buffer_output = 1; @@@ -2211,9 -2217,9 +2218,9 @@@ o->renormalize = 0; o->detect_rename = 1; merge_recursive_config(o); - if (getenv("GIT_MERGE_VERBOSITY")) - o->verbosity = - strtol(getenv("GIT_MERGE_VERBOSITY"), NULL, 10); + merge_verbosity = getenv("GIT_MERGE_VERBOSITY"); + if (merge_verbosity) + o->verbosity = strtol(merge_verbosity, NULL, 10); if (o->verbosity >= 5) o->buffer_output = 0; strbuf_init(&o->obuf, 0); @@@ -2253,8 -2259,6 +2260,8 @@@ int parse_merge_opt(struct merge_option DIFF_XDL_SET(o, IGNORE_WHITESPACE); else if (!strcmp(s, "ignore-space-at-eol")) DIFF_XDL_SET(o, IGNORE_WHITESPACE_AT_EOL); + else if (!strcmp(s, "ignore-cr-at-eol")) + DIFF_XDL_SET(o, IGNORE_CR_AT_EOL); else if (!strcmp(s, "renormalize")) o->renormalize = 1; else if (!strcmp(s, "no-renormalize")) diff --combined merge.c index e5d796c9f,b0714bc85..195b57870 --- a/merge.c +++ b/merge.c @@@ -1,4 -1,6 +1,6 @@@ #include "cache.h" + #include "diff.h" + #include "diffcore.h" #include "lockfile.h" #include "commit.h" #include "run-command.h" @@@ -15,6 -17,37 +17,37 @@@ static const char *merge_argument(struc return EMPTY_TREE_SHA1_HEX; } + int index_has_changes(struct strbuf *sb) + { + struct object_id head; + int i; + + if (!get_oid_tree("HEAD", &head)) { + struct diff_options opt; + + diff_setup(&opt); - DIFF_OPT_SET(&opt, EXIT_WITH_STATUS); ++ opt.flags.exit_with_status = 1; + if (!sb) - DIFF_OPT_SET(&opt, QUICK); ++ opt.flags.quick = 1; + do_diff_cache(&head, &opt); + diffcore_std(&opt); + for (i = 0; sb && i < diff_queued_diff.nr; i++) { + if (i) + strbuf_addch(sb, ' '); + strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path); + } + diff_flush(&opt); - return DIFF_OPT_TST(&opt, HAS_CHANGES) != 0; ++ return opt.flags.has_changes != 0; + } else { + for (i = 0; sb && i < active_nr; i++) { + if (i) + strbuf_addch(sb, ' '); + strbuf_addstr(sb, active_cache[i]->name); + } + return !!active_nr; + } + } + int try_merge_command(const char *strategy, size_t xopts_nr, const char **xopts, struct commit_list *common, const char *head_arg, struct commit_list *remotes) @@@ -53,11 -86,11 +86,11 @@@ int checkout_fast_forward(const struct struct tree_desc t[MAX_UNPACK_TREES]; int i, nr_trees = 0; struct dir_struct dir; - struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); + struct lock_file lock_file = LOCK_INIT; refresh_cache(REFRESH_QUIET); - if (hold_locked_index(lock_file, LOCK_REPORT_ON_ERROR) < 0) + if (hold_locked_index(&lock_file, LOCK_REPORT_ON_ERROR) < 0) return -1; memset(&trees, 0, sizeof(trees)); @@@ -91,7 -124,9 +124,7 @@@ } if (unpack_trees(nr_trees, t, &opts)) return -1; - if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) { - rollback_lock_file(lock_file); + if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) return error(_("unable to write new index file")); - } return 0; }