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
4 changes: 2 additions & 2 deletions 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(state->repo) || !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 Expand Up @@ -4511,7 +4511,7 @@ static int try_create_file(struct apply_state *state, const char *path,
return !!mkdir(path, 0777);
}

if (has_symlinks && S_ISLNK(mode))
if (repo_has_symlinks(state->repo) && S_ISLNK(mode))
/* Although buf:size is counted string, it also is NUL
* terminated.
*/
Expand Down
2 changes: 1 addition & 1 deletion combine-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
/* if symlinks don't work, assume symlink if all parents
* are symlinks
*/
is_file = has_symlinks;
is_file = repo_has_symlinks(rev->repo);
for (i = 0; !is_file && i < num_parent; i++)
is_file = !S_ISLNK(elem->parent[i].mode);
if (!is_file)
Expand Down
17 changes: 13 additions & 4 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "config.h"
#include "dir.h"
#include "environment.h"
#include "repository.h"
#include "gettext.h"
#include "run-command.h"
#include "strbuf.h"
Expand Down Expand Up @@ -1043,7 +1044,7 @@ int mingw_chdir(const char *dirname)
if (xutftowcs_path(wdirname, dirname) < 0)
return -1;

if (has_symlinks) {
if (repo_has_symlinks(the_repository)) {
HANDLE hnd = CreateFileW(wdirname, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
Expand Down Expand Up @@ -2903,7 +2904,7 @@ int symlink(const char *target, const char *link)
int len;

/* fail if symlinks are disabled or API is not supported (WinXP) */
if (!has_symlinks) {
if (!repo_has_symlinks(the_repository)) {
errno = ENOSYS;
return -1;
}
Expand Down Expand Up @@ -3173,15 +3174,23 @@ static void setup_windows_environment(void)
if (!tmp && (tmp = getenv("USERPROFILE")))
setenv("HOME", tmp, 1);
}
}

int mingw_platform_has_symlinks(void)
{
static int has_symlinks = -1;
/*
* Change 'core.symlinks' default to false, unless native symlinks are
* enabled in MSys2 (via 'MSYS=winsymlinks:nativestrict'). Thus we can
* run the test suite (which doesn't obey config files) with or without
* symlink support.
*/
if (!(tmp = getenv("MSYS")) || !strstr(tmp, "winsymlinks:nativestrict"))
has_symlinks = 0;
if (has_symlinks < 0) {
const char *tmp = getenv("MSYS");
has_symlinks = (tmp && strstr(tmp, "winsymlinks:nativestrict")) ? 1 : 0;
}

return has_symlinks;
}

static void get_current_user_sid(PSID *sid, HANDLE *linked_token)
Expand Down
3 changes: 3 additions & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ void open_in_gdb(void);
*/
int err_win_to_posix(DWORD winerr);

int mingw_platform_has_symlinks(void);
#define platform_has_symlinks() mingw_platform_has_symlinks()

#ifndef NO_UNIX_SOCKETS
int mingw_have_unix_sockets(void);
#undef have_unix_sockets
Expand Down
2 changes: 1 addition & 1 deletion entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
* We can't make a real symlink; write out a regular file entry
* with the symlink destination as its contents.
*/
if (!has_symlinks || to_tempfile)
if (!repo_has_symlinks(state->istate ? state->istate->repo : NULL) || to_tempfile)
goto write_file_entry;

ret = symlink(new_blob, path);
Expand Down
27 changes: 23 additions & 4 deletions environment.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,8 @@
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;
int minimum_abbrev = 4, default_abbrev = -1;
int ignore_case;
int assume_unchanged;
Expand Down Expand Up @@ -142,6 +140,24 @@ 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 repo_has_symlinks(struct repository *repo)
{
if (!repo)
repo = the_repository;

if (!repo->gitdir)
return platform_has_symlinks();

return repo_config_values(repo)->has_symlinks;
}

int have_git_dir(void)
{
return startup_info->have_repository
Expand Down Expand Up @@ -305,7 +321,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 All @@ -330,7 +346,8 @@ int git_default_core_config(const char *var, const char *value,
}

if (!strcmp(var, "core.symlinks")) {
has_symlinks = git_config_bool(var, value);
struct repo_config_values *cfg = repo_config_values(the_repository);
cfg->has_symlinks = git_config_bool(var, value);
return 0;
}

Expand Down Expand Up @@ -720,5 +737,7 @@ 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->has_symlinks = platform_has_symlinks();
cfg->branch_track = BRANCH_TRACK_REMOTE;
}
8 changes: 6 additions & 2 deletions environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ struct repo_config_values {
/* section "core" config values */
char *attributes_file;
int apply_sparse_checkout;
int trust_executable_bit;
int has_symlinks;

/* section "branch" config values */
enum branch_track branch_track;
Expand Down Expand Up @@ -123,6 +125,10 @@ 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);

int repo_trust_executable_bit(struct repository *repo);

int repo_has_symlinks(struct repository *repo);

void repo_config_values_init(struct repo_config_values *cfg);

/*
Expand Down Expand Up @@ -160,10 +166,8 @@ 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;
extern int minimum_abbrev, default_abbrev;
extern int ignore_case;
extern int assume_unchanged;
Expand Down
4 changes: 4 additions & 0 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ static inline int git_is_dir_sep(int c)
#define is_dir_sep git_is_dir_sep
#endif

#ifndef platform_has_symlinks
#define platform_has_symlinks() 1
#endif

#ifndef offset_1st_component
static inline int git_offset_1st_component(const char *path)
{
Expand Down
33 changes: 26 additions & 7 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 (!repo_has_symlinks(the_repository) && 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);
return repo_has_symlinks(the_repository) ? 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,13 +338,13 @@ 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;
case S_IFLNK:
if (!S_ISLNK(st->st_mode) &&
(has_symlinks || !S_ISREG(st->st_mode)))
(repo_has_symlinks(the_repository) || !S_ISREG(st->st_mode)))
changed |= TYPE_CHANGED;
break;
case S_IFGITLINK:
Expand Down Expand Up @@ -741,7 +759,8 @@ 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(istate->repo) &&
repo_has_symlinks(istate->repo)) {
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