From db559f123697163815f91801a4ed31d9b36be4f3 Mon Sep 17 00:00:00 2001 From: Nicholas openSUSE Software Engineer Date: Tue, 6 Aug 2024 13:30:19 -0300 Subject: plumbing: filemode, Remove check for setting size of .git/index file (#1159) * plumbing: filemode, Remove check for setting size of .git/index file on staging. Fixes #1003 Co-authored-by: Paulo Gomes --- worktree_status.go | 8 +++-- worktree_status_test.go | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 worktree_status_test.go diff --git a/worktree_status.go b/worktree_status.go index 6a0049c..f6b8282 100644 --- a/worktree_status.go +++ b/worktree_status.go @@ -559,9 +559,11 @@ func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbi return err } - if e.Mode.IsRegular() { - e.Size = uint32(info.Size()) - } + // The entry size must always reflect the current state, otherwise + // it will cause go-git's Worktree.Status() to divert from "git status". + // The size of a symlink is the length of the path to the target. + // The size of Regular and Executable files is the size of the files. + e.Size = uint32(info.Size()) fillSystemInfo(e, info.Sys()) return nil diff --git a/worktree_status_test.go b/worktree_status_test.go new file mode 100644 index 0000000..629ebd5 --- /dev/null +++ b/worktree_status_test.go @@ -0,0 +1,89 @@ +package git + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/go-git/go-billy/v5/osfs" + "github.com/go-git/go-git/v5/plumbing/cache" + "github.com/go-git/go-git/v5/storage/filesystem" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// For additional context: #1159. +func TestIndexEntrySizeUpdatedForNonRegularFiles(t *testing.T) { + w := osfs.New(t.TempDir(), osfs.WithBoundOS()) + dot, err := w.Chroot(GitDirName) + require.NoError(t, err) + + s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault()) + r, err := Init(s, w) + require.NoError(t, err) + require.NotNil(t, r) + + wt, err := r.Worktree() + require.NoError(t, err) + require.NotNil(t, wt) + + file := "LICENSE" + f, err := w.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0o666) + require.NoError(t, err) + require.NotNil(t, f) + + content := []byte(strings.Repeat("a\n", 1000)) + _, err = f.Write(content) + require.NoError(t, err) + err = f.Close() + require.NoError(t, err) + + _, err = wt.Add(file) + require.NoError(t, err) + + _, err = wt.Commit("add file", &CommitOptions{}) + require.NoError(t, err) + + st, err := wt.StatusWithOptions(StatusOptions{Strategy: Preload}) + require.NoError(t, err) + assert.Equal(t, + &FileStatus{Worktree: Unmodified, Staging: Unmodified}, + st.File(file)) + + // Make the file not regular. The same would apply to a transition + // from regular file to symlink. + err = os.Chmod(filepath.Join(w.Root(), file), 0o777) + require.NoError(t, err) + + f, err = w.OpenFile(file, os.O_APPEND|os.O_RDWR, 0o777) + require.NoError(t, err) + require.NotNil(t, f) + + _, err = f.Write([]byte("\n\n")) + require.NoError(t, err) + err = f.Close() + require.NoError(t, err) + + _, err = wt.Add(file) + assert.NoError(t, err) + + // go-git's Status diverges from "git status", so this check does not + // fail, even when the issue is present. As at this point "git status" + // reports the unstaged file was modified while "git diff" would return + // empty, as the files are the same but the index has the incorrect file + // size. + st, err = wt.StatusWithOptions(StatusOptions{Strategy: Preload}) + assert.NoError(t, err) + assert.Equal(t, + &FileStatus{Worktree: Unmodified, Staging: Modified}, + st.File(file)) + + idx, err := wt.r.Storer.Index() + assert.NoError(t, err) + require.NotNil(t, idx) + require.Len(t, idx.Entries, 1) + + // Check whether the index was updated with the two new line breaks. + assert.Equal(t, uint32(len(content)+2), idx.Entries[0].Size) +} -- cgit