# [PATCH 0/2] Fix warnings on access of a remote with Windows paths

19 messages from 2017-05-20 to 2017-05-25. Participants: Johannes Sixt, Johannes Schindelin, stefan.naewe@atlas-elektronik.com, Junio C Hamano.
Thread: https://gitlist.dev/t/46007

## Johannes Sixt, 2017-05-20 06:28

Subject: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <cover.1495261020.git.j6t@kdbg.org>
URL: https://gitlist.dev/e/cover.1495261020.git.j6t%40kdbg.org

```
This small series fixes these warnings on Windows:

C:\Temp\gittest>git fetch C:\Temp\gittest
warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
From C:\Temp\gittest
 * branch            HEAD       -> FETCH_HEAD

The fix is in the second patch; the first patch is a
preparation that allows to write the fix in my preferred style.

Johannes Sixt (2):
  mingw.h: permit arguments with side effects for is_dir_sep
  Windows: do not treat a path with backslashes as a remote's nick name

 compat/mingw.h | 6 +++++-
 remote.c       | 5 ++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

-- 
2.13.0.55.g17b7d13330


```

## Johannes Sixt, 2017-05-20 06:28

Subject: [PATCH 1/2] mingw.h: permit arguments with side effects for is_dir_sep
Message-ID: <69bafb7c9e08ba837a9b92573bef165a62c5bf92.1495261020.git.j6t@kdbg.org>
URL: https://gitlist.dev/e/69bafb7c9e08ba837a9b92573bef165a62c5bf92.1495261020.git.j6t%40kdbg.org
In-Reply-To: <cover.1495261020.git.j6t@kdbg.org>

```
The implementation of is_dir_sep in git-compat-util.h uses an inline
function. Use one also for the implementation in compat/mingw.h to support
non-trivial argument expressions.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 compat/mingw.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/compat/mingw.h b/compat/mingw.h
index cdc112526a..5e8447019b 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -398,7 +398,11 @@ HANDLE winansi_get_osfhandle(int fd);
 	(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
 int mingw_skip_dos_drive_prefix(char **path);
 #define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
-#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
+static inline int mingw_is_dir_sep(int c)
+{
+	return c == '/' || c == '\\';
+}
+#define is_dir_sep mingw_is_dir_sep
 static inline char *mingw_find_last_dir_sep(const char *path)
 {
 	char *ret = NULL;
-- 
2.13.0.55.g17b7d13330


```

## Johannes Sixt, 2017-05-20 06:28

Subject: [PATCH 2/2] Windows: do not treat a path with backslashes as a remote's nick name
Message-ID: <6347731f26396b1256070e02376bf3623bfb7102.1495261020.git.j6t@kdbg.org>
URL: https://gitlist.dev/e/6347731f26396b1256070e02376bf3623bfb7102.1495261020.git.j6t%40kdbg.org
In-Reply-To: <cover.1495261020.git.j6t@kdbg.org>

```
Fetching from a remote using a native Windows path produces these warnings:

C:\Temp\gittest>git fetch C:\Temp\gittest
warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
From C:\Temp\gittest
 * branch            HEAD       -> FETCH_HEAD

The functions that read the branches and remotes files are protected by
a valid_remote_nick() check. Its implementation does not take Windows
paths into account, so that the caller simply concatenates the paths,
leading to the error seen above.

Use is_dir_sep() to check for both slashes and backslashes on Windows.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 remote.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/remote.c b/remote.c
index 9584af366d..9501357c06 100644
--- a/remote.c
+++ b/remote.c
@@ -649,7 +649,10 @@ static int valid_remote_nick(const char *name)
 {
 	if (!name[0] || is_dot_or_dotdot(name))
 		return 0;
-	return !strchr(name, '/'); /* no slash */
+	while (*name)
+		if (is_dir_sep(*name++))	/* no slash */
+			return 0;
+	return 1;
 }
 
 const char *remote_for_branch(struct branch *branch, int *explicit)
-- 
2.13.0.55.g17b7d13330


```

## Johannes Schindelin, 2017-05-22 11:52

Subject: Re: [PATCH 1/2] mingw.h: permit arguments with side effects for is_dir_sep
Message-ID: <alpine.DEB.2.21.1.1705221349200.3610@virtualbox>
URL: https://gitlist.dev/e/alpine.DEB.2.21.1.1705221349200.3610%40virtualbox
In-Reply-To: <69bafb7c9e08ba837a9b92573bef165a62c5bf92.1495261020.git.j6t@kdbg.org>

