--- a/builtin/clone.c +++ b/builtin/clone.c @@ -939,7 +939,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) 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 = git_url_basename(repo_name, is_bundle, option_bare); strip_dir_trailing_slashes(dir); diff --git a/cache.h b/cache.h index 6226f6a8a5..e8c0158e46 100644 --- a/cache.h +++ b/cache.h @@ -1284,6 +1284,7 @@ int normalize_path_copy_len(char *dst, const char *src, int *prefix_len); 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); /* --- a/path.c +++ b/path.c @@ -14,6 +14,10 @@ #include "lockfile.h" #include "exec-cmd.h" +#if defined(__CYGWIN__) +#include +#endif + static int get_st_mode_bits(const char *path, int *mode) { struct stat st; @@ -1300,6 +1304,39 @@ char *strip_path_suffix(const char *path, const char *suffix) return offset == -1 ? NULL : xstrndup(path, offset); } +/* 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; --- a/pathspec.c +++ b/pathspec.c @@ -418,6 +418,10 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags, 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 unsigned magic = 0, element_magic = 0; const char *copyfrom = elt; char *match; @@ -514,6 +518,10 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags, item->prefix > item->len) { BUG("error initializing pathspec_item"); } +#if defined(__CYGWIN__) + if (in_elt != elt) + free((void*)elt); +#endif } static int pathspec_item_cmp(const void *a_, const void *b_) --- a/strbuf.c +++ b/strbuf.c @@ -894,6 +894,10 @@ void strbuf_humanise_rate(struct strbuf *buf, off_t bytes) 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)) { @@ -915,6 +919,10 @@ void strbuf_add_absolute_path(struct strbuf *sb, const char *path) free(cwd); } strbuf_addstr(sb, path); +#if defined(__CYGWIN__) + if (in_path != path) + free((void*)path); +#endif } void strbuf_add_real_path(struct strbuf *sb, const char *path)