Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to clone remote repository with a clone path > 255 chars #2576

Closed
1 task
rishabhBudhouliya opened this issue Apr 6, 2020 · 33 comments
Closed
1 task

Comments

@rishabhBudhouliya
Copy link

rishabhBudhouliya commented Apr 6, 2020

  • I was not able to find an open or closed issue matching what I'm seeing

Setup

  • Which version of Git for Windows are you using? Is it 32-bit or 64-bit?
$ git --version --build-options

git version 2.26.0.windows.1
cpu: x86_64
built from commit: 9c98e1ccdfd839e4eaae1c2747d0088ef89d446b
sizeof-long: 4
sizeof-size_t: 8
  • Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit?
$ cmd.exe /c ver

Microsoft Windows [Version 10.0.18363.720]
  • What options did you set as part of the installation? Or did you choose the
    defaults?
# One of the following:
> type "C:\Program Files\Git\etc\install-options.txt"

Editor Option: VIM
Custom Editor Path:
Path Option: Cmd
SSH Option: OpenSSH
Tortoise Option: false
CURL Option: OpenSSL
CRLF Option: CRLFAlways
Bash Terminal Option: MinTTY
Performance Tweaks FSCache: Enabled
Use Credential Manager: Enabled
Enable Symlinks: Disabled **
  • Any other interesting things about your environment that might be related
    to the issue you're seeing?

** Nothing that I can think of**

Details

  • Which terminal/shell are you running Git from? e.g Bash/CMD/PowerShell/other

Git Bash

git clone -c core.longpaths=true <repo-url>
  • What did you expect to occur after running these commands?

A fresh repository cloned in my local file system

  • What actually happened instead?

fatal: Unable to create temporary file 'C:/Users/techn/AppData/Local/Temp/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqdnbsbqnbnclnhbnvoewqnslobjqszcinqbpibonqbandlftxf14739883836305635481/zedtlkgruqbrdlhijcmwdltgocurldhkcxzjqlutteqqpljllmpofmhmkm/git-client-p': Filename too long

  • Steps to reproduce the issue:
1. Create a directory structure with char length 246, in my case, it is:    C:/Users/techn/AppData/Local/Temp/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqdnbsbqnbnclnhbnvoewqnslobjqszcinqbpibonqbandlftxf14739883836305635481/zedtlkgruqbrdlhijcmwdltgocurldhkcxzjqlutteqqpljllmpofmhmkm
2. Open a Git Bash and change into this directory
3. Use git clone -c core.longpaths=true https://github.com/jenkinsci/git-client-plugin.git (18 chars)
3. The resulting clone path is 264 chars.
@rishabhBudhouliya
Copy link
Author

rishabhBudhouliya commented Apr 6, 2020

This issue is in reference to the issue #2075 , I could not find a solution there, hence created a new issue.

@dscho
Copy link
Member

dscho commented Apr 7, 2020

git clone -c core.longpaths=true <repo-url>

Does it work if you use git -c core.longpaths=true clone <url>, i.e. put the -c before the clone command?

@rishabhBudhouliya
Copy link
Author

rishabhBudhouliya commented Apr 7, 2020

No, it results with the same fatal error: Unable to create temporary file : Filename too long

There is one more observation, I have tried a git init + git fetch instead of git clone and that works, but as soon as I apply git config remote.origin.url <url>, the results is:

error: could not lock config file .git/config: Filename too long

@dscho
Copy link
Member

dscho commented Apr 7, 2020

And in all those cases, .git/config contains the setting core.longPaths = true, right?

I won't lie, there is a very good chance that I won't get to this anytime soon. Do you have some experience with C? I could guide you through debugging and fixing this, is the best I can do in the foreseeable future.

@rishabhBudhouliya
Copy link
Author

.git/config doesn't contain core.longpaths = true because that also results in the error could not lock config file .git/config:Filename too long

I was applying git config --global core.longpaths = true which didn't show any error but apparently it can't access the local git config.

I only have some theoretical knowledge (college) in C. I could try it if you don't mind guiding me or point me to the right direction.

@dscho
Copy link
Member

dscho commented Apr 7, 2020

.git/config doesn't contain core.longpaths = true because that also results in the error could not lock config file .git/config:Filename too long

Yeah, there is a catch-22 right there. If the config itself cannot be read... because it would need the setting that's in the config... it simply won't work.

I guess that we cannot really support that use case.

However, git config --global core.longpaths true should have worked. (Note the absence of the =, that would be incorrect syntax.)

@rishabhBudhouliya
Copy link
Author

My bad, I used git config --global core.longpaths true only.

After setting the global property, I should be able to access the local git config? That is the unexpected behavior. (git init and git fetch both work fine in the same local repository)

@dscho
Copy link
Member

dscho commented Apr 8, 2020