```
Hi Hannes,


On Sat, 20 May 2017, Johannes Sixt wrote:

> The implementation of is_dir_sep in git-compat-util.h uses an inline
> function. Use one also for the implementation in compat/mingw.h to support
> non-trivial argument expressions.
> 
> Signed-off-by: Johannes Sixt <j6t@kdbg.org>

I was a bit confused by the oneline. Maybe something like

	mingw.h: avoid side effects with is_dir_sep()'s argument

	Taking git-compat-util.h's cue (which uses an inline function
	to back is_dir_sep()), let's use an inline function to back
	also the Windows version of is_dir_sep(); This avoids problems
	when calling the function with arguments that do more than just
	provide a single character, e.g. incrementing a pointer. Example:

		is_dir_sep(*(p++))

> diff --git a/compat/mingw.h b/compat/mingw.h
> index cdc112526a..5e8447019b 100644
> --- a/compat/mingw.h
> +++ b/compat/mingw.h
> @@ -398,7 +398,11 @@ HANDLE winansi_get_osfhandle(int fd);
>  	(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
>  int mingw_skip_dos_drive_prefix(char **path);
>  #define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
> -#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
> +static inline int mingw_is_dir_sep(int c)
> +{
> +	return c == '/' || c == '\\';
> +}
> +#define is_dir_sep mingw_is_dir_sep
>  static inline char *mingw_find_last_dir_sep(const char *path)
>  {
>  	char *ret = NULL;

The patch is very good, of course.

ACK,
Dscho

```

## Johannes Schindelin, 2017-05-22 11:56

Subject: Re: [PATCH 2/2] Windows: do not treat a path with backslashes as a remote's nick name
Message-ID: <alpine.DEB.2.21.1.1705221353570.3610@virtualbox>
URL: https://gitlist.dev/e/alpine.DEB.2.21.1.1705221353570.3610%40virtualbox
In-Reply-To: <6347731f26396b1256070e02376bf3623bfb7102.1495261020.git.j6t@kdbg.org>

```
Hi Hannes,

On Sat, 20 May 2017, Johannes Sixt wrote:

> Fetching from a remote using a native Windows path produces these warnings:
> 
> C:\Temp\gittest>git fetch C:\Temp\gittest
> warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
> warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
> From C:\Temp\gittest
>  * branch            HEAD       -> FETCH_HEAD
> 
> The functions that read the branches and remotes files are protected by
> a valid_remote_nick() check. Its implementation does not take Windows
> paths into account, so that the caller simply concatenates the paths,
> leading to the error seen above.
> 
> Use is_dir_sep() to check for both slashes and backslashes on Windows.
> 
> Signed-off-by: Johannes Sixt <j6t@kdbg.org>

I like this explanation.

> diff --git a/remote.c b/remote.c
> index 9584af366d..9501357c06 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -649,7 +649,10 @@ static int valid_remote_nick(const char *name)
>  {
>  	if (!name[0] || is_dot_or_dotdot(name))
>  		return 0;
> -	return !strchr(name, '/'); /* no slash */
> +	while (*name)
> +		if (is_dir_sep(*name++))	/* no slash */

I understand that you simply kept the comment, yet I have to admit that I
find it confusing in the post image. Something like

	/* remote nicknames cannot contain slashes */

(and putting it *above* the `if` line instead of appending it separated by
a <tab>) would have made it easier on me.

> +			return 0;
> +	return 1;
>  }
>  

With my suggested change or without it, ACK.

Ciao,
Dscho

```

## Johannes Schindelin, 2017-05-22 11:59

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <alpine.DEB.2.21.1.1705221357360.3610@virtualbox>
URL: https://gitlist.dev/e/alpine.DEB.2.21.1.1705221357360.3610%40virtualbox
In-Reply-To: <cover.1495261020.git.j6t@kdbg.org>

```
Hi Hannes,


On Sat, 20 May 2017, Johannes Sixt wrote:

> This small series fixes these warnings on Windows:
> 
> C:\Temp\gittest>git fetch C:\Temp\gittest
> warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
> warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
> From C:\Temp\gittest
>  * branch            HEAD       -> FETCH_HEAD
> 
> The fix is in the second patch; the first patch is a
> preparation that allows to write the fix in my preferred style.

Thank you!

Maybe you want to accompany these patches with a simple test case that
uses e.g. ls-remote on $(pwd | tr / \\\\)?

Ciao,
Dscho

```

## stefan.naewe@atlas-elektronik.com, 2017-05-22 12:38

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <122838f4-5f6b-6921-9242-2724bb6d8c95@atlas-elektronik.com>
URL: https://gitlist.dev/e/122838f4-5f6b-6921-9242-2724bb6d8c95%40atlas-elektronik.com
In-Reply-To: <cover.1495261020.git.j6t@kdbg.org>

