Use core.filemode.
authorJunio C Hamano <junkio@cox.net>
Wed, 12 Oct 2005 01:45:33 +0000 (18:45 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 12 Oct 2005 01:45:33 +0000 (18:45 -0700)
With "[core] filemode = false", you can tell git to ignore
differences in the working tree file only in executable bit.

* "git-update-index --refresh" does not say "needs update" if index
entry and working tree file differs only in executable bit.

* "git-update-index" on an existing path takes executable bit
from the existing index entry, if the path and index entry are
both regular files.

* "git-diff-files" and "git-diff-index" without --cached flag
pretend the path on the filesystem has the same executable
bit as the existing index entry, if the path and index entry
are both regular files.

If you are on a filesystem with unreliable mode bits, you may need to
force the executable bit after registering the path in the index.

* "git-update-index --chmod=+x foo" flips the executable bit of the
index file entry for path "foo" on. Use "--chmod=-x" to flip it
off.

Note that --chmod only works in index file and does not look at nor
update the working tree.

So if you are on a filesystem and do not have working executable bit,
you would do:

1. set the appropriate .git/config option;

2. "git-update-index --add new-file.c"

3. "git-ls-files --stage new-file.c" to see if it has the desired
mode bits. If not, e.g. to drop executable bit picked up from the
filesystem, say "git-update-index --chmod=-x new-file.c".

Signed-off-by: Junio C Hamano <junkio@cox.net>
diff-files.c
diff-index.c
read-cache.c
update-index.c
index 96d2c7f19f03aed937d325e12a2d397634a92e1e..8a8f9b6dc77683bd7926f8599a2aa6eb03023b57 100644 (file)
@@ -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);
        }
index 62b36cc8ee2bad8e4c37c4c7e2a99d6d4abc2f88..c9a9f4c74d96ea22b2a6c4c7593bccc3d5396457 100644 (file)
@@ -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];
index c7f3b2686296b16f8fb6de0c6e1bbee5e1a5d389..4ed369acf8a62212c759c16dae8177597d02d536 100644 (file)
@@ -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));
index 01b4088ad661691c8a8b778071b12527bfc45c3c..1eeb45dbb18a7a9fb081a6ce1b4d9558f2ff7b21 100644 (file)
@@ -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;