gitoxide icon indicating copy to clipboard operation
gitoxide copied to clipboard

Fetching a Repository with special branch names breaks on Windows

Open calyptobai opened this issue 2 years ago • 7 comments

Current behavior 😯

Calling fetch_only on Windows for a repository with a branch named foo<1.0 fails due to:

Fetch(UpdateRefs(EditReferences(FileTransactionCommit(DeleteReference { full_name: "refs/remotes/origin/foo<1.0", err: Os { code: 123, kind: InvalidFilename, message: "The filename, directory name, or volume label syntax is incorrect." } }))))

Expected behavior 🤔

I would expect this to work on Windows, given that foo<1.0 is a well-formed name according to git's ref naming rules.

Steps to reproduce 🕹

  1. Use Windows
  2. Try to PrepareFetch and fetch_only for https://github.com/calyptobai/gix-fetch-win-fail.git

calyptobai avatar Oct 09 '23 23:10 calyptobai

Thanks for reporting!

git seems to be able to do it by writing packed-refs right away.

# pack-refs with: peeled fully-peeled sorted 
2f3c410f1900acbf8bb3d29f008d1f9b57103053 refs/remotes/origin/foo<1.0
2f3c410f1900acbf8bb3d29f008d1f9b57103053 refs/remotes/origin/main

gix also does that which works around issues around case-insensitivity for example, but that doesn't seem to kick in here. Instead it tries to create a file with such a name and fails.

The goal here would to figure out why it's not writing straight to packed refs.

Byron avatar Oct 10 '23 06:10 Byron

A quick investigation shows that…

So in this case, it's probably these the last two points to adjust and investigate.

Byron avatar Oct 10 '23 07:10 Byron

I didn't test this prior to the changes in #1374, but currently the failure, if tested with gix, is that it attempts to write a reflog for that remote branch to a file of the same name:

C:\Users\ek\src> gix clone https://github.com/calyptobai/gix-fetch-win-fail.git
 14:39:23 indexing done 3.0 objects in 0.00s (2.1k objects/s)
 14:39:23 decompressing done 729B in 0.00s (456.3KB/s)
 14:39:23     Resolving done 3.0 objects in 0.05s (58.0 objects/s)
 14:39:23      Decoding done 729B in 0.05s (14.2KB/s)
 14:39:23 writing index file done 1.2KB in 0.00s (5.3MB/s)
 14:39:23  create index file done 3.0 objects in 0.06s (49.0 objects/s)
 14:39:23          read pack done 626B in 0.06s (9.9KB/s)
Error: Failed to update references to their new position to match their remote locations

Caused by:
    0: The reflog could not be created or updated
    1: Could not open reflog file at "gix-fetch-win-fail\\.git\\logs\\refs\\remotes\\origin\\foo<1.0" for appending
    2: The filename, directory name, or volume label syntax is incorrect. (os error 123)

EliahKagan avatar Jul 29 '24 18:07 EliahKagan

It's amazing that Git can do it - or does it just ignore the reflog maybe? If so, and it's my guess that it does, gix could do the same.

Byron avatar Jul 29 '24 19:07 Byron

It's amazing that Git can do it - or does it just ignore the reflog maybe?

Yeah, with git I don't see any file for it there.

(Attempting to switch to the branch with git does fail, as I would expect, due to an attempt to create a lockfile that has the branch name as its basename.)

EliahKagan avatar Jul 29 '24 19:07 EliahKagan

I should acknowledge that this may not be all that must change. We also want to be able to fetch again.

C:\Users\ek\src\gix-fetch-win-fail [main ≡]> gix fetch
Error: The ref file ".\\.git\\refs\\remotes\\origin\\foo<1.0" could not be read in full

Caused by:
    The filename, directory name, or volume label syntax is incorrect. (os error 123)

There, the problem is not related to a log. This may be considered more strongly to resemble the original problem description. git fetch succeeds with no output. (git diff can also compare to origin/foo<1.0, and it is shown in the output of git log, which also accepts it as an argument.)

EliahKagan avatar Jul 29 '24 19:07 EliahKagan

Great! This is quite actionable, even though it's not trivial to implement. After all, I wonder if gitoxide should generally treat the reflog as optional. Maybe Git only treats the creation as optional though, or maybe it's a Windows-only fix?

With more research to understand Git as baseline, one can probably make a good decision there.

But with the comment above, it's once again clear that this is more work to get right, probably in many different places then. And with that, I once more wonder if Git has a clever solution for this to also 'do the right thing' instead of just ignoring errors.

Byron avatar Jul 29 '24 19:07 Byron