```
Am 20.05.2017 um 08:28 schrieb Johannes Sixt:
> This small series fixes these warnings on Windows:
> 
> C:\Temp\gittest>git fetch C:\Temp\gittest
> warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
> warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
> From C:\Temp\gittest
>  * branch            HEAD       -> FETCH_HEAD

What is the exact precondition to get such a warning ?

Just wondering, because I'm not able to reproduce that warning
(with Git4win version 2.13.0.windows.1).

Stefan
-- 
----------------------------------------------------------------
/dev/random says: Spock, you are such a putz!
python -c "print '73746566616e2e6e616577654061746c61732d656c656b74726f6e696b2e636f6d'.decode('hex')" 
GPG Key fingerprint = 2DF5 E01B 09C3 7501 BCA9  9666 829B 49C5 9221 27AF
```

## Johannes Schindelin, 2017-05-22 14:01

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <alpine.DEB.2.21.1.1705221600100.3610@virtualbox>
URL: https://gitlist.dev/e/alpine.DEB.2.21.1.1705221600100.3610%40virtualbox
In-Reply-To: <122838f4-5f6b-6921-9242-2724bb6d8c95@atlas-elektronik.com>

```
Hi Stefan,

On Mon, 22 May 2017, stefan.naewe@atlas-elektronik.com wrote:

> Am 20.05.2017 um 08:28 schrieb Johannes Sixt:
> > This small series fixes these warnings on Windows:
> > 
> > C:\Temp\gittest>git fetch C:\Temp\gittest
> > warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
> > warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
> > From C:\Temp\gittest
> >  * branch            HEAD       -> FETCH_HEAD
> 
> What is the exact precondition to get such a warning ?
> 
> Just wondering, because I'm not able to reproduce that warning
> (with Git4win version 2.13.0.windows.1).

I had tested this also, and came to the conclusion that only Hannes'
MSys-based custom version is affected that is much closer to git.git's
`master` than to Git for Windows' fork.

Still, the patches are good in my opinion.

Ciao,
Dscho

```

## Johannes Sixt, 2017-05-22 16:28

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <1542d54f-d530-b60d-3270-d9b4e94c814d@kdbg.org>
URL: https://gitlist.dev/e/1542d54f-d530-b60d-3270-d9b4e94c814d%40kdbg.org
In-Reply-To: <alpine.DEB.2.21.1.1705221600100.3610@virtualbox>

```
Am 22.05.2017 um 16:01 schrieb Johannes Schindelin:
> On Mon, 22 May 2017, stefan.naewe@atlas-elektronik.com wrote:
>> Am 20.05.2017 um 08:28 schrieb Johannes Sixt:
>>> This small series fixes these warnings on Windows:
>>>
>>> C:\Temp\gittest>git fetch C:\Temp\gittest
>>> warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
>>> warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
>>>  From C:\Temp\gittest
>>>   * branch            HEAD       -> FETCH_HEAD
>>
>> What is the exact precondition to get such a warning ?
>>
>> Just wondering, because I'm not able to reproduce that warning
>> (with Git4win version 2.13.0.windows.1).
> 
> I had tested this also, and came to the conclusion that only Hannes'
> MSys-based custom version is affected that is much closer to git.git's
> `master` than to Git for Windows' fork.

In this case, the warning occurs because I build with nd/fopen-errors.

Which explains why I observed it only recently even though I fetch from 
Windows paths regularly.

-- Hannes

```

## Johannes Sixt, 2017-05-22 16:36

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <947b2453-52b6-4940-fd20-ddf350c5df4d@kdbg.org>
URL: https://gitlist.dev/e/947b2453-52b6-4940-fd20-ddf350c5df4d%40kdbg.org
In-Reply-To: <alpine.DEB.2.21.1.1705221357360.3610@virtualbox>

```
Am 22.05.2017 um 13:59 schrieb Johannes Schindelin:
> On Sat, 20 May 2017, Johannes Sixt wrote:
>> This small series fixes these warnings on Windows:
>>
>> C:\Temp\gittest>git fetch C:\Temp\gittest
>> warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
>> warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
>>  From C:\Temp\gittest
>>   * branch            HEAD       -> FETCH_HEAD
>>
>> The fix is in the second patch; the first patch is a
>> preparation that allows to write the fix in my preferred style.
> 
> Thank you!
> 
> Maybe you want to accompany these patches with a simple test case that
> uses e.g. ls-remote on $(pwd | tr / \\\\)?

Actually, no, I don't want to. It would have to be protected by MINGW, 
and I don't want to burden us (and here I mean Windows folks) with a 
check for a cosmetic deficiency. (Shell scripts, slow forks, yadda, 
yadda...)

-- Hannes

```

