1package git
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8
9 "github.com/go-git/go-billy/v5/osfs"
10 "github.com/go-git/go-git/v5/plumbing/cache"
11 "github.com/go-git/go-git/v5/storage/filesystem"
12 "github.com/stretchr/testify/assert"
13 "github.com/stretchr/testify/require"
14)
15
16// For additional context: #1159.
17func TestIndexEntrySizeUpdatedForNonRegularFiles(t *testing.T) {
18 w := osfs.New(t.TempDir(), osfs.WithBoundOS())
19 dot, err := w.Chroot(GitDirName)
20 require.NoError(t, err)
21
22 s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())
23 r, err := Init(s, w)
24 require.NoError(t, err)
25 require.NotNil(t, r)
26
27 wt, err := r.Worktree()
28 require.NoError(t, err)
29 require.NotNil(t, wt)
30
31 file := "LICENSE"
32 f, err := w.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0o666)
33 require.NoError(t, err)
34 require.NotNil(t, f)
35
36 content := []byte(strings.Repeat("a\n", 1000))
37 _, err = f.Write(content)
38 require.NoError(t, err)
39 err = f.Close()
40 require.NoError(t, err)
41
42 _, err = wt.Add(file)
43 require.NoError(t, err)
44
45 _, err = wt.Commit("add file", &CommitOptions{})
46 require.NoError(t, err)
47
48 st, err := wt.StatusWithOptions(StatusOptions{Strategy: Preload})
49 require.NoError(t, err)
50 assert.Equal(t,
51 &FileStatus{Worktree: Unmodified, Staging: Unmodified},
52 st.File(file))
53
54 // Make the file not regular. The same would apply to a transition
55 // from regular file to symlink.
56 err = os.Chmod(filepath.Join(w.Root(), file), 0o777)
57 require.NoError(t, err)
58
59 f, err = w.OpenFile(file, os.O_APPEND|os.O_RDWR, 0o777)
60 require.NoError(t, err)
61 require.NotNil(t, f)
62
63 _, err = f.Write([]byte("\n\n"))
64 require.NoError(t, err)
65 err = f.Close()
66 require.NoError(t, err)
67
68 _, err = wt.Add(file)
69 assert.NoError(t, err)
70
71 // go-git's Status diverges from "git status", so this check does not
72 // fail, even when the issue is present. As at this point "git status"
73 // reports the unstaged file was modified while "git diff" would return
74 // empty, as the files are the same but the index has the incorrect file
75 // size.
76 st, err = wt.StatusWithOptions(StatusOptions{Strategy: Preload})
77 assert.NoError(t, err)
78 assert.Equal(t,
79 &FileStatus{Worktree: Unmodified, Staging: Modified},
80 st.File(file))
81
82 idx, err := wt.r.Storer.Index()
83 assert.NoError(t, err)
84 require.NotNil(t, idx)
85 require.Len(t, idx.Entries, 1)
86
87 // Check whether the index was updated with the two new line breaks.
88 assert.Equal(t, uint32(len(content)+2), idx.Entries[0].Size)
89}