Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
win32: emulate Git for Windows in symlink support
Emulate the Git for Windows `core.symlinks` support.  Since symbolic
links are generally enabled for Administrator (and _may_ be enabled due
to enabling Developer mode) but symbolic links are still sufficiently
uncommon on Windows that Git users are expected to explicitly opt-in to
symbolic links by enabling `core.symlinks=true` in a global (or xdg or
system) configuration.

When `core.symlinks=true` is set globally _and_ symbolic links support
is detected then new repositories created will not have a
`core.symlinks` set.  If `core.symlinks` is _not_ set then no detection
will be performed, and `core.symlinks=false` will be set in the
repository configuration.
  • Loading branch information
ethomson committed Oct 20, 2018
commit b433a22a979ae78c28c8b16f8c3487e2787cb73e
52 changes: 42 additions & 10 deletions src/repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -1411,24 +1411,56 @@ static bool is_filesystem_case_insensitive(const char *gitdir_path)

static bool are_symlinks_supported(const char *wd_path)
{
git_config *config = NULL;
git_buf path = GIT_BUF_INIT;
int fd;
struct stat st;
int symlinks_supported = -1;
bool symlinks = false;

/*
* To emulate Git for Windows, symlinks on Windows must be explicitly
* opted-in. We examine the system configuration for a core.symlinks
* set to true. If found, we then examine the filesystem to see if
* symlinks are _actually_ supported by the current user. If that is
* _not_ set, then we do not test or enable symlink support.
*/
#ifdef GIT_WIN32
git_buf global_buf = GIT_BUF_INIT;
git_buf xdg_buf = GIT_BUF_INIT;
git_buf system_buf = GIT_BUF_INIT;
git_buf programdata_buf = GIT_BUF_INIT;

git_config_find_global(&global_buf);
git_config_find_xdg(&xdg_buf);
git_config_find_system(&system_buf);
git_config_find_programdata(&programdata_buf);

if (load_config(&config, NULL,
path_unless_empty(&global_buf),
path_unless_empty(&xdg_buf),
path_unless_empty(&system_buf),
path_unless_empty(&programdata_buf)) < 0)
goto done;

if (git_config_get_bool(&symlinks, config, "core.symlinks") < 0 || !symlinks)
goto done;
#endif

if ((fd = git_futils_mktmp(&path, wd_path, 0666)) < 0 ||
p_close(fd) < 0 ||
p_unlink(path.ptr) < 0 ||
p_symlink("testing", path.ptr) < 0 ||
p_lstat(path.ptr, &st) < 0)
symlinks_supported = false;
else
symlinks_supported = (S_ISLNK(st.st_mode) != 0);
p_close(fd) < 0 ||
p_unlink(path.ptr) < 0 ||
p_symlink("testing", path.ptr) < 0 ||
p_lstat(path.ptr, &st) < 0)
goto done;

symlinks = (S_ISLNK(st.st_mode) != 0);

(void)p_unlink(path.ptr);
git_buf_dispose(&path);

return symlinks_supported;
done:
git_buf_dispose(&path);
git_config_free(config);
return symlinks;
}

static int create_empty_file(const char *path, mode_t mode)
Expand Down