revert(3p/git): Revert merge of git upstream at v2.26.2
This causes cgit to serve error pages, which is undesirable. This reverts commit5229c9b232
, reversing changes made tof2b211131f
.
This commit is contained in:
parent
6f8fbf4aa4
commit
93ba78d6f4
1006 changed files with 60537 additions and 148724 deletions
409
third_party/git/compat/mingw.c
vendored
409
third_party/git/compat/mingw.c
vendored
|
@ -13,19 +13,6 @@
|
|||
|
||||
static const int delay[] = { 0, 1, 10, 20, 40 };
|
||||
|
||||
void open_in_gdb(void)
|
||||
{
|
||||
static struct child_process cp = CHILD_PROCESS_INIT;
|
||||
extern char *_pgmptr;
|
||||
|
||||
argv_array_pushl(&cp.args, "mintty", "gdb", NULL);
|
||||
argv_array_pushf(&cp.args, "--pid=%d", getpid());
|
||||
cp.clean_on_exit = 1;
|
||||
if (start_command(&cp) < 0)
|
||||
die_errno("Could not start gdb");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
int err_win_to_posix(DWORD winerr)
|
||||
{
|
||||
int error = ENOSYS;
|
||||
|
@ -127,7 +114,6 @@ int err_win_to_posix(DWORD winerr)
|
|||
case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
|
||||
case ERROR_SHARING_VIOLATION: error = EACCES; break;
|
||||
case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
|
||||
case ERROR_SUCCESS: BUG("err_win_to_posix() called without an error!");
|
||||
case ERROR_SWAPERROR: error = ENOENT; break;
|
||||
case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
|
||||
case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
|
||||
|
@ -226,7 +212,6 @@ enum hide_dotfiles_type {
|
|||
HIDE_DOTFILES_DOTGITONLY
|
||||
};
|
||||
|
||||
static int core_restrict_inherited_handles = -1;
|
||||
static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
|
||||
static char *unset_environment_variables;
|
||||
|
||||
|
@ -246,15 +231,6 @@ int mingw_core_config(const char *var, const char *value, void *cb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(var, "core.restrictinheritedhandles")) {
|
||||
if (value && !strcasecmp(value, "auto"))
|
||||
core_restrict_inherited_handles = -1;
|
||||
else
|
||||
core_restrict_inherited_handles =
|
||||
git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -387,8 +363,6 @@ static inline int needs_hiding(const char *path)
|
|||
/* ignore trailing slashes */
|
||||
if (*path)
|
||||
basename = path;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (hide_dotfiles == HIDE_DOTFILES_TRUE)
|
||||
|
@ -416,12 +390,6 @@ int mingw_mkdir(const char *path, int mode)
|
|||
{
|
||||
int ret;
|
||||
wchar_t wpath[MAX_PATH];
|
||||
|
||||
if (!is_valid_win32_path(path, 0)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xutftowcs_path(wpath, path) < 0)
|
||||
return -1;
|
||||
ret = _wmkdir(wpath);
|
||||
|
@ -495,7 +463,7 @@ int mingw_open (const char *filename, int oflags, ...)
|
|||
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
|
||||
va_list args;
|
||||
unsigned mode;
|
||||
int fd, create = (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
|
||||
int fd;
|
||||
wchar_t wfilename[MAX_PATH];
|
||||
open_fn_t open_fn;
|
||||
|
||||
|
@ -503,21 +471,16 @@ int mingw_open (const char *filename, int oflags, ...)
|
|||
mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
|
||||
if (!is_valid_win32_path(filename, !create)) {
|
||||
errno = create ? EINVAL : ENOENT;
|
||||
return -1;
|
||||
}
|
||||
if (filename && !strcmp(filename, "/dev/null"))
|
||||
filename = "nul";
|
||||
|
||||
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
|
||||
open_fn = mingw_open_append;
|
||||
else
|
||||
open_fn = _wopen;
|
||||
|
||||
if (filename && !strcmp(filename, "/dev/null"))
|
||||
wcscpy(wfilename, L"nul");
|
||||
else if (xutftowcs_path(wfilename, filename) < 0)
|
||||
if (xutftowcs_path(wfilename, filename) < 0)
|
||||
return -1;
|
||||
|
||||
fd = open_fn(wfilename, oflags, mode);
|
||||
|
||||
if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
|
||||
|
@ -575,17 +538,10 @@ FILE *mingw_fopen (const char *filename, const char *otype)
|
|||
FILE *file;
|
||||
wchar_t wfilename[MAX_PATH], wotype[4];
|
||||
if (filename && !strcmp(filename, "/dev/null"))
|
||||
wcscpy(wfilename, L"nul");
|
||||
else if (!is_valid_win32_path(filename, 1)) {
|
||||
int create = otype && strchr(otype, 'w');
|
||||
errno = create ? EINVAL : ENOENT;
|
||||
filename = "nul";
|
||||
if (xutftowcs_path(wfilename, filename) < 0 ||
|
||||
xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
|
||||
return NULL;
|
||||
} else if (xutftowcs_path(wfilename, filename) < 0)
|
||||
return NULL;
|
||||
|
||||
if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
|
||||
return NULL;
|
||||
|
||||
if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
|
||||
error("could not unhide %s", filename);
|
||||
return NULL;
|
||||
|
@ -604,17 +560,10 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
|
|||
FILE *file;
|
||||
wchar_t wfilename[MAX_PATH], wotype[4];
|
||||
if (filename && !strcmp(filename, "/dev/null"))
|
||||
wcscpy(wfilename, L"nul");
|
||||
else if (!is_valid_win32_path(filename, 1)) {
|
||||
int create = otype && strchr(otype, 'w');
|
||||
errno = create ? EINVAL : ENOENT;
|
||||
filename = "nul";
|
||||
if (xutftowcs_path(wfilename, filename) < 0 ||
|
||||
xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
|
||||
return NULL;
|
||||
} else if (xutftowcs_path(wfilename, filename) < 0)
|
||||
return NULL;
|
||||
|
||||
if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
|
||||
return NULL;
|
||||
|
||||
if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
|
||||
error("could not unhide %s", filename);
|
||||
return NULL;
|
||||
|
@ -1035,16 +984,16 @@ int pipe(int filedes[2])
|
|||
|
||||
struct tm *gmtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
if (gmtime_s(result, timep) == 0)
|
||||
return result;
|
||||
return NULL;
|
||||
/* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
|
||||
memcpy(result, gmtime(timep), sizeof(struct tm));
|
||||
return result;
|
||||
}
|
||||
|
||||
struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
if (localtime_s(result, timep) == 0)
|
||||
return result;
|
||||
return NULL;
|
||||
/* localtime() in MSVCRT.DLL is thread-safe, but not reentrant */
|
||||
memcpy(result, localtime(timep), sizeof(struct tm));
|
||||
return result;
|
||||
}
|
||||
|
||||
char *mingw_getcwd(char *pointer, int len)
|
||||
|
@ -1103,7 +1052,7 @@ static const char *quote_arg_msvc(const char *arg)
|
|||
p++;
|
||||
len++;
|
||||
}
|
||||
if (*p == '"' || !*p)
|
||||
if (*p == '"')
|
||||
n += count*2 + 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -1125,19 +1074,16 @@ static const char *quote_arg_msvc(const char *arg)
|
|||
count++;
|
||||
*d++ = *arg++;
|
||||
}
|
||||
if (*arg == '"' || !*arg) {
|
||||
if (*arg == '"') {
|
||||
while (count-- > 0)
|
||||
*d++ = '\\';
|
||||
/* don't escape the surrounding end quote */
|
||||
if (!*arg)
|
||||
break;
|
||||
*d++ = '\\';
|
||||
}
|
||||
}
|
||||
*d++ = *arg++;
|
||||
}
|
||||
*d++ = '"';
|
||||
*d++ = '\0';
|
||||
*d++ = 0;
|
||||
return q;
|
||||
}
|
||||
|
||||
|
@ -1150,14 +1096,13 @@ static const char *quote_arg_msys2(const char *arg)
|
|||
|
||||
for (p = arg; *p; p++) {
|
||||
int ws = isspace(*p);
|
||||
if (!ws && *p != '\\' && *p != '"' && *p != '{' && *p != '\'' &&
|
||||
*p != '?' && *p != '*' && *p != '~')
|
||||
if (!ws && *p != '\\' && *p != '"' && *p != '{')
|
||||
continue;
|
||||
if (!buf.len)
|
||||
strbuf_addch(&buf, '"');
|
||||
if (p != p2)
|
||||
strbuf_add(&buf, p2, p - p2);
|
||||
if (*p == '\\' || *p == '"')
|
||||
if (!ws && *p != '{')
|
||||
strbuf_addch(&buf, '\\');
|
||||
p2 = p;
|
||||
}
|
||||
|
@ -1167,7 +1112,7 @@ static const char *quote_arg_msys2(const char *arg)
|
|||
else if (!buf.len)
|
||||
return arg;
|
||||
else
|
||||
strbuf_add(&buf, p2, p - p2);
|
||||
strbuf_add(&buf, p2, p - p2),
|
||||
|
||||
strbuf_addch(&buf, '"');
|
||||
return strbuf_detach(&buf, 0);
|
||||
|
@ -1216,21 +1161,14 @@ static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
|
|||
int isexe, int exe_only)
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
wchar_t wpath[MAX_PATH];
|
||||
snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
|
||||
|
||||
if (xutftowcs_path(wpath, path) < 0)
|
||||
return NULL;
|
||||
|
||||
if (!isexe && _waccess(wpath, F_OK) == 0)
|
||||
if (!isexe && access(path, F_OK) == 0)
|
||||
return xstrdup(path);
|
||||
wpath[wcslen(wpath)-4] = '\0';
|
||||
if ((!exe_only || isexe) && _waccess(wpath, F_OK) == 0) {
|
||||
if (!(GetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
path[strlen(path)-4] = '\0';
|
||||
path[strlen(path)-4] = '\0';
|
||||
if ((!exe_only || isexe) && access(path, F_OK) == 0)
|
||||
if (!(GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY))
|
||||
return xstrdup(path);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1245,7 +1183,7 @@ static char *path_lookup(const char *cmd, int exe_only)
|
|||
int len = strlen(cmd);
|
||||
int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
|
||||
|
||||
if (strpbrk(cmd, "/\\"))
|
||||
if (strchr(cmd, '/') || strchr(cmd, '\\'))
|
||||
return xstrdup(cmd);
|
||||
|
||||
path = mingw_getenv("PATH");
|
||||
|
@ -1291,6 +1229,11 @@ static int wenvcmp(const void *a, const void *b)
|
|||
return _wcsnicmp(p, q, p_len);
|
||||
}
|
||||
|
||||
/* We need a stable sort to convert the environment between UTF-16 <-> UTF-8 */
|
||||
#ifndef INTERNAL_QSORT
|
||||
#include "qsort.c"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Build an environment block combining the inherited environment
|
||||
* merged with the given list of settings.
|
||||
|
@ -1322,15 +1265,15 @@ static wchar_t *make_environment_block(char **deltaenv)
|
|||
}
|
||||
|
||||
ALLOC_ARRAY(result, size);
|
||||
COPY_ARRAY(result, wenv, size);
|
||||
memcpy(result, wenv, size * sizeof(*wenv));
|
||||
FreeEnvironmentStringsW(wenv);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a deltaenv, let's accumulate all keys into `array`,
|
||||
* sort them using the stable git_stable_qsort() and then copy,
|
||||
* skipping duplicate keys
|
||||
* sort them using the stable git_qsort() and then copy, skipping
|
||||
* duplicate keys
|
||||
*/
|
||||
for (p = wenv; p && *p; ) {
|
||||
ALLOC_GROW(array, nr + 1, alloc);
|
||||
|
@ -1353,7 +1296,7 @@ static wchar_t *make_environment_block(char **deltaenv)
|
|||
p += wlen + 1;
|
||||
}
|
||||
|
||||
git_stable_qsort(array, nr, sizeof(*array), wenvcmp);
|
||||
git_qsort(array, nr, sizeof(*array), wenvcmp);
|
||||
ALLOC_ARRAY(result, size + delta_size);
|
||||
|
||||
for (p = result, i = 0; i < nr; i++) {
|
||||
|
@ -1366,7 +1309,7 @@ static wchar_t *make_environment_block(char **deltaenv)
|
|||
continue;
|
||||
|
||||
size = wcslen(array[i]) + 1;
|
||||
COPY_ARRAY(p, array[i], size);
|
||||
memcpy(p, array[i], size * sizeof(*p));
|
||||
p += size;
|
||||
}
|
||||
*p = L'\0';
|
||||
|
@ -1424,10 +1367,7 @@ static inline int match_last_path_component(const char *path, size_t *len,
|
|||
|
||||
static int is_msys2_sh(const char *cmd)
|
||||
{
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(cmd, "sh")) {
|
||||
if (cmd && !strcmp(cmd, "sh")) {
|
||||
static int ret = -1;
|
||||
char *p;
|
||||
|
||||
|
@ -1447,16 +1387,6 @@ static int is_msys2_sh(const char *cmd)
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ends_with(cmd, "\\sh.exe")) {
|
||||
static char *sh;
|
||||
|
||||
if (!sh)
|
||||
sh = path_lookup("sh", 0);
|
||||
|
||||
return !fspathcmp(cmd, sh);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1464,34 +1394,15 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
|
|||
const char *dir,
|
||||
int prepend_cmd, int fhin, int fhout, int fherr)
|
||||
{
|
||||
static int restrict_handle_inheritance = -1;
|
||||
STARTUPINFOEXW si;
|
||||
STARTUPINFOW si;
|
||||
PROCESS_INFORMATION pi;
|
||||
LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
|
||||
HANDLE stdhandles[3];
|
||||
DWORD stdhandles_count = 0;
|
||||
SIZE_T size;
|
||||
struct strbuf args;
|
||||
wchar_t wcmd[MAX_PATH], wdir[MAX_PATH], *wargs, *wenvblk = NULL;
|
||||
unsigned flags = CREATE_UNICODE_ENVIRONMENT;
|
||||
BOOL ret;
|
||||
HANDLE cons;
|
||||
const char *(*quote_arg)(const char *arg) =
|
||||
is_msys2_sh(cmd ? cmd : *argv) ?
|
||||
quote_arg_msys2 : quote_arg_msvc;
|
||||
|
||||
/* Make sure to override previous errors, if any */
|
||||
errno = 0;
|
||||
|
||||
if (restrict_handle_inheritance < 0)
|
||||
restrict_handle_inheritance = core_restrict_inherited_handles;
|
||||
/*
|
||||
* The following code to restrict which handles are inherited seems
|
||||
* to work properly only on Windows 7 and later, so let's disable it
|
||||
* on Windows Vista and 2008.
|
||||
*/
|
||||
if (restrict_handle_inheritance < 0)
|
||||
restrict_handle_inheritance = GetVersion() >> 16 >= 7601;
|
||||
is_msys2_sh(*argv) ? quote_arg_msys2 : quote_arg_msvc;
|
||||
|
||||
do_unset_environment_variables();
|
||||
|
||||
|
@ -1520,23 +1431,11 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
|
|||
CloseHandle(cons);
|
||||
}
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.StartupInfo.cb = sizeof(si);
|
||||
si.StartupInfo.hStdInput = winansi_get_osfhandle(fhin);
|
||||
si.StartupInfo.hStdOutput = winansi_get_osfhandle(fhout);
|
||||
si.StartupInfo.hStdError = winansi_get_osfhandle(fherr);
|
||||
|
||||
/* The list of handles cannot contain duplicates */
|
||||
if (si.StartupInfo.hStdInput != INVALID_HANDLE_VALUE)
|
||||
stdhandles[stdhandles_count++] = si.StartupInfo.hStdInput;
|
||||
if (si.StartupInfo.hStdOutput != INVALID_HANDLE_VALUE &&
|
||||
si.StartupInfo.hStdOutput != si.StartupInfo.hStdInput)
|
||||
stdhandles[stdhandles_count++] = si.StartupInfo.hStdOutput;
|
||||
if (si.StartupInfo.hStdError != INVALID_HANDLE_VALUE &&
|
||||
si.StartupInfo.hStdError != si.StartupInfo.hStdInput &&
|
||||
si.StartupInfo.hStdError != si.StartupInfo.hStdOutput)
|
||||
stdhandles[stdhandles_count++] = si.StartupInfo.hStdError;
|
||||
if (stdhandles_count)
|
||||
si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdInput = winansi_get_osfhandle(fhin);
|
||||
si.hStdOutput = winansi_get_osfhandle(fhout);
|
||||
si.hStdError = winansi_get_osfhandle(fherr);
|
||||
|
||||
if (*argv && !strcmp(cmd, *argv))
|
||||
wcmd[0] = L'\0';
|
||||
|
@ -1569,98 +1468,16 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
|
|||
wenvblk = make_environment_block(deltaenv);
|
||||
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
if (restrict_handle_inheritance && stdhandles_count &&
|
||||
(InitializeProcThreadAttributeList(NULL, 1, 0, &size) ||
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
|
||||
(attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)
|
||||
(HeapAlloc(GetProcessHeap(), 0, size))) &&
|
||||
InitializeProcThreadAttributeList(attr_list, 1, 0, &size) &&
|
||||
UpdateProcThreadAttribute(attr_list, 0,
|
||||
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||
stdhandles,
|
||||
stdhandles_count * sizeof(HANDLE),
|
||||
NULL, NULL)) {
|
||||
si.lpAttributeList = attr_list;
|
||||
flags |= EXTENDED_STARTUPINFO_PRESENT;
|
||||
}
|
||||
|
||||
ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
|
||||
stdhandles_count ? TRUE : FALSE,
|
||||
flags, wenvblk, dir ? wdir : NULL,
|
||||
&si.StartupInfo, &pi);
|
||||
|
||||
/*
|
||||
* On Windows 2008 R2, it seems that specifying certain types of handles
|
||||
* (such as FILE_TYPE_CHAR or FILE_TYPE_PIPE) will always produce an
|
||||
* error. Rather than playing finicky and fragile games, let's just try
|
||||
* to detect this situation and simply try again without restricting any
|
||||
* handle inheritance. This is still better than failing to create
|
||||
* processes.
|
||||
*/
|
||||
if (!ret && restrict_handle_inheritance && stdhandles_count) {
|
||||
DWORD err = GetLastError();
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (err != ERROR_NO_SYSTEM_RESOURCES &&
|
||||
/*
|
||||
* On Windows 7 and earlier, handles on pipes and character
|
||||
* devices are inherited automatically, and cannot be
|
||||
* specified in the thread handle list. Rather than trying
|
||||
* to catch each and every corner case (and running the
|
||||
* chance of *still* forgetting a few), let's just fall
|
||||
* back to creating the process without trying to limit the
|
||||
* handle inheritance.
|
||||
*/
|
||||
!(err == ERROR_INVALID_PARAMETER &&
|
||||
GetVersion() >> 16 < 9200) &&
|
||||
!getenv("SUPPRESS_HANDLE_INHERITANCE_WARNING")) {
|
||||
DWORD fl = 0;
|
||||
int i;
|
||||
|
||||
setenv("SUPPRESS_HANDLE_INHERITANCE_WARNING", "1", 1);
|
||||
|
||||
for (i = 0; i < stdhandles_count; i++) {
|
||||
HANDLE h = stdhandles[i];
|
||||
strbuf_addf(&buf, "handle #%d: %p (type %lx, "
|
||||
"handle info (%d) %lx\n", i, h,
|
||||
GetFileType(h),
|
||||
GetHandleInformation(h, &fl),
|
||||
fl);
|
||||
}
|
||||
strbuf_addstr(&buf, "\nThis is a bug; please report it "
|
||||
"at\nhttps://github.com/git-for-windows/"
|
||||
"git/issues/new\n\n"
|
||||
"To suppress this warning, please set "
|
||||
"the environment variable\n\n"
|
||||
"\tSUPPRESS_HANDLE_INHERITANCE_WARNING=1"
|
||||
"\n");
|
||||
}
|
||||
restrict_handle_inheritance = 0;
|
||||
flags &= ~EXTENDED_STARTUPINFO_PRESENT;
|
||||
ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
|
||||
TRUE, flags, wenvblk, dir ? wdir : NULL,
|
||||
&si.StartupInfo, &pi);
|
||||
if (!ret)
|
||||
errno = err_win_to_posix(GetLastError());
|
||||
if (ret && buf.len) {
|
||||
warning("failed to restrict file handles (%ld)\n\n%s",
|
||||
err, buf.buf);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
} else if (!ret)
|
||||
errno = err_win_to_posix(GetLastError());
|
||||
|
||||
if (si.lpAttributeList)
|
||||
DeleteProcThreadAttributeList(si.lpAttributeList);
|
||||
if (attr_list)
|
||||
HeapFree(GetProcessHeap(), 0, attr_list);
|
||||
ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL, TRUE,
|
||||
flags, wenvblk, dir ? wdir : NULL, &si, &pi);
|
||||
|
||||
free(wenvblk);
|
||||
free(wargs);
|
||||
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
|
||||
}
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
/*
|
||||
|
@ -1745,7 +1562,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
|
|||
while (argv[argc]) argc++;
|
||||
ALLOC_ARRAY(argv2, argc + 1);
|
||||
argv2[0] = (char *)cmd; /* full path to the script file */
|
||||
COPY_ARRAY(&argv2[1], &argv[1], argc);
|
||||
memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
|
||||
exec_id = trace2_exec(prog, argv2);
|
||||
pid = mingw_spawnv(prog, argv2, 1);
|
||||
if (pid >= 0) {
|
||||
|
@ -1846,8 +1663,6 @@ char *mingw_getenv(const char *name)
|
|||
if (!w_key)
|
||||
die("Out of memory, (tried to allocate %u wchar_t's)", len_key);
|
||||
xutftowcs(w_key, name, len_key);
|
||||
/* GetEnvironmentVariableW() only sets the last error upon failure */
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
len_value = GetEnvironmentVariableW(w_key, w_value, ARRAY_SIZE(w_value));
|
||||
if (!len_value && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
|
||||
free(w_key);
|
||||
|
@ -2546,128 +2361,6 @@ static void setup_windows_environment(void)
|
|||
}
|
||||
}
|
||||
|
||||
int is_valid_win32_path(const char *path, int allow_literal_nul)
|
||||
{
|
||||
const char *p = path;
|
||||
int preceding_space_or_period = 0, i = 0, periods = 0;
|
||||
|
||||
if (!protect_ntfs)
|
||||
return 1;
|
||||
|
||||
skip_dos_drive_prefix((char **)&path);
|
||||
goto segment_start;
|
||||
|
||||
for (;;) {
|
||||
char c = *(path++);
|
||||
switch (c) {
|
||||
case '\0':
|
||||
case '/': case '\\':
|
||||
/* cannot end in ` ` or `.`, except for `.` and `..` */
|
||||
if (preceding_space_or_period &&
|
||||
(i != periods || periods > 2))
|
||||
return 0;
|
||||
if (!c)
|
||||
return 1;
|
||||
|
||||
i = periods = preceding_space_or_period = 0;
|
||||
|
||||
segment_start:
|
||||
switch (*path) {
|
||||
case 'a': case 'A': /* AUX */
|
||||
if (((c = path[++i]) != 'u' && c != 'U') ||
|
||||
((c = path[++i]) != 'x' && c != 'X')) {
|
||||
not_a_reserved_name:
|
||||
path += i;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 'c': case 'C': /* COM<N>, CON, CONIN$, CONOUT$ */
|
||||
if ((c = path[++i]) != 'o' && c != 'O')
|
||||
goto not_a_reserved_name;
|
||||
c = path[++i];
|
||||
if (c == 'm' || c == 'M') { /* COM<N> */
|
||||
if (!isdigit(path[++i]))
|
||||
goto not_a_reserved_name;
|
||||
} else if (c == 'n' || c == 'N') { /* CON */
|
||||
c = path[i + 1];
|
||||
if ((c == 'i' || c == 'I') &&
|
||||
((c = path[i + 2]) == 'n' ||
|
||||
c == 'N') &&
|
||||
path[i + 3] == '$')
|
||||
i += 3; /* CONIN$ */
|
||||
else if ((c == 'o' || c == 'O') &&
|
||||
((c = path[i + 2]) == 'u' ||
|
||||
c == 'U') &&
|
||||
((c = path[i + 3]) == 't' ||
|
||||
c == 'T') &&
|
||||
path[i + 4] == '$')
|
||||
i += 4; /* CONOUT$ */
|
||||
} else
|
||||
goto not_a_reserved_name;
|
||||
break;
|
||||
case 'l': case 'L': /* LPT<N> */
|
||||
if (((c = path[++i]) != 'p' && c != 'P') ||
|
||||
((c = path[++i]) != 't' && c != 'T') ||
|
||||
!isdigit(path[++i]))
|
||||
goto not_a_reserved_name;
|
||||
break;
|
||||
case 'n': case 'N': /* NUL */
|
||||
if (((c = path[++i]) != 'u' && c != 'U') ||
|
||||
((c = path[++i]) != 'l' && c != 'L') ||
|
||||
(allow_literal_nul &&
|
||||
!path[i + 1] && p == path))
|
||||
goto not_a_reserved_name;
|
||||
break;
|
||||
case 'p': case 'P': /* PRN */
|
||||
if (((c = path[++i]) != 'r' && c != 'R') ||
|
||||
((c = path[++i]) != 'n' && c != 'N'))
|
||||
goto not_a_reserved_name;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* So far, this looks like a reserved name. Let's see
|
||||
* whether it actually is one: trailing spaces, a file
|
||||
* extension, or an NTFS Alternate Data Stream do not
|
||||
* matter, the name is still reserved if any of those
|
||||
* follow immediately after the actual name.
|
||||
*/
|
||||
i++;
|
||||
if (path[i] == ' ') {
|
||||
preceding_space_or_period = 1;
|
||||
while (path[++i] == ' ')
|
||||
; /* skip all spaces */
|
||||
}
|
||||
|
||||
c = path[i];
|
||||
if (c && c != '.' && c != ':' && c != '/' && c != '\\')
|
||||
goto not_a_reserved_name;
|
||||
|
||||
/* contains reserved name */
|
||||
return 0;
|
||||
case '.':
|
||||
periods++;
|
||||
/* fallthru */
|
||||
case ' ':
|
||||
preceding_space_or_period = 1;
|
||||
i++;
|
||||
continue;
|
||||
case ':': /* DOS drive prefix was already skipped */
|
||||
case '<': case '>': case '"': case '|': case '?': case '*':
|
||||
/* illegal character */
|
||||
return 0;
|
||||
default:
|
||||
if (c > '\0' && c < '\x20')
|
||||
/* illegal character */
|
||||
return 0;
|
||||
}
|
||||
preceding_space_or_period = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
/*
|
||||
* Disable MSVCRT command line wildcard expansion (__getmainargs called from
|
||||
|
|
39
third_party/git/compat/mingw.h
vendored
39
third_party/git/compat/mingw.h
vendored
|
@ -11,7 +11,7 @@ typedef _sigset_t sigset_t;
|
|||
#undef _POSIX_THREAD_SAFE_FUNCTIONS
|
||||
#endif
|
||||
|
||||
int mingw_core_config(const char *var, const char *value, void *cb);
|
||||
extern int mingw_core_config(const char *var, const char *value, void *cb);
|
||||
#define platform_core_config mingw_core_config
|
||||
|
||||
/*
|
||||
|
@ -443,7 +443,7 @@ static inline void convert_slashes(char *path)
|
|||
*path = '/';
|
||||
}
|
||||
#define PATH_SEP ';'
|
||||
char *mingw_query_user_email(void);
|
||||
extern char *mingw_query_user_email(void);
|
||||
#define query_user_email mingw_query_user_email
|
||||
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
|
||||
#define PRIuMAX "I64u"
|
||||
|
@ -452,27 +452,6 @@ char *mingw_query_user_email(void);
|
|||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Verifies that the given path is a valid one on Windows.
|
||||
*
|
||||
* In particular, path segments are disallowed which
|
||||
*
|
||||
* - end in a period or a space (except the special directories `.` and `..`).
|
||||
*
|
||||
* - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
|
||||
*
|
||||
* - correspond to reserved names (such as `AUX`, `PRN`, etc)
|
||||
*
|
||||
* The `allow_literal_nul` parameter controls whether the path `NUL` should
|
||||
* be considered valid (this makes sense e.g. before opening files, as it is
|
||||
* perfectly legitimate to open `NUL` on Windows, just as it is to open
|
||||
* `/dev/null` on Unix/Linux).
|
||||
*
|
||||
* Returns 1 upon success, otherwise 0.
|
||||
*/
|
||||
int is_valid_win32_path(const char *path, int allow_literal_nul);
|
||||
#define is_valid_path(path) is_valid_win32_path(path, 0)
|
||||
|
||||
/**
|
||||
* Converts UTF-8 encoded string to UTF-16LE.
|
||||
*
|
||||
|
@ -579,7 +558,7 @@ int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
|
|||
|
||||
/*
|
||||
* A critical section used in the implementation of the spawn
|
||||
* functions (mingw_spawnv[p]e()) and waitpid(). Initialised in
|
||||
* functions (mingw_spawnv[p]e()) and waitpid(). Intialised in
|
||||
* the replacement main() macro below.
|
||||
*/
|
||||
extern CRITICAL_SECTION pinfo_cs;
|
||||
|
@ -598,17 +577,7 @@ extern CRITICAL_SECTION pinfo_cs;
|
|||
int wmain(int argc, const wchar_t **w_argv);
|
||||
int main(int argc, const char **argv);
|
||||
|
||||
/*
|
||||
* For debugging: if a problem occurs, say, in a Git process that is spawned
|
||||
* from another Git process which in turn is spawned from yet another Git
|
||||
* process, it can be quite daunting to figure out what is going on.
|
||||
*
|
||||
* Call this function to open a new MinTTY (this assumes you are in Git for
|
||||
* Windows' SDK) with a GDB that attaches to the current process right away.
|
||||
*/
|
||||
extern void open_in_gdb(void);
|
||||
|
||||
/*
|
||||
* Used by Pthread API implementation for Windows
|
||||
*/
|
||||
int err_win_to_posix(DWORD winerr);
|
||||
extern int err_win_to_posix(DWORD winerr);
|
||||
|
|
12
third_party/git/compat/nedmalloc/malloc.c.h
vendored
12
third_party/git/compat/nedmalloc/malloc.c.h
vendored
|
@ -1564,7 +1564,7 @@ static FORCEINLINE void* win32direct_mmap(size_t size) {
|
|||
return (ptr != 0)? ptr: MFAIL;
|
||||
}
|
||||
|
||||
/* This function supports releasing coalesced segments */
|
||||
/* This function supports releasing coalesed segments */
|
||||
static FORCEINLINE int win32munmap(void* ptr, size_t size) {
|
||||
MEMORY_BASIC_INFORMATION minfo;
|
||||
char* cptr = (char*)ptr;
|
||||
|
@ -1655,7 +1655,7 @@ static FORCEINLINE int win32munmap(void* ptr, size_t size) {
|
|||
#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
|
||||
#endif /* HAVE_MMAP && HAVE_MREMAP */
|
||||
|
||||
/* mstate bit set if contiguous morecore disabled or failed */
|
||||
/* mstate bit set if continguous morecore disabled or failed */
|
||||
#define USE_NONCONTIGUOUS_BIT (4U)
|
||||
|
||||
/* segment bit set in create_mspace_with_base */
|
||||
|
@ -1755,10 +1755,10 @@ static FORCEINLINE void pthread_release_lock (MLOCK_T *sl) {
|
|||
assert(sl->l != 0);
|
||||
assert(sl->threadid == CURRENT_THREAD);
|
||||
if (--sl->c == 0) {
|
||||
sl->threadid = 0;
|
||||
volatile unsigned int* lp = &sl->l;
|
||||
int prev = 0;
|
||||
int ret;
|
||||
sl->threadid = 0;
|
||||
__asm__ __volatile__ ("lock; xchgl %0, %1"
|
||||
: "=r" (ret)
|
||||
: "m" (*(lp)), "0"(prev)
|
||||
|
@ -2485,7 +2485,7 @@ typedef struct malloc_segment* msegmentptr;
|
|||
|
||||
Trim support
|
||||
Fields holding the amount of unused topmost memory that should trigger
|
||||
timing, and a counter to force periodic scanning to release unused
|
||||
timming, and a counter to force periodic scanning to release unused
|
||||
non-topmost segments.
|
||||
|
||||
Locking
|
||||
|
@ -3066,7 +3066,7 @@ static int init_mparams(void) {
|
|||
#if !ONLY_MSPACES
|
||||
/* Set up lock for main malloc area */
|
||||
gm->mflags = mparams.default_mflags;
|
||||
(void)INITIAL_LOCK(&gm->mutex);
|
||||
INITIAL_LOCK(&gm->mutex);
|
||||
#endif
|
||||
|
||||
#if (FOOTERS && !INSECURE)
|
||||
|
@ -5017,7 +5017,7 @@ static mstate init_user_mstate(char* tbase, size_t tsize) {
|
|||
mchunkptr msp = align_as_chunk(tbase);
|
||||
mstate m = (mstate)(chunk2mem(msp));
|
||||
memset(m, 0, msize);
|
||||
(void)INITIAL_LOCK(&m->mutex);
|
||||
INITIAL_LOCK(&m->mutex);
|
||||
msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
|
||||
m->seg.base = m->least_addr = tbase;
|
||||
m->seg.size = m->footprint = m->max_footprint = tsize;
|
||||
|
|
8
third_party/git/compat/obstack.h
vendored
8
third_party/git/compat/obstack.h
vendored
|
@ -79,7 +79,7 @@ change its address during its lifetime.
|
|||
When the chars burst over a chunk boundary, we allocate a larger
|
||||
chunk, and then copy the partly formed object from the end of the old
|
||||
chunk to the beginning of the new larger chunk. We then carry on
|
||||
accrediting characters to the end of the object as we normally would.
|
||||
accreting characters to the end of the object as we normally would.
|
||||
|
||||
A special macro is provided to add a single char at a time to a
|
||||
growing object. This allows the use of register variables, which
|
||||
|
@ -135,10 +135,8 @@ extern "C" {
|
|||
alignment relative to 0. */
|
||||
|
||||
#define __PTR_ALIGN(B, P, A) \
|
||||
(sizeof (PTR_INT_TYPE) < sizeof(void *) ? \
|
||||
__BPTR_ALIGN((B), (P), (A)) : \
|
||||
(void *)__BPTR_ALIGN((PTR_INT_TYPE)(void *)0, (PTR_INT_TYPE)(P), (A)) \
|
||||
)
|
||||
__BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
|
||||
P, A)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
31
third_party/git/compat/poll/poll.c
vendored
31
third_party/git/compat/poll/poll.c
vendored
|
@ -139,10 +139,22 @@ win32_compute_revents (HANDLE h, int *p_sought)
|
|||
INPUT_RECORD *irbuffer;
|
||||
DWORD avail, nbuffer;
|
||||
BOOL bRet;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
FILE_PIPE_LOCAL_INFORMATION fpli;
|
||||
static PNtQueryInformationFile NtQueryInformationFile;
|
||||
static BOOL once_only;
|
||||
|
||||
switch (GetFileType (h))
|
||||
{
|
||||
case FILE_TYPE_PIPE:
|
||||
if (!once_only)
|
||||
{
|
||||
NtQueryInformationFile = (PNtQueryInformationFile)(void (*)(void))
|
||||
GetProcAddress (GetModuleHandleW (L"ntdll.dll"),
|
||||
"NtQueryInformationFile");
|
||||
once_only = TRUE;
|
||||
}
|
||||
|
||||
happened = 0;
|
||||
if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
|
||||
{
|
||||
|
@ -154,9 +166,22 @@ win32_compute_revents (HANDLE h, int *p_sought)
|
|||
|
||||
else
|
||||
{
|
||||
/* It was the write-end of the pipe. Unfortunately there is no
|
||||
reliable way of knowing if it can be written without blocking.
|
||||
Just say that it's all good. */
|
||||
/* It was the write-end of the pipe. Check if it is writable.
|
||||
If NtQueryInformationFile fails, optimistically assume the pipe is
|
||||
writable. This could happen on Win9x, where NtQueryInformationFile
|
||||
is not available, or if we inherit a pipe that doesn't permit
|
||||
FILE_READ_ATTRIBUTES access on the write end (I think this should
|
||||
not happen since WinXP SP2; WINE seems fine too). Otherwise,
|
||||
ensure that enough space is available for atomic writes. */
|
||||
memset (&iosb, 0, sizeof (iosb));
|
||||
memset (&fpli, 0, sizeof (fpli));
|
||||
|
||||
if (!NtQueryInformationFile
|
||||
|| NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
|
||||
FilePipeLocalInformation)
|
||||
|| fpli.WriteQuotaAvailable >= PIPE_BUF
|
||||
|| (fpli.OutboundQuota < PIPE_BUF &&
|
||||
fpli.WriteQuotaAvailable == fpli.OutboundQuota))
|
||||
happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
|
||||
}
|
||||
return happened;
|
||||
|
|
62
third_party/git/compat/qsort.c
vendored
Normal file
62
third_party/git/compat/qsort.c
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "../git-compat-util.h"
|
||||
|
||||
/*
|
||||
* A merge sort implementation, simplified from the qsort implementation
|
||||
* by Mike Haertel, which is a part of the GNU C Library.
|
||||
*/
|
||||
|
||||
static void msort_with_tmp(void *b, size_t n, size_t s,
|
||||
int (*cmp)(const void *, const void *),
|
||||
char *t)
|
||||
{
|
||||
char *tmp;
|
||||
char *b1, *b2;
|
||||
size_t n1, n2;
|
||||
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
n1 = n / 2;
|
||||
n2 = n - n1;
|
||||
b1 = b;
|
||||
b2 = (char *)b + (n1 * s);
|
||||
|
||||
msort_with_tmp(b1, n1, s, cmp, t);
|
||||
msort_with_tmp(b2, n2, s, cmp, t);
|
||||
|
||||
tmp = t;
|
||||
|
||||
while (n1 > 0 && n2 > 0) {
|
||||
if (cmp(b1, b2) <= 0) {
|
||||
memcpy(tmp, b1, s);
|
||||
tmp += s;
|
||||
b1 += s;
|
||||
--n1;
|
||||
} else {
|
||||
memcpy(tmp, b2, s);
|
||||
tmp += s;
|
||||
b2 += s;
|
||||
--n2;
|
||||
}
|
||||
}
|
||||
if (n1 > 0)
|
||||
memcpy(tmp, b1, n1 * s);
|
||||
memcpy(b, t, (n - n2) * s);
|
||||
}
|
||||
|
||||
void git_qsort(void *b, size_t n, size_t s,
|
||||
int (*cmp)(const void *, const void *))
|
||||
{
|
||||
const size_t size = st_mult(n, s);
|
||||
char buf[1024];
|
||||
|
||||
if (size < sizeof(buf)) {
|
||||
/* The temporary array fits on the small on-stack buffer. */
|
||||
msort_with_tmp(b, n, s, cmp, buf);
|
||||
} else {
|
||||
/* It's somewhat large, so malloc it. */
|
||||
char *tmp = xmalloc(size);
|
||||
msort_with_tmp(b, n, s, cmp, tmp);
|
||||
free(tmp);
|
||||
}
|
||||
}
|
2
third_party/git/compat/regex/regcomp.c
vendored
2
third_party/git/compat/regex/regcomp.c
vendored
|
@ -3462,7 +3462,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
|
|||
/* This isn't a valid character. */
|
||||
return REG_ECOLLATE;
|
||||
|
||||
/* Build single byte matching table for this equivalence class. */
|
||||
/* Build single byte matcing table for this equivalence class. */
|
||||
char_buf[1] = (unsigned char) '\0';
|
||||
len = weights[idx1 & 0xffffff];
|
||||
for (ch = 0; ch < SBC_MAX; ++ch)
|
||||
|
|
7
third_party/git/compat/regex/regex.h
vendored
7
third_party/git/compat/regex/regex.h
vendored
|
@ -41,11 +41,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define regcomp git_regcomp
|
||||
#define regexec git_regexec
|
||||
#define regerror git_regerror
|
||||
#define regfree git_regfree
|
||||
|
||||
/* The following two types have to be signed and unsigned integer type
|
||||
wide enough to hold a value of a pointer. For most ANSI compilers
|
||||
ptrdiff_t and size_t should be likely OK. Still size of these two
|
||||
|
@ -327,7 +322,7 @@ typedef enum
|
|||
/* POSIX regcomp return error codes. (In the order listed in the
|
||||
standard.) */
|
||||
REG_BADPAT, /* Invalid pattern. */
|
||||
REG_ECOLLATE, /* Invalid collating element. */
|
||||
REG_ECOLLATE, /* Inalid collating element. */
|
||||
REG_ECTYPE, /* Invalid character class name. */
|
||||
REG_EESCAPE, /* Trailing backslash. */
|
||||
REG_ESUBREG, /* Invalid back reference. */
|
||||
|
|
|
@ -1616,7 +1616,7 @@ free_state (re_dfastate_t *state)
|
|||
re_free (state);
|
||||
}
|
||||
|
||||
/* Create the new state which is independent of contexts.
|
||||
/* Create the new state which is independ of contexts.
|
||||
Return the new state if succeeded, otherwise return NULL. */
|
||||
|
||||
static re_dfastate_t *
|
||||
|
|
4
third_party/git/compat/regex/regexec.c
vendored
4
third_party/git/compat/regex/regexec.c
vendored
|
@ -2420,7 +2420,7 @@ find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
|
|||
/* From the node set CUR_NODES, pick up the nodes whose types are
|
||||
OP_OPEN_SUBEXP and which have corresponding back references in the regular
|
||||
expression. And register them to use them later for evaluating the
|
||||
corresponding back references. */
|
||||
correspoding back references. */
|
||||
|
||||
static reg_errcode_t
|
||||
internal_function
|
||||
|
@ -3347,7 +3347,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
|
|||
dests_node = dests_alloc->dests_node;
|
||||
dests_ch = dests_alloc->dests_ch;
|
||||
|
||||
/* Initialize transition table. */
|
||||
/* Initialize transiton table. */
|
||||
state->word_trtable = state->trtable = NULL;
|
||||
|
||||
/* At first, group all nodes belonging to `state' into several
|
||||
|
|
249
third_party/git/compat/terminal.c
vendored
249
third_party/git/compat/terminal.c
vendored
|
@ -2,9 +2,6 @@
|
|||
#include "compat/terminal.h"
|
||||
#include "sigchain.h"
|
||||
#include "strbuf.h"
|
||||
#include "run-command.h"
|
||||
#include "string-list.h"
|
||||
#include "hashmap.h"
|
||||
|
||||
#if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE)
|
||||
|
||||
|
@ -35,7 +32,7 @@ static void restore_term(void)
|
|||
term_fd = -1;
|
||||
}
|
||||
|
||||
static int disable_bits(tcflag_t bits)
|
||||
static int disable_echo(void)
|
||||
{
|
||||
struct termios t;
|
||||
|
||||
|
@ -46,7 +43,7 @@ static int disable_bits(tcflag_t bits)
|
|||
old_term = t;
|
||||
sigchain_push_common(restore_term_on_signal);
|
||||
|
||||
t.c_lflag &= ~bits;
|
||||
t.c_lflag &= ~ECHO;
|
||||
if (!tcsetattr(term_fd, TCSAFLUSH, &t))
|
||||
return 0;
|
||||
|
||||
|
@ -56,44 +53,17 @@ error:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int disable_echo(void)
|
||||
{
|
||||
return disable_bits(ECHO);
|
||||
}
|
||||
|
||||
static int enable_non_canonical(void)
|
||||
{
|
||||
return disable_bits(ICANON | ECHO);
|
||||
}
|
||||
|
||||
#elif defined(GIT_WINDOWS_NATIVE)
|
||||
|
||||
#define INPUT_PATH "CONIN$"
|
||||
#define OUTPUT_PATH "CONOUT$"
|
||||
#define FORCE_TEXT "t"
|
||||
|
||||
static int use_stty = 1;
|
||||
static struct string_list stty_restore = STRING_LIST_INIT_DUP;
|
||||
static HANDLE hconin = INVALID_HANDLE_VALUE;
|
||||
static DWORD cmode;
|
||||
|
||||
static void restore_term(void)
|
||||
{
|
||||
if (use_stty) {
|
||||
int i;
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
|
||||
if (stty_restore.nr == 0)
|
||||
return;
|
||||
|
||||
argv_array_push(&cp.args, "stty");
|
||||
for (i = 0; i < stty_restore.nr; i++)
|
||||
argv_array_push(&cp.args, stty_restore.items[i].string);
|
||||
run_command(&cp);
|
||||
string_list_clear(&stty_restore, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hconin == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
|
@ -102,39 +72,8 @@ static void restore_term(void)
|
|||
hconin = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
static int disable_bits(DWORD bits)
|
||||
static int disable_echo(void)
|
||||
{
|
||||
if (use_stty) {
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
|
||||
argv_array_push(&cp.args, "stty");
|
||||
|
||||
if (bits & ENABLE_LINE_INPUT) {
|
||||
string_list_append(&stty_restore, "icanon");
|
||||
argv_array_push(&cp.args, "-icanon");
|
||||
}
|
||||
|
||||
if (bits & ENABLE_ECHO_INPUT) {
|
||||
string_list_append(&stty_restore, "echo");
|
||||
argv_array_push(&cp.args, "-echo");
|
||||
}
|
||||
|
||||
if (bits & ENABLE_PROCESSED_INPUT) {
|
||||
string_list_append(&stty_restore, "-ignbrk");
|
||||
string_list_append(&stty_restore, "intr");
|
||||
string_list_append(&stty_restore, "^c");
|
||||
argv_array_push(&cp.args, "ignbrk");
|
||||
argv_array_push(&cp.args, "intr");
|
||||
argv_array_push(&cp.args, "");
|
||||
}
|
||||
|
||||
if (run_command(&cp) == 0)
|
||||
return 0;
|
||||
|
||||
/* `stty` could not be executed; access the Console directly */
|
||||
use_stty = 0;
|
||||
}
|
||||
|
||||
hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
@ -143,7 +82,7 @@ static int disable_bits(DWORD bits)
|
|||
|
||||
GetConsoleMode(hconin, &cmode);
|
||||
sigchain_push_common(restore_term_on_signal);
|
||||
if (!SetConsoleMode(hconin, cmode & ~bits)) {
|
||||
if (!SetConsoleMode(hconin, cmode & (~ENABLE_ECHO_INPUT))) {
|
||||
CloseHandle(hconin);
|
||||
hconin = INVALID_HANDLE_VALUE;
|
||||
return -1;
|
||||
|
@ -152,47 +91,6 @@ static int disable_bits(DWORD bits)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int disable_echo(void)
|
||||
{
|
||||
return disable_bits(ENABLE_ECHO_INPUT);
|
||||
}
|
||||
|
||||
static int enable_non_canonical(void)
|
||||
{
|
||||
return disable_bits(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Override `getchar()`, as the default implementation does not use
|
||||
* `ReadFile()`.
|
||||
*
|
||||
* This poses a problem when we want to see whether the standard
|
||||
* input has more characters, as the default of Git for Windows is to start the
|
||||
* Bash in a MinTTY, which uses a named pipe to emulate a pty, in which case
|
||||
* our `poll()` emulation calls `PeekNamedPipe()`, which seems to require
|
||||
* `ReadFile()` to be called first to work properly (it only reports 0
|
||||
* available bytes, otherwise).
|
||||
*
|
||||
* So let's just override `getchar()` with a version backed by `ReadFile()` and
|
||||
* go our merry ways from here.
|
||||
*/
|
||||
static int mingw_getchar(void)
|
||||
{
|
||||
DWORD read = 0;
|
||||
unsigned char ch;
|
||||
|
||||
if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &read, NULL))
|
||||
return EOF;
|
||||
|
||||
if (!read) {
|
||||
error("Unexpected 0 read");
|
||||
return EOF;
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
#define getchar mingw_getchar
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef FORCE_TEXT
|
||||
|
@ -239,126 +137,6 @@ char *git_terminal_prompt(const char *prompt, int echo)
|
|||
return buf.buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* The `is_known_escape_sequence()` function returns 1 if the passed string
|
||||
* corresponds to an Escape sequence that the terminal capabilities contains.
|
||||
*
|
||||
* To avoid depending on ncurses or other platform-specific libraries, we rely
|
||||
* on the presence of the `infocmp` executable to do the job for us (failing
|
||||
* silently if the program is not available or refused to run).
|
||||
*/
|
||||
struct escape_sequence_entry {
|
||||
struct hashmap_entry entry;
|
||||
char sequence[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
static int sequence_entry_cmp(const void *hashmap_cmp_fn_data,
|
||||
const struct escape_sequence_entry *e1,
|
||||
const struct escape_sequence_entry *e2,
|
||||
const void *keydata)
|
||||
{
|
||||
return strcmp(e1->sequence, keydata ? keydata : e2->sequence);
|
||||
}
|
||||
|
||||
static int is_known_escape_sequence(const char *sequence)
|
||||
{
|
||||
static struct hashmap sequences;
|
||||
static int initialized;
|
||||
|
||||
if (!initialized) {
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
char *p, *eol;
|
||||
|
||||
hashmap_init(&sequences, (hashmap_cmp_fn)sequence_entry_cmp,
|
||||
NULL, 0);
|
||||
|
||||
argv_array_pushl(&cp.args, "infocmp", "-L", "-1", NULL);
|
||||
if (pipe_command(&cp, NULL, 0, &buf, 0, NULL, 0))
|
||||
strbuf_setlen(&buf, 0);
|
||||
|
||||
for (eol = p = buf.buf; *p; p = eol + 1) {
|
||||
p = strchr(p, '=');
|
||||
if (!p)
|
||||
break;
|
||||
p++;
|
||||
eol = strchrnul(p, '\n');
|
||||
|
||||
if (starts_with(p, "\\E")) {
|
||||
char *comma = memchr(p, ',', eol - p);
|
||||
struct escape_sequence_entry *e;
|
||||
|
||||
p[0] = '^';
|
||||
p[1] = '[';
|
||||
FLEX_ALLOC_MEM(e, sequence, p, comma - p);
|
||||
hashmap_entry_init(&e->entry,
|
||||
strhash(e->sequence));
|
||||
hashmap_add(&sequences, &e->entry);
|
||||
}
|
||||
if (!*eol)
|
||||
break;
|
||||
}
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
return !!hashmap_get_from_hash(&sequences, strhash(sequence), sequence);
|
||||
}
|
||||
|
||||
int read_key_without_echo(struct strbuf *buf)
|
||||
{
|
||||
static int warning_displayed;
|
||||
int ch;
|
||||
|
||||
if (warning_displayed || enable_non_canonical() < 0) {
|
||||
if (!warning_displayed) {
|
||||
warning("reading single keystrokes not supported on "
|
||||
"this platform; reading line instead");
|
||||
warning_displayed = 1;
|
||||
}
|
||||
|
||||
return strbuf_getline(buf, stdin);
|
||||
}
|
||||
|
||||
strbuf_reset(buf);
|
||||
ch = getchar();
|
||||
if (ch == EOF) {
|
||||
restore_term();
|
||||
return EOF;
|
||||
}
|
||||
strbuf_addch(buf, ch);
|
||||
|
||||
if (ch == '\033' /* ESC */) {
|
||||
/*
|
||||
* We are most likely looking at an Escape sequence. Let's try
|
||||
* to read more bytes, waiting at most half a second, assuming
|
||||
* that the sequence is complete if we did not receive any byte
|
||||
* within that time.
|
||||
*
|
||||
* Start by replacing the Escape byte with ^[ */
|
||||
strbuf_splice(buf, buf->len - 1, 1, "^[", 2);
|
||||
|
||||
/*
|
||||
* Query the terminal capabilities once about all the Escape
|
||||
* sequences it knows about, so that we can avoid waiting for
|
||||
* half a second when we know that the sequence is complete.
|
||||
*/
|
||||
while (!is_known_escape_sequence(buf->buf)) {
|
||||
struct pollfd pfd = { .fd = 0, .events = POLLIN };
|
||||
|
||||
if (poll(&pfd, 1, 500) < 1)
|
||||
break;
|
||||
|
||||
ch = getchar();
|
||||
if (ch == EOF)
|
||||
return 0;
|
||||
strbuf_addch(buf, ch);
|
||||
}
|
||||
}
|
||||
|
||||
restore_term();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
char *git_terminal_prompt(const char *prompt, int echo)
|
||||
|
@ -366,23 +144,4 @@ char *git_terminal_prompt(const char *prompt, int echo)
|
|||
return getpass(prompt);
|
||||
}
|
||||
|
||||
int read_key_without_echo(struct strbuf *buf)
|
||||
{
|
||||
static int warning_displayed;
|
||||
const char *res;
|
||||
|
||||
if (!warning_displayed) {
|
||||
warning("reading single keystrokes not supported on this "
|
||||
"platform; reading line instead");
|
||||
warning_displayed = 1;
|
||||
}
|
||||
|
||||
res = getpass("");
|
||||
strbuf_reset(buf);
|
||||
if (!res)
|
||||
return EOF;
|
||||
strbuf_addstr(buf, res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
3
third_party/git/compat/terminal.h
vendored
3
third_party/git/compat/terminal.h
vendored
|
@ -3,7 +3,4 @@
|
|||
|
||||
char *git_terminal_prompt(const char *prompt, int echo);
|
||||
|
||||
/* Read a single keystroke, without echoing it to the terminal */
|
||||
int read_key_without_echo(struct strbuf *buf);
|
||||
|
||||
#endif /* COMPAT_TERMINAL_H */
|
||||
|
|
|
@ -18,7 +18,7 @@ REM and MAKE, we must blend these two different worlds. This script
|
|||
REM attempts to do that.
|
||||
REM ================================================================
|
||||
REM This BAT file starts in a plain (non-developer) command prompt,
|
||||
REM searches for the "best" command prompt setup script, installs
|
||||
REM searches for the "best" commmand prompt setup script, installs
|
||||
REM it into the current CMD process, and exports the various MSVC
|
||||
REM environment variables for use by MAKE.
|
||||
REM
|
||||
|
|
52
third_party/git/compat/vcbuild/scripts/clink.pl
vendored
52
third_party/git/compat/vcbuild/scripts/clink.pl
vendored
|
@ -45,9 +45,9 @@ while (@ARGV) {
|
|||
} elsif ("$arg" eq "-liconv") {
|
||||
push(@args, "libiconv.lib");
|
||||
} elsif ("$arg" eq "-lcrypto") {
|
||||
push(@args, "libcrypto.lib");
|
||||
push(@args, "libeay32.lib");
|
||||
} elsif ("$arg" eq "-lssl") {
|
||||
push(@args, "libssl.lib");
|
||||
push(@args, "ssleay32.lib");
|
||||
} elsif ("$arg" eq "-lcurl") {
|
||||
my $lib = "";
|
||||
# Newer vcpkg definitions call this libcurl_imp.lib; Do we
|
||||
|
@ -68,54 +68,8 @@ while (@ARGV) {
|
|||
} elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
|
||||
$arg =~ s/^-L/-LIBPATH:/;
|
||||
push(@lflags, $arg);
|
||||
} elsif ("$arg" =~ /^-[Rl]/) {
|
||||
} elsif ("$arg" =~ /^-R/) {
|
||||
# eat
|
||||
} elsif ("$arg" eq "-Werror") {
|
||||
push(@cflags, "-WX");
|
||||
} elsif ("$arg" eq "-Wall") {
|
||||
# cl.exe understands -Wall, but it is really overzealous
|
||||
push(@cflags, "-W4");
|
||||
# disable the "signed/unsigned mismatch" warnings; our source code violates that
|
||||
push(@cflags, "-wd4018");
|
||||
push(@cflags, "-wd4245");
|
||||
push(@cflags, "-wd4389");
|
||||
# disable the "unreferenced formal parameter" warning; our source code violates that
|
||||
push(@cflags, "-wd4100");
|
||||
# disable the "conditional expression is constant" warning; our source code violates that
|
||||
push(@cflags, "-wd4127");
|
||||
# disable the "const object should be initialized" warning; these warnings affect only objects that are `static`
|
||||
push(@cflags, "-wd4132");
|
||||
# disable the "function/data pointer conversion in expression" warning; our source code violates that
|
||||
push(@cflags, "-wd4152");
|
||||
# disable the "non-constant aggregate initializer" warning; our source code violates that
|
||||
push(@cflags, "-wd4204");
|
||||
# disable the "cannot be initialized using address of automatic variable" warning; our source code violates that
|
||||
push(@cflags, "-wd4221");
|
||||
# disable the "possible loss of data" warnings; our source code violates that
|
||||
push(@cflags, "-wd4244");
|
||||
push(@cflags, "-wd4267");
|
||||
# disable the "array is too small to include a terminating null character" warning; we ab-use strings to initialize OIDs
|
||||
push(@cflags, "-wd4295");
|
||||
# disable the "'<<': result of 32-bit shift implicitly converted to 64 bits" warning; our source code violates that
|
||||
push(@cflags, "-wd4334");
|
||||
# disable the "declaration hides previous local declaration" warning; our source code violates that
|
||||
push(@cflags, "-wd4456");
|
||||
# disable the "declaration hides function parameter" warning; our source code violates that
|
||||
push(@cflags, "-wd4457");
|
||||
# disable the "declaration hides global declaration" warning; our source code violates that
|
||||
push(@cflags, "-wd4459");
|
||||
# disable the "potentially uninitialized local variable '<name>' used" warning; our source code violates that
|
||||
push(@cflags, "-wd4701");
|
||||
# disable the "unreachable code" warning; our source code violates that
|
||||
push(@cflags, "-wd4702");
|
||||
# disable the "potentially uninitialized local pointer variable used" warning; our source code violates that
|
||||
push(@cflags, "-wd4703");
|
||||
# disable the "assignment within conditional expression" warning; our source code violates that
|
||||
push(@cflags, "-wd4706");
|
||||
# disable the "'inet_ntoa': Use inet_ntop() or InetNtop() instead" warning; our source code violates that
|
||||
push(@cflags, "-wd4996");
|
||||
} elsif ("$arg" =~ /^-W[a-z]/) {
|
||||
# let's ignore those
|
||||
} else {
|
||||
push(@args, $arg);
|
||||
}
|
||||
|
|
24
third_party/git/compat/win32/path-utils.c
vendored
24
third_party/git/compat/win32/path-utils.c
vendored
|
@ -1,29 +1,5 @@
|
|||
#include "../../git-compat-util.h"
|
||||
|
||||
int win32_has_dos_drive_prefix(const char *path)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Does it start with an ASCII letter (i.e. highest bit not set),
|
||||
* followed by a colon?
|
||||
*/
|
||||
if (!(0x80 & (unsigned char)*path))
|
||||
return *path && path[1] == ':' ? 2 : 0;
|
||||
|
||||
/*
|
||||
* While drive letters must be letters of the English alphabet, it is
|
||||
* possible to assign virtually _any_ Unicode character via `subst` as
|
||||
* a drive letter to "virtual drives". Even `1`, or `ä`. Or fun stuff
|
||||
* like this:
|
||||
*
|
||||
* subst ֍: %USERPROFILE%\Desktop
|
||||
*/
|
||||
for (i = 1; i < 4 && (0x80 & (unsigned char)path[i]); i++)
|
||||
; /* skip first UTF-8 character */
|
||||
return path[i] == ':' ? i + 1 : 0;
|
||||
}
|
||||
|
||||
int win32_skip_dos_drive_prefix(char **path)
|
||||
{
|
||||
int ret = has_dos_drive_prefix(*path);
|
||||
|
|
10
third_party/git/compat/win32/path-utils.h
vendored
10
third_party/git/compat/win32/path-utils.h
vendored
|
@ -1,9 +1,5 @@
|
|||
#ifndef WIN32_PATH_UTILS_H
|
||||
#define WIN32_PATH_UTILS_H
|
||||
|
||||
int win32_has_dos_drive_prefix(const char *path);
|
||||
#define has_dos_drive_prefix win32_has_dos_drive_prefix
|
||||
|
||||
#define has_dos_drive_prefix(path) \
|
||||
(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
|
||||
int win32_skip_dos_drive_prefix(char **path);
|
||||
#define skip_dos_drive_prefix win32_skip_dos_drive_prefix
|
||||
static inline int win32_is_dir_sep(int c)
|
||||
|
@ -22,5 +18,3 @@ static inline char *win32_find_last_dir_sep(const char *path)
|
|||
#define find_last_dir_sep win32_find_last_dir_sep
|
||||
int win32_offset_1st_component(const char *path);
|
||||
#define offset_1st_component win32_offset_1st_component
|
||||
|
||||
#endif
|
||||
|
|
8
third_party/git/compat/win32/pthread.h
vendored
8
third_party/git/compat/win32/pthread.h
vendored
|
@ -50,8 +50,8 @@ typedef struct {
|
|||
DWORD tid;
|
||||
} pthread_t;
|
||||
|
||||
int pthread_create(pthread_t *thread, const void *unused,
|
||||
void *(*start_routine)(void*), void *arg);
|
||||
extern int pthread_create(pthread_t *thread, const void *unused,
|
||||
void *(*start_routine)(void*), void *arg);
|
||||
|
||||
/*
|
||||
* To avoid the need of copying a struct, we use small macro wrapper to pass
|
||||
|
@ -59,10 +59,10 @@ int pthread_create(pthread_t *thread, const void *unused,
|
|||
*/
|
||||
#define pthread_join(a, b) win32_pthread_join(&(a), (b))
|
||||
|
||||
int win32_pthread_join(pthread_t *thread, void **value_ptr);
|
||||
extern int win32_pthread_join(pthread_t *thread, void **value_ptr);
|
||||
|
||||
#define pthread_equal(t1, t2) ((t1).tid == (t2).tid)
|
||||
pthread_t pthread_self(void);
|
||||
extern pthread_t pthread_self(void);
|
||||
|
||||
static inline void NORETURN pthread_exit(void *ret)
|
||||
{
|
||||
|
|
14
third_party/git/compat/winansi.c
vendored
14
third_party/git/compat/winansi.c
vendored
|
@ -546,7 +546,7 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
|
|||
typedef struct _OBJECT_NAME_INFORMATION
|
||||
{
|
||||
UNICODE_STRING Name;
|
||||
WCHAR NameBuffer[FLEX_ARRAY];
|
||||
WCHAR NameBuffer[0];
|
||||
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
|
||||
|
||||
#define ObjectNameInformation 1
|
||||
|
@ -662,20 +662,10 @@ void winansi_init(void)
|
|||
*/
|
||||
HANDLE winansi_get_osfhandle(int fd)
|
||||
{
|
||||
HANDLE ret;
|
||||
|
||||
if (fd == 1 && (fd_is_interactive[1] & FD_SWAPPED))
|
||||
return hconsole1;
|
||||
if (fd == 2 && (fd_is_interactive[2] & FD_SWAPPED))
|
||||
return hconsole2;
|
||||
|
||||
ret = (HANDLE)_get_osfhandle(fd);
|
||||
|
||||
/*
|
||||
* There are obviously circumstances under which _get_osfhandle()
|
||||
* returns (HANDLE)-2. This is not documented anywhere, but that is so
|
||||
* clearly an invalid handle value that we can just work around this
|
||||
* and return the correct value for invalid handles.
|
||||
*/
|
||||
return ret == (HANDLE)-2 ? INVALID_HANDLE_VALUE : ret;
|
||||
return (HANDLE)_get_osfhandle(fd);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue