Skip to content

Commit

Permalink
Use core.filemode.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Junio C Hamano committed Oct 12, 2005
1 parent 5cbb401 commit 3e09cdf
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 9 deletions.
10 changes: 8 additions & 2 deletions diff-files.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
Expand Down
11 changes: 9 additions & 2 deletions diff-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
}
Expand All @@ -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;

Expand Down Expand Up @@ -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];
Expand Down
12 changes: 8 additions & 4 deletions read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand All @@ -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));
Expand Down
46 changes: 45 additions & 1 deletion update-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 3e09cdf

Please sign in to comment.