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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

gix clone sets core.symlinks to false on Windows even if globally true #1353

Open
EliahKagan opened this issue May 6, 2024 · 1 comment
Open
Labels
acknowledged an issue is accepted as shortcoming to be fixed C-Windows Windows-specific issues help wanted Extra attention is needed

Comments

@EliahKagan
Copy link
Contributor

EliahKagan commented May 6, 2024

Current behavior 馃槸

On Windows, core.symlinks is intended to to false when not set, and in some installations is even set as false in the installation scope. Changing it, if done, is most often done in the global scope, such as by running git config --global core.symlinks true.

But gix clone does not honor this, instead checking out regular-file stubs rather than symlinks even on such a Windows system. gix clone furthermore sets core.symlinks to false explicitly in the newly cloned repository's .git/config. This happens even when the user is able to create symbolic links (without having to elevate privileges to do so via UAC or any other mechanism).

When -c core.symlinks=true is passed to gix, the clone will create the symlinks. But even in that case, gix sets a local false value for it in .git/config. Thus the problem appears to be that local value, which rightly overrides the global value, but is wrongly created in the first place (or at least is wrongly set to false even when it should not).

(This may or may not be readily checkable on CI without special effort, since the Windows runners for GitHub Actions customize core.symlinks, setting it to true for the installation, at installation time.)

Expected behavior 馃

When core.symlinks is set to true explicitly. gix clone should attempt to check out symbolic links as symbolic links rather than as regular files.

If falling back to checking out regular files is an intended behavior, then when core.symlinks is set to true this fallback should either be disabled or should be done only based on the failure of an actual attempt to create a symbolic link, or based on a precise check of the running process's abilities. (A precise pre-check done without attempting symlink creation would not be straightforward, since this is affected by multiple settings in Windows, and not all documentation covers all of them.)

This entails that gix should not always automatically set core.symlinks to false in newly cloned repositories' local configuration, but either should never do that, or (though this would be more complex) should only do it in scenarios where it is consistent with the existing Git configuration and user account abilities.

Git behavior

Git will check out symlinks as actual Windows symbolic links rather than as regular-file stubs, including in commands such as git clone.

Steps to reproduce 馃暪

Make the test repository

Create a repository with a symbolic link. For simplicity, it should be a symbolic link to a regular file in the repository, and thus not dangling/broken. (Besides simplicity, this also avoids confusion relating to the separate issue #1354.) This can be done with Git either on Windows or on a Unix-like system; I used Ubuntu, pushed to a remote, and cloned from a remote, to ensure that this bug was not specific to file:// remotes.

git init has-symlink
cd has-symlink
echo 'This is a regular file.' >target
ln -s target symlink
git commit -m 'Initial commit'

Alternatively, the has-symlink repository may be used. It was created that way (then minimal documentation was added in a second commit). It is used in the instructions below, which assume that either PowerShell or Git Bash is used.

Set core.symlinks globally and/or check that it is set

On a Windows system, run this command, at least if that has not already been done in your user account:

git config core.symlinks true

Checking that it is set in the global scope by running git config core.symlinks should show true.

Clone with gix clone and inspect the repository

Clone the repository with gix:

gix clone git@github.com:EliahKagan/has-symlink.git

The clone succeeds, but inspecting the checked out files reveals that symlink is actually a regular file rather than a symbolic link. Run:

ls -l has-symlink/symlink

In PowerShell, that shows output like:

    Directory: C:\Users\ek\src\has-symlink

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            5/6/2024  4:41 AM              6 symlink

To verify that gix set core.symlinks to false in the local configuration, inspect has-symlink/.git/config, or run this command, which outputs false:

git -C has-symlink config --local core.symlinks

Redo the clone with core.symlinks set in the command

To see how this differs from the behavior of gix when core.symlinks is provided on the command line, first delete the cloned repository:

  • In Git Bash, run: rm -rf has-symlink
  • In PowerShell, run: rm -r -fo has-symlink

Then try the clone again, but this time use the -c option to gix:

gix -c core.symlinks=true clone git@github.com:EliahKagan/has-symlink.git

Check the symlink entry again:

ls -l has-symlink/symlink

This time, that shows that it really is a symlink on disk. For example, in PowerShell, it looks like:

    Directory: C:\Users\ek\src\has-symlink

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
la---            5/6/2024  4:47 AM              0 symlink -> target

However, it has still set core.symlinks to false in the newly cloned repository's local configuration. This still outputs false:

git -C has-symlink config --local core.symlinks

Thus the reason -c behaved differently was that it overrode the wrongly set false value that gix placed at repository level. Furthermore, using -c is an insufficient workaround because it is still set otherwise locally (though unsetting it locally after cloning it that way should be a sufficient workaround until a fix is available).

Optionally, compare to the behavior of Git

Deleting the cloned repository again and cloning it with git clone rather than gix clone shows the expected behavior (and -c does not need to be used). After doing that, ls -l has-symlink/symlink shows thatsymlink is created as a symlink, and git -C has-symlink config --local core.symlinks shows no output (since git clone does not set a local value for core.symlinks when cloning).

Optionally, verify that other global configuration is honored

The problem is not that gix doesn't use global configuration in general. I verified this by temporarily breaking ssh for git and gix by running:

git config --global core.sshCommand foo   # Warning: breaks ssh in git until undone!

Then I attempted to clone a repository that I know I can otherwise clone with gix:

gix clone git@github.com:EliahKagan/gitoxide.git

As expected, this attempted to use the bogus foo implementation of SSH:

Error: Failed to invoke program "foo"

Caused by:
    program not found

To undo that, simply run:

git config --global --unset core.sshCommand
@Byron
Copy link
Owner

Byron commented May 6, 2024

The issue might originate here which is the only spot where it writes the local configuration.

It's a well-known limitation that in-memory configuration can't be written back yet, merely because I didn't work on the API for that yet, which also explains why it doesn't change.

However, this also means that gix_fs::Capabilities::probe() is unable to figure out that the filesystem supports symlinks on Windows, or in this particular situation.

Finally, another bug seems to be that it doesn't correctly pick up global configuration for this and is probably quite none-conforming with how Git does it.

@Byron Byron added help wanted Extra attention is needed acknowledged an issue is accepted as shortcoming to be fixed labels May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
acknowledged an issue is accepted as shortcoming to be fixed C-Windows Windows-specific issues help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants