diff -urN git-2.8.2-orig/builtin/clone.c git-2.8.2/builtin/clone.c --- git-2.8.2-orig/builtin/clone.c 2016-05-17 11:31:07.469884100 +0100 +++ git-2.8.2/builtin/clone.c 2016-05-17 11:31:16.899423500 +0100 @@ -887,7 +887,7 @@ die(_("depth %s is not a positive number"), option_depth); if (argc == 2) - dir = xstrdup(argv[1]); + dir = maybe_xstrdup_cyg_conv_path(argv[1], 1); else dir = guess_dir_name(repo_name, is_bundle, option_bare); strip_trailing_slashes(dir); diff -urN git-2.8.2-orig/cache.h git-2.8.2/cache.h --- git-2.8.2-orig/cache.h 2016-05-17 11:31:07.561889400 +0100 +++ git-2.8.2/cache.h 2016-05-17 11:31:16.884422600 +0100 @@ -989,6 +989,7 @@ int normalize_path_copy(char *dst, const char *src); int longest_ancestor_length(const char *path, struct string_list *prefixes); char *strip_path_suffix(const char *path, const char *suffix); +char *maybe_xstrdup_cyg_conv_path(const char *path, int always_dupe); int daemon_avoid_alias(const char *path); extern int is_ntfs_dotgit(const char *name); diff -urN git-2.8.2-orig/path.c git-2.8.2/path.c --- git-2.8.2-orig/path.c 2016-05-17 11:31:06.252814500 +0100 +++ git-2.8.2/path.c 2016-05-17 11:38:34.828471600 +0100 @@ -6,6 +6,10 @@ #include "string-list.h" #include "dir.h" +#if defined(__CYGWIN__) +#include +#endif + static int get_st_mode_bits(const char *path, int *mode) { struct stat st; @@ -1101,6 +1105,39 @@ return xstrndup(path, chomp_trailing_dir_sep(path, path_len)); } +/* We're deliberately not changing the normal has_dos_drive_prefix + * here, since doing that would likely have unintended side-effects + * This version is only for maybe_xstrdup_cyg_conv_path which is + * called in very specific cases. + */ +#if defined(__CYGWIN__) +#define cyg_conv_has_dos_drive_prefix(path) \ + (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0) +#endif + +/* + * Avoids duplicating `path` if not needed unless `always_dupe` is non-zero. + */ +char *maybe_xstrdup_cyg_conv_path(const char *path, int always_dupe) +{ +#if defined(__CYGWIN__) + int dos_prefix = cyg_conv_has_dos_drive_prefix(path) ? 1 : 0; + int backslash = strchr(path, '\\') ? 1 : 0; + if (dos_prefix || backslash) + { + cygwin_conv_path_t form = dos_prefix ? CCP_ABSOLUTE : CCP_RELATIVE; + form |= CCP_WIN_A_TO_POSIX; + ssize_t cyg_len = cygwin_conv_path(form, path, NULL, 0); + char *cyg_path = (char *)alloca(cyg_len + 1); + if (cyg_path == NULL) + die("Couldn't alloca space for cyg_path"); + cygwin_conv_path(form, path, cyg_path, cyg_len); + return xstrndup(cyg_path, cyg_len); + } +#endif + return always_dupe ? xstrdup(path) : (char*)path; +} + int daemon_avoid_alias(const char *p) { int sl, ndot; diff -urN git-2.8.2-orig/pathspec.c git-2.8.2/pathspec.c --- git-2.8.2-orig/pathspec.c 2016-05-17 11:31:06.253814600 +0100 +++ git-2.8.2/pathspec.c 2016-05-17 11:31:16.903423700 +0100 @@ -107,6 +107,10 @@ const char *prefix, int prefixlen, const char *elt) { +#if defined(__CYGWIN__) + const char *in_elt = elt; + elt = maybe_xstrdup_cyg_conv_path(elt, 0); +#endif static int literal_global = -1; static int glob_global = -1; static int noglob_global = -1; @@ -315,6 +319,10 @@ /* sanity checks, pathspec matchers assume these are sane */ assert(item->nowildcard_len <= item->len && item->prefix <= item->len); +#if defined(__CYGWIN__) + if (in_elt != elt) + free((void*)elt); +#endif return magic; } diff -urN git-2.8.2-orig/strbuf.c git-2.8.2/strbuf.c --- git-2.8.2-orig/strbuf.c 2016-05-17 11:31:06.336819300 +0100 +++ git-2.8.2/strbuf.c 2016-05-17 11:31:16.893423100 +0100 @@ -671,6 +671,10 @@ void strbuf_add_absolute_path(struct strbuf *sb, const char *path) { +#if defined(__CYGWIN__) + const char *in_path = path; + path = maybe_xstrdup_cyg_conv_path(path, 0); +#endif if (!*path) die("The empty string is not a valid path"); if (!is_absolute_path(path)) { @@ -692,6 +696,10 @@ free(cwd); } strbuf_addstr(sb, path); +#if defined(__CYGWIN__) + if (in_path != path) + free((void*)path); +#endif } int printf_ln(const char *fmt, ...)