After setting the global property, I should be able to access the local git config?

I would think so, yes.

Maybe you can build Git and then run it in gdb to figure out where things go wrong? You could set a break point on builtin_error() via b builtin_error so that execution stops just before printing the error message, and you could inspect the stack trace via bt. Or you could git grep for the error message and insert open_in_gdb() before recompiling and running the command with /usr/src/git/bin-wrappers/git ....

@rishabhBudhouliya
Copy link
Author

So I have built Git and I can run it in gdb. How am I suppose to attach the gdb to the git process I'm running from git bash?

@dscho
Copy link
Member

dscho commented Apr 8, 2020

How am I suppose to attach the gdb to the git process I'm running from git bash?

It is too short-lived to attach it via normal use.

If you use the open_in_gdb() method I mentioned above, that function will do it for you.

Otherwise, start the command in gdb to begin with:

GIT_DEBUGGER=1 /usr/src/git/bin-wrappers/git ...

@rishabhBudhouliya
Copy link
Author

rishabhBudhouliya commented Apr 9, 2020

So here is what I tried:

Clone path: `/test/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqdnbsbqnbnclnhbnvoewqnslobjqszcinqbpibonqbandlftxf14739883836305635481/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqd` (246 chars)

Command: git init
Error stack trace:

(gdb) bt
#0  die_builtin (err=0x158f1b0 "Invalid path '%s': Filename too long",
    params=0x158f5e8 "▒9Y\001") at usage.c:64
#1  0x0000000000660c69 in die_errno (
    fmt=0x706495 <write_tree_usage+437> "Invalid path '%s'") at usage.c:211
#2  0x00000000004cd046 in strbuf_realpath (resolved=0x158f740,
    path=0x6e9374 <index_pack_usage+4052> ".git", die_on_error=1)
    at abspath.c:137
#3  0x00000000004cd29e in real_pathdup (
    path=0x6e9374 <index_pack_usage+4052> ".git", die_on_error=1)
    at abspath.c:229
#4  0x0000000000455d1d in init_db (
    git_dir=0x6e9374 <index_pack_usage+4052> ".git", real_git_dir=0x0,
    template_dir=0x0, flags=2) at builtin/init-db.c:348
#5  0x00000000004566e4 in cmd_init_db (argc=0, argv=0x1590620, prefix=0x0)
    at builtin/init-db.c:600
#6  0x000000000040305c in run_builtin (p=0x6bf4c0 <commands+1152>, argc=1,
    argv=0x1590620) at git.c:444
#7  0x0000000000403446 in handle_builtin (argc=1, argv=0x1590620) at git.c:674
#8  0x00000000004036fc in run_argv (argcp=0x158fd80, argv=0x158fd28)
    at git.c:741
#9  0x0000000000403b62 in cmd_main (argc=1, argv=0x1590620) at git.c:872
#10 0x00000000004cc8a7 in main (argc=2, argv=0x1590618) at common-main.c:52

@dscho
Copy link
Member

dscho commented Apr 9, 2020

Didn't you say earlier that git init does work?

@rishabhBudhouliya
Copy link
Author

rishabhBudhouliya commented Apr 9, 2020

Yes, when I tried the same experiment explained in the issue description, git init and git fetch worked.
Strangely in the windows sdk environment, this is the result I am getting. git init is not working.
(I applied git config --global core.longpaths true before performing any other git operation)

I'm not sure myself if this is because of the experiment I am performing or git-for-windows fault.

@rishabhBudhouliya
Copy link
Author

What is strange in the gdb debugging experiment, the clone path isn't even 255 chars long, it is shorter than that, it would be greater than that after cloning the remote repository (18 chars).

Would you like me to debug further?

@rishabhBudhouliya
Copy link
Author

@dscho apologies, it is because of the experiment. The clone path was already >260 chars hence git init was not working.

This the new experiment:
Clone path: C:/git-sdk-64/test/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqdnbsbqnbnclnhbnvoewqnslobjqszcinqbpibonqbandlftxf14739883836305635481/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftej/

Git Command: run clone -c core.longpaths=true https://github.com/jenkinsci/git-client-plugin.git

Error stack:

(gdb) run clone -c core.longpaths=true https://github.com/jenkinsci/git-client-plugin.git
Starting program: C:\git-sdk-64\usr\src\git\git.exe clone -c core.longpaths=true https://github.com/jenkinsci/git-client-plugin.git
[New Thread 13624.0x2134]
[New Thread 13624.0x23c]
[New Thread 13624.0x9f4]
Cloning into 'git-client-plugin'...
warning: templates not found in C:/git-sdk-64/usr/src/share/git-core/templates

Thread 1 hit Breakpoint 2, die_builtin (
    err=0x158f150 "Unable to create temporary file '%s': Filename too long",
    params=0x158f588 "Ȓ▒\003") at usage.c:64