## Johannes Sixt, 2017-05-22 18:58

Subject: [PATCH v2 1/2] mingw.h: permit arguments with side effects for is_dir_sep
Message-ID: <7b1f97ff-52b7-72c3-211f-e73dce562911@kdbg.org>
URL: https://gitlist.dev/e/7b1f97ff-52b7-72c3-211f-e73dce562911%40kdbg.org
In-Reply-To: <cover.1495261020.git.j6t@kdbg.org>

```
Taking git-compat-util.h's cue (which uses an inline function to back
is_dir_sep()), let's use an inline function to back also the Windows
version of is_dir_sep(). This avoids problems when calling the function
with arguments that do more than just provide a single character, e.g.
incrementing a pointer. Example:

    is_dir_sep(*p++)

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 This v2 takes your commit message body because I like it better
 than mine. I did not change the subject because your suggestion
 sounded like the exact opposite of what this patch wants to achieve
 on first reading. Patch text is unchanged.

 compat/mingw.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/compat/mingw.h b/compat/mingw.h
index 034fff9479..d2168c1e5e 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -395,7 +395,11 @@ HANDLE winansi_get_osfhandle(int fd);
 	(isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
 int mingw_skip_dos_drive_prefix(char **path);
 #define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
-#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
+static inline int mingw_is_dir_sep(int c)
+{
+	return c == '/' || c == '\\';
+}
+#define is_dir_sep mingw_is_dir_sep
 static inline char *mingw_find_last_dir_sep(const char *path)
 {
 	char *ret = NULL;
-- 
2.13.0.55.g17b7d13330


```

## Johannes Sixt, 2017-05-22 19:01

Subject: [PATCH v2 2/2] Windows: do not treat a path with backslashes as a remote's nick name
Message-ID: <b2fa1cff-9902-5bef-0392-1371bf1f4268@kdbg.org>
URL: https://gitlist.dev/e/b2fa1cff-9902-5bef-0392-1371bf1f4268%40kdbg.org
In-Reply-To: <7b1f97ff-52b7-72c3-211f-e73dce562911@kdbg.org>

```
Fetching from a remote using a native Windows path produces these warnings:

C:\Temp\gittest>git fetch C:\Temp\gittest
warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
From C:\Temp\gittest
 * branch            HEAD       -> FETCH_HEAD

The functions that read the branches and remotes files are protected by
a valid_remote_nick() check. Its implementation does not take Windows
paths into account, so that the caller simply concatenates the paths,
leading to the error seen above.

Use is_dir_sep() to check for both slashes and backslashes on Windows.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 This v2 writes your suggested comment in front of the loop (not just
 the 'if' because then I feel I would have to add braces).

 remote.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/remote.c b/remote.c
index ad6c5424ed..1949882c10 100644
--- a/remote.c
+++ b/remote.c
@@ -645,7 +645,12 @@ static int valid_remote_nick(const char *name)
 {
 	if (!name[0] || is_dot_or_dotdot(name))
 		return 0;
-	return !strchr(name, '/'); /* no slash */
+
+	/* remote nicknames cannot contain slashes */
+	while (*name)
+		if (is_dir_sep(*name++))
+			return 0;
+	return 1;
 }
 
 const char *remote_for_branch(struct branch *branch, int *explicit)
-- 
2.13.0.55.g17b7d13330

```

## Johannes Schindelin, 2017-05-23 10:46

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <alpine.DEB.2.21.1.1705231245300.3610@virtualbox>
URL: https://gitlist.dev/e/alpine.DEB.2.21.1.1705231245300.3610%40virtualbox
In-Reply-To: <1542d54f-d530-b60d-3270-d9b4e94c814d@kdbg.org>

