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;
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);
}
}
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;
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;
}
}
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;
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];
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:
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;
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));
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))
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)
{
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");
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;