Commit 2dfd5eae33e079bc92a15ccfd561901ea7b69e45

Edward Thomson 2015-07-24T15:05:16

Merge pull request #3307 from libgit2/cmn/submodule-backslash Normalize submodule urls before looking at them

diff --git a/src/path.c b/src/path.c
index 3e63f06..8317aaa 100644
--- a/src/path.c
+++ b/src/path.c
@@ -1676,3 +1676,19 @@ bool git_path_isvalid(
 
 	return verify_component(repo, start, (c - start), flags);
 }
+
+int git_path_normalize_slashes(git_buf *out, const char *path)
+{
+	int error;
+	char *p;
+
+	if ((error = git_buf_puts(out, path)) < 0)
+		return error;
+
+	for (p = out->ptr; *p; p++) {
+		if (*p == '\\')
+			*p = '/';
+	}
+
+	return 0;
+}
diff --git a/src/path.h b/src/path.h
index 5927a53..adb7686 100644
--- a/src/path.h
+++ b/src/path.h
@@ -591,4 +591,9 @@ extern bool git_path_isvalid(
 	const char *path,
 	unsigned int flags);
 
+/**
+ * Convert any backslashes into slashes
+ */
+int git_path_normalize_slashes(git_buf *out, const char *path);
+
 #endif
diff --git a/src/submodule.c b/src/submodule.c
index 892c983..991ebc8 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -781,11 +781,21 @@ const char *git_submodule_url(git_submodule *submodule)
 int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url)
 {
 	int error = 0;
+	git_buf normalized = GIT_BUF_INIT;
 
 	assert(out && repo && url);
 
 	git_buf_sanitize(out);
 
+	/* We do this in all platforms in case someone on Windows created the .gitmodules */
+	if (strchr(url, '\\')) {
+		if ((error = git_path_normalize_slashes(&normalized, url)) < 0)
+			return error;
+
+		url = normalized.ptr;
+	}
+
+
 	if (git_path_is_relative(url)) {
 		if (!(error = get_url_base(out, repo)))
 			error = git_path_apply_relative(out, url);
@@ -796,6 +806,7 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur
 		error = -1;
 	}
 
+	git_buf_free(&normalized);
 	return error;
 }
 
diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c
index 9b2b3aa..ecea694 100644
--- a/tests/submodule/lookup.c
+++ b/tests/submodule/lookup.c
@@ -151,6 +151,29 @@ void test_submodule_lookup__lookup_even_with_missing_index(void)
 	test_submodule_lookup__simple_lookup(); /* baseline should still pass */
 }
 
+void test_submodule_lookup__backslashes(void)
+{
+	git_config *cfg;
+	git_submodule *sm;
+	git_repository *subrepo;
+	git_buf buf = GIT_BUF_INIT;
+	const char *backslashed_path = "..\\submod2_target";
+
+	cl_git_pass(git_config_open_ondisk(&cfg, "submod2/.gitmodules"));
+	cl_git_pass(git_config_set_string(cfg, "submodule.sm_unchanged.url", backslashed_path));
+	git_config_free(cfg);
+
+	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
+	cl_assert_equal_s(backslashed_path, git_submodule_url(sm));
+	cl_git_pass(git_submodule_open(&subrepo, sm));
+
+	cl_git_pass(git_submodule_resolve_url(&buf, g_repo, backslashed_path));
+
+	git_buf_free(&buf);
+	git_submodule_free(sm);
+	git_repository_free(subrepo);
+}
+
 static void baseline_tests(void)
 {
 	/* small baseline that should work even if we change the index or make