```
Hi Hannes,

On Mon, 22 May 2017, Johannes Sixt wrote:

> Am 22.05.2017 um 16:01 schrieb Johannes Schindelin:
> > On Mon, 22 May 2017, stefan.naewe@atlas-elektronik.com wrote:
> > > Am 20.05.2017 um 08:28 schrieb Johannes Sixt:
> > > > This small series fixes these warnings on Windows:
> > > >
> > > > C:\Temp\gittest>git fetch C:\Temp\gittest
> > > > warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid
> > > > warning: argument
> > > > warning: unable to access '.git/branches/C:\Temp\gittest': Invalid
> > > > warning: argument
> > > >  From C:\Temp\gittest
> > > >   * branch            HEAD       -> FETCH_HEAD
> > >
> > > What is the exact precondition to get such a warning ?
> > >
> > > Just wondering, because I'm not able to reproduce that warning
> > > (with Git4win version 2.13.0.windows.1).
> > 
> > I had tested this also, and came to the conclusion that only Hannes'
> > MSys-based custom version is affected that is much closer to git.git's
> > `master` than to Git for Windows' fork.
> 
> In this case, the warning occurs because I build with nd/fopen-errors.

Ah. So the base commit Junio chose for your v1 is completely
inappropriate. It should be nd/fopen-errors instead.

Thanks for the clarification!
Dscho

```

## Johannes Schindelin, 2017-05-23 10:53

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <alpine.DEB.2.21.1.1705231248150.3610@virtualbox>
URL: https://gitlist.dev/e/alpine.DEB.2.21.1.1705231248150.3610%40virtualbox
In-Reply-To: <947b2453-52b6-4940-fd20-ddf350c5df4d@kdbg.org>

```
Hi Hannes (& Junio, see below),

On Mon, 22 May 2017, Johannes Sixt wrote:

> Am 22.05.2017 um 13:59 schrieb Johannes Schindelin:
> > On Sat, 20 May 2017, Johannes Sixt wrote:
> > > This small series fixes these warnings on Windows:
> > >
> > > C:\Temp\gittest>git fetch C:\Temp\gittest
> > > warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
> > > warning: unable to access '.git/branches/C:\Temp\gittest': Invalid
> > > warning: argument
> > >  From C:\Temp\gittest
> > >   * branch            HEAD       -> FETCH_HEAD
> > >
> > > The fix is in the second patch; the first patch is a
> > > preparation that allows to write the fix in my preferred style.
> > 
> > Thank you!
> > 
> > Maybe you want to accompany these patches with a simple test case that
> > uses e.g. ls-remote on $(pwd | tr / \\\\)?
> 
> Actually, no, I don't want to. It would have to be protected by MINGW, and I
> don't want to burden us (and here I mean Windows folks) with a check for a
> cosmetic deficiency. (Shell scripts, slow forks, yadda, yadda...)

Actually, yes, I want to.

Yes, it would have to be protected by MINGW, and yes, it would put a
burden on us, but also yes: it would put an even higher burden on me to
check this manually before releasing Git for Windows, or even worse: this
regression would be the kind of bug that triggers many bug reports,
addressing which would take a lot more time than writing this test case
and executing it as part of our test suite.

So here goes:

-- snipsnap --
From: Johannes Schindelin <johannes.schindelin@gmx.de>
Date: Tue, 23 May 2017 12:42:13 +0200
Subject: [PATCH] mingw: verify that paths are not mistaken for remote nicknames

This added test case simply verifies that users will not be bothered
with bogus complaints à la

	warning: unable to access '.git/remotes/D:\repo': Invalid argument

when fetching from a Windows path (in this case, D:\repo).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 t/t5580-clone-push-unc.sh | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/t/t5580-clone-push-unc.sh b/t/t5580-clone-push-unc.sh
index b195f71ea98..93ce99ba3c6 100755
--- a/t/t5580-clone-push-unc.sh
+++ b/t/t5580-clone-push-unc.sh
@@ -1,13 +1,19 @@
 #!/bin/sh
 
-test_description='various UNC path tests (Windows-only)'
+test_description='various Windows-only path tests'
 . ./test-lib.sh
 
 if ! test_have_prereq MINGW; then
-	skip_all='skipping UNC path tests, requires Windows'
+	skip_all='skipping Windows-only path tests'
 	test_done
 fi
 
+test_expect_success 'remote nick cannot contain backslashes' '
+	BACKSLASHED="$(pwd | tr / \\\\)" &&
+	git ls-remote "$BACKSLASHED" >out 2>err &&
+	! grep "unable to access" err
+'
+
 UNCPATH="$(pwd)"
 case "$UNCPATH" in
 [A-Z]:*)
-- 
2.13.0.windows.1

```

## Johannes Sixt, 2017-05-23 18:39

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <574f9050-e711-e83c-ba93-6be2dc2a44bc@kdbg.org>
URL: https://gitlist.dev/e/574f9050-e711-e83c-ba93-6be2dc2a44bc%40kdbg.org
In-Reply-To: <alpine.DEB.2.21.1.1705231248150.3610@virtualbox>