64              trace2_cmd_error_va(err, params);
(gdb) bt
#0  die_builtin (
    err=0x158f150 "Unable to create temporary file '%s': Filename too long",
    params=0x158f588 "Ȓ▒\003") at usage.c:64
#1  0x0000000000660c69 in die_errno (
    fmt=0x73c528 <result_type+1320> "Unable to create temporary file '%s'")
    at usage.c:211
#2  0x0000000000667391 in xmkstemp (
    filename_template=0x158f5c0 "C:/git-sdk-64/test/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqdnbsbqnbnclnhbnvoewqnslobjqszcinqbpibonqbandlftxf14739883836305635481/mdyshjeqvvvkiotkhiimoqkhwjl"...) at wrapper.c:427
#3  0x00000000004559cb in create_default_files (template_path=0x0,
    original_git_dir=0x38a4db8 "C:/git-sdk-64/test/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqdnbsbqnbnclnhbnvoewqnslobjqszcinqbpibonqbandlftxf14739883836305635481/mdyshjeqvvvkiotkhiimoqkhwjl"...) at builtin/init-db.c:281
#4  0x0000000000455e34 in init_db (
    git_dir=0x38a54c8 "C:/git-sdk-64/test/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqdnbsbqnbnclnhbnvoewqnslobjqszcinqbpibonqbandlftxf14739883836305635481/mdyshjeqvvvkiotkhiimoqkhwjl"...,
    real_git_dir=0x0, template_dir=0x0, flags=1) at builtin/init-db.c:383
#5  0x0000000000426fa3 in cmd_clone (argc=1, argv=0x38a0800, prefix=0x0)
    at builtin/clone.c:1107
#6  0x000000000040305c in run_builtin (p=0x6bf208 <commands+456>, argc=4,
    argv=0x38a0800) at git.c:444
#7  0x0000000000403446 in handle_builtin (argc=4, argv=0x38a0800) at git.c:674
#8  0x00000000004036fc in run_argv (argcp=0x158fd80, argv=0x158fd28)
    at git.c:741
#9  0x0000000000403b62 in cmd_main (argc=4, argv=0x38a0800) at git.c:872
#10 0x00000000004cc8a7 in main (argc=5, argv=0x38a07f8) at common-main.c:52

@dscho
Copy link
Member

dscho commented Apr 10, 2020

What is the value of the global variable core_long_paths?

@rishabhBudhouliya
Copy link
Author

For: vim ~/.gitconfig
Result:

[core]
        longpaths = true

@dscho
Copy link
Member

dscho commented Apr 10, 2020

No, I meant in memory. The question is whether the config setting has been parsed at that point, or not yet.

@rishabhBudhouliya
Copy link
Author

Okay, so I put a breakpoint at compat/mingw.c: core_long_paths = git_config_bool(var,value)
The result is:

(gdb) bt
#0  mingw_core_config (var=0x1591098 "core.longpaths",
    value=0x1593c58 "true", cb=0x0) at compat/mingw.c:281
#1  0x00000000005166e7 in configset_iter (cs=0x1592348,
    fn=0x67e6fa <mingw_core_config>, data=0x0) at config.c:1799
#2  0x00000000005174c8 in repo_config (repo=0x7bafc0 <the_repo>,
    fn=0x67e6fa <mingw_core_config>, data=0x0) at config.c:2119
#3  0x00000000005177b9 in git_config (fn=0x67e6fa <mingw_core_config>,
    data=0x0) at config.c:2203
#4  0x0000000000426923 in cmd_clone (argc=4, argv=0x1590800, prefix=0x0)
    at builtin/clone.c:960
#5  0x000000000040305c in run_builtin (p=0x6bf208 <commands+456>, argc=4,
    argv=0x1590800) at git.c:444
#6  0x0000000000403446 in handle_builtin (argc=4, argv=0x1590800) at git.c:674
#7  0x00000000004036fc in run_argv (argcp=0x158fd80, argv=0x158fd28)
    at git.c:741
#8  0x0000000000403b62 in cmd_main (argc=4, argv=0x1590800) at git.c:872
#9  0x00000000004cc8a7 in main (argc=5, argv=0x15907f8) at common-main.c:52

@dscho
Copy link
Member

dscho commented Apr 10, 2020

So what you're saying is that the global variable is set when the error_builtin() function is called?

If so, it would be good to study the code in compat/mingw.c (or compat/mingw.h) that is supposed to handle the long paths, and if necessary, single-step through the code to understand why it fails to work as intended.

@rishabhBudhouliya
Copy link
Author

rishabhBudhouliya commented Apr 10, 2020

