From d84126ea75bc74d194e76d9ea3511d7d5e828bdd Mon Sep 17 00:00:00 2001 From: EdmondDantes21 Date: Wed, 14 Oct 2026 14:43:12 +0200 Subject: [PATCH] fix: persist restored file modes in UpdateIndex Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/clients/git/git.go | 2 +- internal/clients/git/git_test.go | 51 ++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/internal/clients/git/git.go b/internal/clients/git/git.go index 38d2b40..9a86ac9 100644 --- a/internal/clients/git/git.go +++ b/internal/clients/git/git.go @@ -458,7 +458,7 @@ func (s *Repo) UpdateIndex(idx *IndexOptions) error { e.Mode = fromEntry.Mode } } - return nil + return s.storer.SetIndex(toIdx) } func Clone(opts CloneOptions) (*Repo, error) { return clone(context.Background(), opts) diff --git a/internal/clients/git/git_test.go b/internal/clients/git/git_test.go index dccb46c..53a7e2e 100644 --- a/internal/clients/git/git_test.go +++ b/internal/clients/git/git_test.go @@ -5,9 +5,11 @@ import ( "errors" "fmt" "os" + "path" "strings" "testing" + "github.com/go-git/go-git/v5/plumbing/filemode" "github.com/go-git/go-git/v5/plumbing/object" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -336,3 +338,52 @@ func TestIsFuncInGitCommitHistory_complex(t *testing.T) { err = repo.Push("origin", "new-branch", false) require.NoError(t, err) } + +func TestCommitPreservesFileMode(t *testing.T) { + baseRepo := BaseSuite{} + baseRepo.BuildBasicRepository() + + writeFile := func(t *testing.T, repo *Repo, name string, perm os.FileMode) { + t.Helper() + require.NoError(t, repo.FS().MkdirAll(path.Dir(name), 0755)) + f, err := repo.FS().OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, perm) + require.NoError(t, err) + _, err = f.Write([]byte("#!/bin/sh\necho hi\n")) + require.NoError(t, err) + require.NoError(t, f.Close()) + } + + files := []string{"run.sh", "scripts/nested/run.sh"} + + origin, err := Clone(CloneOptions{URL: baseRepo.GetBasicLocalRepositoryURL(), Branch: "master"}) + require.NoError(t, err) + defer origin.Cleanup() + for _, name := range files { + writeFile(t, origin, name, 0755) + } + _, err = origin.Commit(".", "Add executables", &IndexOptions{}) + require.NoError(t, err) + + target, err := Clone(CloneOptions{URL: baseRepo.GetBasicLocalRepositoryURL(), Branch: "master"}) + require.NoError(t, err) + defer target.Cleanup() + for _, name := range files { + writeFile(t, target, name, 0644) + } + hash, err := target.Commit(".", "Copy executables", &IndexOptions{ + OriginRepo: origin, + FromPath: "/", + ToPath: "/", + }) + require.NoError(t, err) + + commit, err := target.repo.CommitObject(hash) + require.NoError(t, err) + tree, err := commit.Tree() + require.NoError(t, err) + for _, name := range files { + entry, err := tree.FindEntry(name) + require.NoError(t, err) + assert.Equal(t, filemode.Executable, entry.Mode, name) + } +}