```
Am 23.05.2017 um 12:53 schrieb Johannes Schindelin:
> Hi Hannes (& Junio, see below),
> 
> On Mon, 22 May 2017, Johannes Sixt wrote:
> 
>> Am 22.05.2017 um 13:59 schrieb Johannes Schindelin:
>>> On Sat, 20 May 2017, Johannes Sixt wrote:
>>>> This small series fixes these warnings on Windows:
>>>>
>>>> C:\Temp\gittest>git fetch C:\Temp\gittest
>>>> warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
>>>> warning: unable to access '.git/branches/C:\Temp\gittest': Invalid
>>>> warning: argument
>>>>   From C:\Temp\gittest
>>>>    * branch            HEAD       -> FETCH_HEAD
>>>>
>>>> The fix is in the second patch; the first patch is a
>>>> preparation that allows to write the fix in my preferred style.
>>>
>>> Thank you!
>>>
>>> Maybe you want to accompany these patches with a simple test case that
>>> uses e.g. ls-remote on $(pwd | tr / \\\\)?
>>
>> Actually, no, I don't want to. It would have to be protected by MINGW, and I
>> don't want to burden us (and here I mean Windows folks) with a check for a
>> cosmetic deficiency. (Shell scripts, slow forks, yadda, yadda...)
> 
> Actually, yes, I want to.
> 
> Yes, it would have to be protected by MINGW, and yes, it would put a
> burden on us, but also yes: it would put an even higher burden on me to
> check this manually before releasing Git for Windows, or even worse: this
> regression would be the kind of bug that triggers many bug reports,
> addressing which would take a lot more time than writing this test case
> and executing it as part of our test suite.

Fair enough. The patch looks good. I'll be able to test no earlier than 
Monday, though.

> 
> So here goes:
> 
> -- snipsnap --
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> Date: Tue, 23 May 2017 12:42:13 +0200
> Subject: [PATCH] mingw: verify that paths are not mistaken for remote nicknames
> 
> This added test case simply verifies that users will not be bothered
> with bogus complaints à la
> 
> 	warning: unable to access '.git/remotes/D:\repo': Invalid argument
> 
> when fetching from a Windows path (in this case, D:\repo).
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>   t/t5580-clone-push-unc.sh | 10 ++++++++--
>   1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/t/t5580-clone-push-unc.sh b/t/t5580-clone-push-unc.sh
> index b195f71ea98..93ce99ba3c6 100755
> --- a/t/t5580-clone-push-unc.sh
> +++ b/t/t5580-clone-push-unc.sh
> @@ -1,13 +1,19 @@
>   #!/bin/sh
>   
> -test_description='various UNC path tests (Windows-only)'
> +test_description='various Windows-only path tests'
>   . ./test-lib.sh
>   
>   if ! test_have_prereq MINGW; then
> -	skip_all='skipping UNC path tests, requires Windows'
> +	skip_all='skipping Windows-only path tests'
>   	test_done
>   fi
>   
> +test_expect_success 'remote nick cannot contain backslashes' '
> +	BACKSLASHED="$(pwd | tr / \\\\)" &&
> +	git ls-remote "$BACKSLASHED" >out 2>err &&
> +	! grep "unable to access" err
> +'
> +
>   UNCPATH="$(pwd)"
>   case "$UNCPATH" in
>   [A-Z]:*)
> 


```

## Junio C Hamano, 2017-05-23 22:08

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <xmqqinkrjkfb.fsf@gitster.mtv.corp.google.com>
URL: https://gitlist.dev/e/xmqqinkrjkfb.fsf%40gitster.mtv.corp.google.com
In-Reply-To: <alpine.DEB.2.21.1.1705231245300.3610@virtualbox>

