Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -3893,7 +3893,7 @@ static int check_preimage(struct apply_state *state,
if (*ce && !(*ce)->ce_mode)
BUG("ce_mode == 0 for path '%s'", old_name);

if (trust_executable_bit || !S_ISREG(st->st_mode))
if (repo_trust_executable_bit(the_repository) || !S_ISREG(st->st_mode))
st_mode = ce_mode_from_stat(*ce, st->st_mode);
else if (*ce)
st_mode = (*ce)->ce_mode;
Expand Down
11 changes: 9 additions & 2 deletions environment.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
static int pack_compression_seen;
static int zlib_compression_seen;

int trust_executable_bit = 1;
int trust_ctime = 1;
int check_stat = 1;
int has_symlinks = 1;
Expand Down Expand Up @@ -142,6 +141,13 @@ int is_bare_repository(void)
return is_bare_repository_cfg && !repo_get_work_tree(the_repository);
}

int repo_trust_executable_bit(struct repository *repo)
{
return repo->gitdir?
repo_config_values(repo)->trust_executable_bit :
1;
}

int have_git_dir(void)
{
return startup_info->have_repository
Expand Down Expand Up @@ -305,7 +311,7 @@ int git_default_core_config(const char *var, const char *value,

/* This needs a better name */
if (!strcmp(var, "core.filemode")) {
trust_executable_bit = git_config_bool(var, value);
cfg->trust_executable_bit = git_config_bool(var, value);
return 0;
}
if (!strcmp(var, "core.trustctime")) {
Expand Down Expand Up @@ -720,5 +726,6 @@ void repo_config_values_init(struct repo_config_values *cfg)
{
cfg->attributes_file = NULL;
cfg->apply_sparse_checkout = 0;
cfg->trust_executable_bit = 1;
cfg->branch_track = BRANCH_TRACK_REMOTE;
}
9 changes: 8 additions & 1 deletion environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ struct repo_config_values {
/* section "core" config values */
char *attributes_file;
int apply_sparse_checkout;
int trust_executable_bit;

/* section "branch" config values */
enum branch_track branch_track;
Expand Down Expand Up @@ -123,6 +124,13 @@ int git_default_config(const char *, const char *,
int git_default_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);

/*
* Getters for the `repo_trust_executable_bit` fields of `struct repo_config_values`.
* They check `repo->gitdir` to prevent calling repo_config_values()
* before the configuration is loaded or in bare environments.
*/
int repo_trust_executable_bit(struct repository *repo);

void repo_config_values_init(struct repo_config_values *cfg);

/*
Expand Down Expand Up @@ -160,7 +168,6 @@ int is_bare_repository(void);
extern char *git_work_tree_cfg;

/* Environment bits from configuration mechanism */
extern int trust_executable_bit;
extern int trust_ctime;
extern int check_stat;
extern int has_symlinks;
Expand Down
28 changes: 23 additions & 5 deletions read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,33 @@ void fill_stat_cache_info(struct index_state *istate, struct cache_entry *ce, st
}
}

static unsigned int st_mode_from_ce(const struct cache_entry *ce)
/*
* Determine the appropriate index mode for a file based on its stat()
* information and the existing cache entry (if any).
*
* This function handles degradation for filesystems that lack
* symlink support or reliable executable bits.
*/
unsigned int ce_mode_from_stat(const struct cache_entry *ce, unsigned int mode)
{
extern int trust_executable_bit, has_symlinks;
if (!has_symlinks && S_ISREG(mode) &&
ce && S_ISLNK(ce->ce_mode))
return ce->ce_mode;
if (!repo_trust_executable_bit(the_repository) && S_ISREG(mode)) {
if (ce && S_ISREG(ce->ce_mode))
return ce->ce_mode;
return create_ce_mode(0666);
}
return create_ce_mode(mode);
}

static unsigned int st_mode_from_ce(const struct cache_entry *ce)
{
switch (ce->ce_mode & S_IFMT) {
case S_IFLNK:
return has_symlinks ? S_IFLNK : (S_IFREG | 0644);
case S_IFREG:
return (ce->ce_mode & (trust_executable_bit ? 0755 : 0644)) | S_IFREG;
return (ce->ce_mode & (repo_trust_executable_bit(the_repository) ? 0755 : 0644)) | S_IFREG;
case S_IFGITLINK:
return S_IFDIR | 0755;
case S_IFDIR:
Expand Down Expand Up @@ -320,7 +338,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
/* We consider only the owner x bit to be relevant for
* "mode changes"
*/
if (trust_executable_bit &&
if (repo_trust_executable_bit(the_repository) &&
(0100 & (ce->ce_mode ^ st->st_mode)))
changed |= MODE_CHANGED;
break;
Expand Down Expand Up @@ -741,7 +759,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
ce->ce_flags |= CE_INTENT_TO_ADD;


if (trust_executable_bit && has_symlinks) {
if (repo_trust_executable_bit(the_repository) && has_symlinks) {
ce->ce_mode = create_ce_mode(st_mode);
} else {
/* If there is an existing entry, pick the mode bits and type
Expand Down
16 changes: 2 additions & 14 deletions read-cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,8 @@
#include "object.h"
#include "pathspec.h"

static inline unsigned int ce_mode_from_stat(const struct cache_entry *ce,
unsigned int mode)
{
extern int trust_executable_bit, has_symlinks;
if (!has_symlinks && S_ISREG(mode) &&
ce && S_ISLNK(ce->ce_mode))
return ce->ce_mode;
if (!trust_executable_bit && S_ISREG(mode)) {
if (ce && S_ISREG(ce->ce_mode))
return ce->ce_mode;
return create_ce_mode(0666);
}
return create_ce_mode(mode);
}
unsigned int ce_mode_from_stat(const struct cache_entry *ce,
unsigned int mode);

static inline int ce_to_dtype(const struct cache_entry *ce)
{
Expand Down
Loading