diff options
-rw-r--r-- | diff-files.c | 10 | ||||
-rw-r--r-- | diff-index.c | 11 | ||||
-rw-r--r-- | read-cache.c | 12 | ||||
-rw-r--r-- | update-index.c | 46 |
4 files changed, 70 insertions, 9 deletions
diff --git a/diff-files.c b/diff-files.c index 96d2c7f19..8a8f9b6dc 100644 --- a/diff-files.c +++ b/diff-files.c @@ -81,7 +81,7 @@ int main(int argc, const char **argv) for (i = 0; i < entries; i++) { struct stat st; - unsigned int oldmode; + unsigned int oldmode, newmode; struct cache_entry *ce = active_cache[i]; int changed; @@ -111,7 +111,13 @@ int main(int argc, const char **argv) if (!changed && !diff_options.find_copies_harder) continue; oldmode = ntohl(ce->ce_mode); - show_modified(oldmode, DIFF_FILE_CANON_MODE(st.st_mode), + + newmode = DIFF_FILE_CANON_MODE(st.st_mode); + if (!trust_executable_bit && + S_ISREG(newmode) && S_ISREG(oldmode) && + ((newmode ^ oldmode) == 0111)) + newmode = oldmode; + show_modified(oldmode, newmode, ce->sha1, (changed ? null_sha1 : ce->sha1), ce->name); } diff --git a/diff-index.c b/diff-index.c index 62b36cc8e..c9a9f4c74 100644 --- a/diff-index.c +++ b/diff-index.c @@ -15,7 +15,7 @@ static void show_file(const char *prefix, } static int get_stat_data(struct cache_entry *ce, - unsigned char **sha1p, unsigned int *modep) + unsigned char ** sha1p, unsigned int *modep) { unsigned char *sha1 = ce->sha1; unsigned int mode = ce->ce_mode; @@ -35,6 +35,10 @@ static int get_stat_data(struct cache_entry *ce, changed = ce_match_stat(ce, &st); if (changed) { mode = create_ce_mode(st.st_mode); + if (!trust_executable_bit && + S_ISREG(mode) && S_ISREG(ce->ce_mode) && + ((mode ^ ce->ce_mode) == 0111)) + mode = ce->ce_mode; sha1 = no_sha1; } } @@ -49,7 +53,9 @@ static void show_new_file(struct cache_entry *new) unsigned char *sha1; unsigned int mode; - /* New file in the index: it might actually be different in the working copy */ + /* New file in the index: it might actually be different in + * the working copy. + */ if (get_stat_data(new, &sha1, &mode) < 0) return; @@ -174,6 +180,7 @@ int main(int argc, const char **argv) int allow_options = 1; int i; + git_config(git_default_config); diff_setup(&diff_options); for (i = 1; i < argc; i++) { const char *arg = argv[i]; diff --git a/read-cache.c b/read-cache.c index c7f3b2686..4ed369acf 100644 --- a/read-cache.c +++ b/read-cache.c @@ -36,8 +36,11 @@ int ce_match_stat(struct cache_entry *ce, struct stat *st) switch (ntohl(ce->ce_mode) & S_IFMT) { case S_IFREG: changed |= !S_ISREG(st->st_mode) ? TYPE_CHANGED : 0; - /* We consider only the owner x bit to be relevant for "mode changes" */ - if (0100 & (ntohl(ce->ce_mode) ^ st->st_mode)) + /* We consider only the owner x bit to be relevant for + * "mode changes" + */ + if (trust_executable_bit && + (0100 & (ntohl(ce->ce_mode) ^ st->st_mode))) changed |= MODE_CHANGED; break; case S_IFLNK: @@ -393,7 +396,7 @@ int add_cache_entry(struct cache_entry *ce, int option) int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK; pos = cache_name_pos(ce->name, ntohs(ce->ce_flags)); - /* existing match? Just replace it */ + /* existing match? Just replace it. */ if (pos >= 0) { active_cache_changed = 1; active_cache[pos] = ce; @@ -416,7 +419,8 @@ int add_cache_entry(struct cache_entry *ce, int option) if (!ok_to_add) return -1; - if (!skip_df_check && check_file_directory_conflict(ce, pos, ok_to_replace)) { + if (!skip_df_check && + check_file_directory_conflict(ce, pos, ok_to_replace)) { if (!ok_to_replace) return -1; pos = cache_name_pos(ce->name, ntohs(ce->ce_flags)); diff --git a/update-index.c b/update-index.c index 01b4088ad..1eeb45dbb 100644 --- a/update-index.c +++ b/update-index.c @@ -67,13 +67,23 @@ static int add_file_to_cache(const char *path) return error("lstat(\"%s\"): %s", path, strerror(errno)); } + namelen = strlen(path); size = cache_entry_size(namelen); ce = xmalloc(size); memset(ce, 0, size); memcpy(ce->name, path, namelen); fill_stat_cache_info(ce, &st); + ce->ce_mode = create_ce_mode(st.st_mode); + if (!trust_executable_bit) { + /* If there is an existing entry, pick the mode bits + * from it. + */ + int pos = cache_name_pos(path, namelen); + if (0 <= pos) + ce->ce_mode = active_cache[pos]->ce_mode; + } ce->ce_flags = htons(namelen); if (index_path(ce->sha1, path, &st, !info_only)) @@ -253,8 +263,32 @@ static int add_cacheinfo(const char *arg1, const char *arg2, const char *arg3) return add_cache_entry(ce, option); } -static struct cache_file cache_file; +static int chmod_path(int flip, const char *path) +{ + int pos; + struct cache_entry *ce; + unsigned int mode; + pos = cache_name_pos(path, strlen(path)); + if (pos < 0) + return -1; + ce = active_cache[pos]; + mode = ntohl(ce->ce_mode); + if (!S_ISREG(mode)) + return -1; + switch (flip) { + case '+': + ce->ce_mode |= htonl(0111); break; + case '-': + ce->ce_mode &= htonl(~0111); break; + default: + return -1; + } + active_cache_changed = 1; + return 0; +} + +static struct cache_file cache_file; static void update_one(const char *path, const char *prefix, int prefix_length) { @@ -328,6 +362,8 @@ int main(int argc, const char **argv) const char *prefix = setup_git_directory(); int prefix_length = prefix ? strlen(prefix) : 0; + git_config(git_default_config); + newfd = hold_index_file_for_update(&cache_file, get_index_file()); if (newfd < 0) die("unable to create new cachefile"); @@ -376,6 +412,14 @@ int main(int argc, const char **argv) i += 3; continue; } + if (!strcmp(path, "--chmod=-x") || + !strcmp(path, "--chmod=+x")) { + if (argc <= i+1) + die("git-update-index: %s <path>", path); + if (chmod_path(path[8], argv[++i])) + die("git-update-index: %s cannot chmod %s", path, argv[i]); + continue; + } if (!strcmp(path, "--info-only")) { info_only = 1; continue; |