```
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

>> In this case, the warning occurs because I build with nd/fopen-errors.
>
> Ah. So the base commit Junio chose for your v1 is completely
> inappropriate. It should be nd/fopen-errors instead.

Actuallly, Hannes's patch text and problem description are
confusingly inconsistent, and I have to say that the above statement
is wrong---do not react to this statement just yet, because I'll
also say "but you are right" real soon.

Because "git fetch a/b" your UNIXy friends run will not consider
"a/b" as a remote nickname, "a\b" in "git fetch a\b" Windows folks
run must not be taken as a remote nickname either.  That is a
justification enough for Hannes's patch text, and that does not
change whether we take nd/fopen-errors or discard it.  So in that
sense, the patch text does not have anything to do with the other
topic.

But you are right (as promised ;-) to say that nd/fopen-errors needs
a bit more polishing to work correctly on Windows.  I unfortunately
do not think Hannes's patch addresses the real issue.  

Isn't the root cause of "Invalid argument" a colon in a (mistakenly
identified) remote nickname, not a backslash?  I doubt that it would
help to loosen valid_remote_nick() to pay attention to backslashes.
Surely, it may hide the issue when the path also has a backslash,
but wouldn't Windows folks see the same warning for "git fetch c:c"
for example even with Hannes's patch?

We use the pattern "try to open a path, and treat a failure to open
as indicating that the path is missing (and take information we
would have obtained from the contents of the path, if existed, from
elsewhere, as necessary)" pretty much everywhere, not just when
accessing a remote.  And nd/fopen-errors tries to tweak the "treat a
failure to open as a sign of missing path" to be a bit more careful
by warning unless the error we get is ENOENT or ENOTDIR (otherwise
we may treat a file that exists but cannot be read as if it is
missing without any indication).

The solution for the problem Hannes's proposed log message describes
lies in warn_on_fopen_errors() function that was introduced in the
nd/fopen-errors topic.  It appears that in Windows port, open() and
fopen() return EINVAL for a file that does not exist and whose name
Windows does not like, so we probably should do something like the
attached to work around the EINVAL (I do not know about the symbol
checked for #ifdef---there may be a more appropriate one).

I am not entirely happy with the workaround, because I do not know
if EINVAL can come _ONLY_ due to a colon in the pathname on Windows,
or if there are some other cases that deserve to be warned that also
yield EINVAL, and the attached will sweep the problem under the rug
for the "other cases", partially undoing what nd/fopen-errors topic
wanted to do.  But it does not make it worse than before the topic
happened [*1*].

And that kind of solution does belong to nd/fopen-errors.

So in short:

 (1) Hannes's patches are good, but they solve a problem that is
     different from what their log messages say; the log message
     needs to be updated;

 (2) In nd/fopen-errors topic, we need a new patch that deals with
     EINVAL on Windows.

Thanks.


[Footnote]

*1* An alternative that may allow us to avoid sweeping the issue
    under the rug may be to have a more precise logic to see if the
    open failure is due to missing file in the implementation of
    open() and fopen() emulation---at that level, the logic can be
    built with more platform knowledge (e.g. EINVAL?  Let's see what
    path we got---ah, there is a colon)---and turn EINVAL into
    ENOENT, or something like that.  I do not have a strong opinion
    if that is a better solution or the attached workaround is good
    enough.

 wrapper.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/wrapper.c b/wrapper.c
index 6e513c904a..7b6d3e3f94 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -418,9 +418,18 @@ FILE *fopen_for_writing(const char *path)
 	return ret;
 }
 
+static int is_an_error_for_missing_path(int no)
+{
+#if WINDOWS
+	if (errno == EINVAL)
+		return 1;
+#endif
+	return (errno == ENOENT || errno == ENOTDIR);
+}
+
 int warn_on_fopen_errors(const char *path)
 {
-	if (errno != ENOENT && errno != ENOTDIR) {
+	if (!is_error_for_missing_path(errno)) {
 		warn_on_inaccessible(path);
 		return -1;
 	}


```

## Johannes Sixt, 2017-05-24 05:45

Subject: Re: [PATCH 0/2] Fix warnings on access of a remote with Windows paths
Message-ID: <c36ae9af-b566-5bb3-ad70-ee7f0051ca9a@kdbg.org>
URL: https://gitlist.dev/e/c36ae9af-b566-5bb3-ad70-ee7f0051ca9a%40kdbg.org
In-Reply-To: <xmqqinkrjkfb.fsf@gitster.mtv.corp.google.com>

```
Am 24.05.2017 um 00:08 schrieb Junio C Hamano:
> So in short:
> 
>   (1) Hannes's patches are good, but they solve a problem that is
>       different from what their log messages say; the log message
>       needs to be updated;
> 
>   (2) In nd/fopen-errors topic, we need a new patch that deals with
>       EINVAL on Windows.

Will reroll the patches. Good analysis, BTW. (It was a late discovery of 
mine that nd/fopen-errors is actually the source of the warnings.)

-- Hannes

```

## Johannes Sixt, 2017-05-25 12:00

Subject: [PATCH v3 2/2] Windows: do not treat a path with backslashes as a remote's nick name
Message-ID: <10ee6b91-cd54-d43a-4cfb-d3baa2af7e7a@kdbg.org>
URL: https://gitlist.dev/e/10ee6b91-cd54-d43a-4cfb-d3baa2af7e7a%40kdbg.org
In-Reply-To: <c36ae9af-b566-5bb3-ad70-ee7f0051ca9a@kdbg.org>

