Merge branch 'js/prep-symlink-windows'

Further preparation to upstream symbolic link support on Windows.

* js/prep-symlink-windows:
  trim_last_path_component(): avoid hard-coding the directory separator
  strbuf_readlink(): support link targets that exceed 2*PATH_MAX
  strbuf_readlink(): avoid calling `readlink()` twice in corner-cases
  init: do parse _all_ core.* settings early
  mingw: do resolve symlinks in `getcwd()`
This commit is contained in:
Junio C Hamano
2026-01-21 08:29:00 -08:00
6 changed files with 18 additions and 20 deletions

View File

@@ -1239,18 +1239,16 @@ char *mingw_getcwd(char *pointer, int len)
{ {
wchar_t cwd[MAX_PATH], wpointer[MAX_PATH]; wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd); DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd);
HANDLE hnd;
if (!ret || ret >= ARRAY_SIZE(cwd)) { if (!ret || ret >= ARRAY_SIZE(cwd)) {
errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError()); errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
return NULL; return NULL;
} }
ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer)); hnd = CreateFileW(cwd, 0,
if (!ret && GetLastError() == ERROR_ACCESS_DENIED) { FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
HANDLE hnd = CreateFileW(cwd, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, if (hnd != INVALID_HANDLE_VALUE) {
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hnd == INVALID_HANDLE_VALUE)
return NULL;
ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0); ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0);
CloseHandle(hnd); CloseHandle(hnd);
if (!ret || ret >= ARRAY_SIZE(wpointer)) if (!ret || ret >= ARRAY_SIZE(wpointer))
@@ -1259,13 +1257,11 @@ char *mingw_getcwd(char *pointer, int len)
return NULL; return NULL;
return pointer; return pointer;
} }
if (!ret || ret >= ARRAY_SIZE(wpointer)) if (GetFileAttributesW(cwd) == INVALID_FILE_ATTRIBUTES) {
return NULL;
if (GetFileAttributesW(wpointer) == INVALID_FILE_ATTRIBUTES) {
errno = ENOENT; errno = ENOENT;
return NULL; return NULL;
} }
if (xwcstoutf(pointer, wpointer, len) < 0) if (xwcstoutf(pointer, cwd, len) < 0)
return NULL; return NULL;
convert_slashes(pointer); convert_slashes(pointer);
return pointer; return pointer;

View File

@@ -324,8 +324,8 @@ next_name:
return (current & ~negative) | positive; return (current & ~negative) | positive;
} }
static int git_default_core_config(const char *var, const char *value, int git_default_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb) const struct config_context *ctx, void *cb)
{ {
/* This needs a better name */ /* This needs a better name */
if (!strcmp(var, "core.filemode")) { if (!strcmp(var, "core.filemode")) {

View File

@@ -106,6 +106,8 @@ const char *strip_namespace(const char *namespaced_ref);
int git_default_config(const char *, const char *, int git_default_config(const char *, const char *,
const struct config_context *, void *); const struct config_context *, void *);
int git_default_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);
/* /*
* TODO: All the below state either explicitly or implicitly relies on * TODO: All the below state either explicitly or implicitly relies on

View File

@@ -19,14 +19,14 @@ static void trim_last_path_component(struct strbuf *path)
int i = path->len; int i = path->len;
/* back up past trailing slashes, if any */ /* back up past trailing slashes, if any */
while (i && path->buf[i - 1] == '/') while (i && is_dir_sep(path->buf[i - 1]))
i--; i--;
/* /*
* then go backwards until a slash, or the beginning of the * then go backwards until a slash, or the beginning of the
* string * string
*/ */
while (i && path->buf[i - 1] != '/') while (i && !is_dir_sep(path->buf[i - 1]))
i--; i--;
strbuf_setlen(path, i); strbuf_setlen(path, i);

View File

@@ -2693,7 +2693,7 @@ int init_db(const char *git_dir, const char *real_git_dir,
* have set up the repository format such that we can evaluate * have set up the repository format such that we can evaluate
* includeIf conditions correctly in the case of re-initialization. * includeIf conditions correctly in the case of re-initialization.
*/ */
repo_config(the_repository, platform_core_config, NULL); repo_config(the_repository, git_default_core_config, NULL);
safe_create_dir(the_repository, git_dir, 0); safe_create_dir(the_repository, git_dir, 0);

View File

@@ -566,7 +566,7 @@ ssize_t strbuf_write(struct strbuf *sb, FILE *f)
return sb->len ? fwrite(sb->buf, 1, sb->len, f) : 0; return sb->len ? fwrite(sb->buf, 1, sb->len, f) : 0;
} }
#define STRBUF_MAXLINK (2*PATH_MAX) #define STRBUF_MAXLINK (32767)
int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint) int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
{ {
@@ -578,12 +578,12 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
while (hint < STRBUF_MAXLINK) { while (hint < STRBUF_MAXLINK) {
ssize_t len; ssize_t len;
strbuf_grow(sb, hint); strbuf_grow(sb, hint + 1);
len = readlink(path, sb->buf, hint); len = readlink(path, sb->buf, hint + 1);
if (len < 0) { if (len < 0) {
if (errno != ERANGE) if (errno != ERANGE)
break; break;
} else if (len < hint) { } else if (len <= hint) {
strbuf_setlen(sb, len); strbuf_setlen(sb, len);
return 0; return 0;
} }