Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Work around case-insensitivity issues with cwd on Windows#54

Closed
dscho wants to merge 2 commits intogitgitgadget:mastergitgitgadget/git:masterfrom
dscho:mingw-getcwddscho/git:mingw-getcwdCopy head branch name to clipboard
Closed

Work around case-insensitivity issues with cwd on Windows#54
dscho wants to merge 2 commits intogitgitgadget:mastergitgitgadget/git:masterfrom
dscho:mingw-getcwddscho/git:mingw-getcwdCopy head branch name to clipboard

Conversation

@dscho
Copy link
Member

@dscho dscho commented Oct 23, 2018

On Windows, file names are recorded case-sensitively, but looked up case-insensitively. Therefore, it is possible to switch to a directory by using incorrect case, e.g. cd documentation will still get you into the Documentation subdirectory.

In Powershell, doing so will however report the current directory with the specified spelling rather than the one recorded on disk, and Git will get confused.

To remedy that, we fixed this in Git for Windows more than three years ago, and needed only a small fix a couple of months later to accommodate for the diverse scenarios encountered by the many Git for Windows users.

Not only to keep the story closer to what happened historically, but also to make it easier to follow, I refrained from squashing these two patches.

Side note: the second patch is technically not battle-tested for that long: it uses an API function that requires Windows Vista or later, and we only recently started to clean up Git for Windows' code to drop fallbacks for Windows XP. Read: this code used to load the GetFinalPathNameByHandle() function dynamically, and that is the only difference to the code that has been "battle-tested" for close to three years.

Changes since v1:

  • Fixed a grammar mistake in the second commit message.

Cc: Stephen Smith ischis2@cox.net

When switching the current working directory, say, in PowerShell, it is
quite possible to use a different capitalization than the one that is
recorded on disk. While doing the same in `cmd.exe` adjusts the
capitalization magically, that does not happen in PowerShell so that
`getcwd()` returns the current directory in a different way than is
recorded on disk.

Typically this creates no problems except when you call

	git log .

in a subdirectory called, say, "GIT/" but you switched to "Git/" and
your `getcwd()` reports the latter, then Git won't understand that you
wanted to see the history as per the `GIT/` subdirectory but it thinks you
wanted to see the history of some directory that may have existed in the
past (but actually never did).

So let's be extra careful to adjust the capitalization of the current
directory before working with it.

Reported by a few PowerShell power users ;-)

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@dscho dscho changed the title Mingw getcwd Work around case-insensitivity issues with cwd on Windows Oct 23, 2018
@dscho
Copy link
Member Author

dscho commented Oct 23, 2018

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Oct 23, 2018

An error occurred while submitting:

Error: git fetch https://github.com/gitgitgadget/git -- +refs/notes/gitgitgadget:refs/notes/gitgitgadget +refs/pull/54/head:refs/pull/54/head +refs/heads/maint:refs/remotes/upstream/maint +refs/heads/master:refs/remotes/upstream/master +refs/heads/next:refs/remotes/upstream/next +refs/heads/pu:refs/remotes/upstream/pu failed: 1,
error: cannot lock ref 'refs/notes/gitgitgadget': is at 261aaa9 but expected 25c50cd
From https://github.com/gitgitgadget/git
! 25c50cd...adc7a62 refs/notes/gitgitgadget -> refs/notes/gitgitgadget (unable to update local ref)

  • [new ref] refs/pull/54/head -> refs/pull/54/head

@dscho
Copy link
Member Author

dscho commented Oct 23, 2018

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Oct 23, 2018

Submitted as pull.54.git.gitgitgadget@gmail.com

`GetLongPathName()` function may fail when it is unable to query
the parent directory of a path component to determine the long name
for that component. It happens, because it uses `FindFirstFile()`
function for each next short part of path. The `FindFirstFile()`
requires `List Directory` and `Synchronize` desired access for a calling
process.

In case of lacking such permission for some part of path,
the `GetLongPathName()` returns 0 as result and `GetLastError()`
returns ERROR_ACCESS_DENIED.

`GetFinalPathNameByHandle()` function can help in such cases, because
it requires `Read Attributes` and `Synchronize` desired access to the
target path only.

The `GetFinalPathNameByHandle()` function was introduced on
`Windows Server 2008/Windows Vista`. So we need to load it dynamically.

`CreateFile()` parameters:
    `lpFileName` = path to the current directory
    `dwDesiredAccess` = 0 (it means `Read Attributes` and `Synchronize`)
    `dwShareMode` = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
                    (it prevents `Sharing Violation`)
    `lpSecurityAttributes` = NULL (default security attributes)
    `dwCreationDisposition` = OPEN_EXISTING
                              (required to obtain a directory handle)
    `dwFlagsAndAttributes` = FILE_FLAG_BACKUP_SEMANTICS
                             (required to obtain a directory handle)
    `hTemplateFile` = NULL (when opening an existing file or directory,
                            `CreateFile` ignores this parameter)

The string that is returned by `GetFinalPathNameByHandle()` function
uses the \\?\ syntax. To skip the prefix and convert backslashes
to slashes, the `normalize_ntpath()` mingw function will be used.

Note: `GetFinalPathNameByHandle()` function returns a final path.
It is the path that is returned when a path is fully resolved.
For example, for a symbolic link named "C:\tmp\mydir" that points to
"D:\yourdir", the final path would be "D:\yourdir".

Signed-off-by: Anton Serbulov <aserbulov@plesk.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@dscho
Copy link
Member Author

dscho commented Oct 24, 2018

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Oct 24, 2018

Submitted as pull.54.v2.git.gitgitgadget@gmail.com

@dscho
Copy link
Member Author

dscho commented Dec 15, 2018

Merged via cc67487

@dscho dscho closed this Dec 15, 2018
@dscho dscho deleted the mingw-getcwd branch December 15, 2018 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.