```
On Windows, the remote repository name in, e.g., `git fetch foo\bar`
is clearly not a nickname for a configured remote repository. However,
the function valid_remote_nick() does not account for backslashes.
Use is_dir_sep() to check for both slashes and backslashes on Windows.

This was discovered while playing with Duy's patches that warn after
fopen() failures. The functions that read the branches and remotes
files are protected by a valid_remote_nick() check. Without this
change, a Windows style absolute path is incorrectly regarded as
nickname and is concatenated to a prefix and used with fopen(). This
triggers warnings because a colon in a path name is not allowed:

C:\Temp\gittest>git fetch C:\Temp\gittest
warning: unable to access '.git/remotes/C:\Temp\gittest': Invalid argument
warning: unable to access '.git/branches/C:\Temp\gittest': Invalid argument
From C:\Temp\gittest
 * branch            HEAD       -> FETCH_HEAD

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
Am 24.05.2017 um 07:45 schrieb Johannes Sixt:
> Am 24.05.2017 um 00:08 schrieb Junio C Hamano:
>> So in short:
>>
>>   (1) Hannes's patches are good, but they solve a problem that is
>>       different from what their log messages say; the log message
>>       needs to be updated;

I do not resend patch 1/2 as it is unchanged in all regards. This 2/2
changes the justification; patch text is unchanged.

 remote.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/remote.c b/remote.c
index ad6c5424ed..1949882c10 100644
--- a/remote.c
+++ b/remote.c
@@ -645,7 +645,12 @@ static int valid_remote_nick(const char *name)
 {
 	if (!name[0] || is_dot_or_dotdot(name))
 		return 0;
-	return !strchr(name, '/'); /* no slash */
+
+	/* remote nicknames cannot contain slashes */
+	while (*name)
+		if (is_dir_sep(*name++))
+			return 0;
+	return 1;
 }
 
 const char *remote_for_branch(struct branch *branch, int *explicit)
-- 
2.13.0.55.g17b7d13330

```

## Junio C Hamano, 2017-05-25 23:16

Subject: Re: [PATCH v3 2/2] Windows: do not treat a path with backslashes as a remote's nick name
Message-ID: <xmqq37bseddy.fsf@gitster.mtv.corp.google.com>
URL: https://gitlist.dev/e/xmqq37bseddy.fsf%40gitster.mtv.corp.google.com
In-Reply-To: <10ee6b91-cd54-d43a-4cfb-d3baa2af7e7a@kdbg.org>

```
Johannes Sixt <j6t@kdbg.org> writes:

>>> So in short:
>>>
>>>   (1) Hannes's patches are good, but they solve a problem that is
>>>       different from what their log messages say; the log message
>>>       needs to be updated;
>
> I do not resend patch 1/2 as it is unchanged in all regards. This 2/2
> changes the justification; patch text is unchanged.

Thanks.  I think this is explained better.  Complaints against
fopen() warnings sounded as if we should avoid attempting to open a
file that may result in _any_ failure, which I felt was misleading,
but it is not a huge issue.

So how do we want to proceed on the point (2), i.e. updating the
"warn on _unexpected_ errors from fopen" series to make it aware of
the EINVAL we can expect on Windows?  My primary question is if all
EINVAL we could ever see on Windows after open/fopen returns an
error is because the pathname the caller gave is not liked by the
filesystem (hence we also know that the path does not exist).

If that is the case, then the "workaround" patch I sent would be an
OK approach (even though I do not know what to write after #ifdef
and I suspect that is not "WINDOWS". We would want to cover the one
you use, the one Dscho releases and possibly the cygwin build).

If we can see EINVAL after open/fopen error that is _not_ expected
and indicates a failure that is worth reporting to the user (just
like we want to report e.g. I/O or permission errors), I think
Windows folks are in a better position than I am to decide between
that approach and a patch at lower level (e.g. teach open/fopen not
to give EINVAL and instead give ENOENT when appropriate).


>  remote.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/remote.c b/remote.c
> index ad6c5424ed..1949882c10 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -645,7 +645,12 @@ static int valid_remote_nick(const char *name)
>  {
>  	if (!name[0] || is_dot_or_dotdot(name))
>  		return 0;
> -	return !strchr(name, '/'); /* no slash */
> +
> +	/* remote nicknames cannot contain slashes */
> +	while (*name)
> +		if (is_dir_sep(*name++))
> +			return 0;
> +	return 1;
>  }
>  
>  const char *remote_for_branch(struct branch *branch, int *explicit)

```
