go-git / go-git

A highly extensible Git implementation in pure Go.
https://pkg.go.dev/github.com/go-git/go-git/v5
Apache License 2.0
6k stars 743 forks source link

Executable permission removed during Windows clone #771

Open zerok opened 1 year ago

zerok commented 1 year ago

Hi 🙂

When trying to clone a repository on Windows using PlainClone, files that have an executable flag set on Linux are checked out as non-executable. This also causes them to be marked as modified when running git status in that repository.

The only thing I could think of was to set core.filemode before running the native Git operations but IMO it would be better if go-git would preserve those permissions.

I've created a minimal example for this: https://github.com/zerok/mre-go-git-win-permissions

pjbgf commented 1 year ago

This is due to the way that go-billy/osfs works. I worked on osfs2 on a fork, key changes are here. You can use that by referring to github.com/fluxcd/go-billy/v5/osfs2.

github-actions[bot] commented 1 year ago

To help us keep things tidy and focus on the active tasks, we've introduced a stale bot to spot issues/PRs that haven't had any activity in a while.

This particular issue hasn't had any updates or activity in the past 90 days, so it's been labeled as 'stale'. If it remains inactive for the next 30 days, it'll be automatically closed.

We understand everyone's busy, but if this issue is still important to you, please feel free to add a comment or make an update to keep it active.

Thanks for your understanding and cooperation!

pjbgf commented 1 year ago

@zerok the new BoundOS from go-billy resolves this issue, as it does not make the changes to the underlying files as the default ChrootOS does:

path := "/tmp/repo"
wt := osfs.New(path, osfs.WithBoundOS())
dot := osfs.New(filepath.Join(path, git.GitDirName), osfs.WithBoundOS())
mibollma commented 2 months ago

@pjbgf Unfortunately it looks to me like this is still an issue in v5.12.0.

Maybe I misunderstand something, but the following code clones the repository successfully on Windows, but marks all bash scripts that have an executable flag set for the build pipeline as modified:

cloneOptions := &gogit.CloneOptions{
    URL:  url,
    Auth: sshKeys,
}

path := "./tmp/some-repo"
wt := osfs.New(path, osfs.WithBoundOS())
dot := osfs.New(filepath.Join(path, ".git"), osfs.WithBoundOS())
s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())

repository, err := gogit.Clone(s, wt, cloneOptions)
if err != nil {
    return nil, errors.Wrapf(err, "cloning repository %s failed", repository)
}