I'm not sure if I understand you correctly, I'll explain what I did if you feel it is wrong, please point it out.

  • I started the gdb and put two breakpoints, one at error_builtin() and one at die_builtin().
  • Once I run run clone -c core.longpaths=true <url>, the thread execution breaks at die_builtin() and I have posted that screenshot.
  • I put one more breakpoint, on compat/mingw.c also to check if core_long_paths is being set or not. I have posted that stack trace as well.

@dscho
Copy link
Member

dscho commented Apr 10, 2020

@rishabhBudhouliya what I meant was inspecting the value of core_long_paths via

p core_long_paths

in gdb when it stops inside error_builtin().

@dscho
Copy link
Member

dscho commented Apr 10, 2020

Also, the code that acts on core_long_paths to internally convert long paths via prefixing them with \\?\ includes https://github.com/git-for-windows/git/blob/v2.26.0.windows.1/compat/mingw.c#L632. And now that I see the comment:

	/* CreateDirectoryW path limit is 248 (MAX_PATH - 8.3 file name) */

I suspect that that is the culprit. IIRC CreateDirectoryW() is unable to handle long paths, or at least it was unable to do that at the time this comment was written.

Maybe you can experiment with this a bit, to see whether this is the actual culprit?

@rishabhBudhouliya
Copy link
Author

Sure, I'll try to investigate this section of code using the debugger.
Also, gdb stopped at die_builtin() and upon inspecting p core_long_paths the result is 1=1, does that make sense?

@dscho
Copy link
Member

dscho commented Apr 10, 2020

upon inspecting p core_long_paths the result is 1=1, does that make sense?

Yes, that means that the config setting is read correctly, and that the code that should handle long paths is misbehaving.

@tboegi
Copy link

tboegi commented Apr 10, 2020

Could it be that we are limited in the path name length because of
PATH_MAX ?

@rishabhBudhouliya
Copy link
Author

While looking at the error stack, there is an issue with creating a temporary file.
As far as I can understand,

git/compat/mingw.c

Lines 1205 to 1207 in db1835b

/* we need to return the path, thus no long paths here! */
if (xutftowcs_path(wtemplate, template) < 0)
return NULL;

doesn't work for long paths, is that useful?

Also, from Windows v1607,
These are the directory management functions that no longer have MAX_PATH restrictions if you opt-in to long path behavior: CreateDirectoryW, CreateDirectoryExW GetCurrentDirectoryW RemoveDirectoryW SetCurrentDirectoryW.

@dscho
Copy link
Member

dscho commented Apr 10, 2020

The crucial tid-bit is "if you opt-in". You have to opt-in, and you have to do that in a manner that does not break Git for Windows on older Windows versions.

@dscho
Copy link
Member

dscho commented Apr 10, 2020

Could it be that we are limited in the path name length because of
PATH_MAX ?

@tboegi I suspect exactly that.

@tboegi
Copy link

tboegi commented Apr 11, 2020

`The problem is deeper than that.
After changing PATH_MAX like this:

diff --git a/git-compat-util.h b/git-compat-util.h
index    6c3dd4a5dd..d06f7980ab  100644
--- a/git-compat-util.h
+++ b/git- compat-util.h
@@ -315,6 +315,9 @@ char *gitdirname(char *);
 #define NI_MAXSERV 32
 #endif                                                                                                                                           +#if defined(GIT_WINDOWS_NATIVE)
+#undef PATH_MAX
+#endif

compiling & installing, I went into another "Git SDK 64 bit" window:

tb@windows MINGW64 ~/mdyshjeqvvvkiotkhiimoqkhwjlmgqrdwwzhnrwlsimanqdqeutjmqcwnyprzzjftejzfjvvjknbsxoswabqdnbsbqnbnclnhbnvoewqnslobjqszcinqbpibonqbandlftxf14739883836305635481/zedtlkgruqbrdlhijcmwdltgocurldh kcxzjqlutteqqpljllmpofmhmkmskdjfhslfkhaslfkhsalfkjhsaflksjahfsalkjfhssss
$ git --version

Error: Current working directory has a path longer than allowed for a
Win32 working directory.
Can't start native Windows application from here.
bash: /mingw64/bin/git: File name too long

@dscho
Copy link
Member

dscho commented Apr 11, 2020

@tboegi I fixed your comment, it was rendered all over the place, totally unreadable.

@rishabhBudhouliya
Copy link
Author

@tboegi I think if we create a potential working directory of char >260 before launching git, git.exe would fail to launch because Windows doesn't allow that. (without longpaths enabled)
So the long path problem can be tested by creating a directory structure such that the char limit is within the permissible limit and then the canonical remote repository name adds to it and makes it >260 char.

@dscho
Copy link
Member

dscho commented Mar 28, 2022

Closing as stale.

@dscho dscho closed this as completed Mar 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants