fork of go-git with some jj specific features
at main 5.5 kB view raw
1package git 2 3import ( 4 "fmt" 5 "os" 6 "testing" 7 "time" 8 9 "github.com/go-git/go-git/v5/plumbing" 10 "github.com/go-git/go-git/v5/plumbing/cache" 11 "github.com/go-git/go-git/v5/plumbing/format/packfile" 12 "github.com/go-git/go-git/v5/plumbing/object" 13 "github.com/go-git/go-git/v5/storage/filesystem" 14 "github.com/go-git/go-git/v5/storage/memory" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/suite" 17 18 "github.com/go-git/go-billy/v5" 19 "github.com/go-git/go-billy/v5/memfs" 20 "github.com/go-git/go-billy/v5/osfs" 21 "github.com/go-git/go-billy/v5/util" 22 fixtures "github.com/go-git/go-git-fixtures/v4" 23) 24 25type BaseFixtureSuite struct { 26 fixtures.Suite 27} 28 29type BaseSuite struct { 30 suite.Suite 31 BaseFixtureSuite 32 Repository *Repository 33 34 cache map[string]*Repository 35} 36 37func (s *BaseSuite) SetupSuite() { 38 s.buildBasicRepository() 39 40 s.cache = make(map[string]*Repository) 41} 42 43func (s *BaseSuite) buildBasicRepository() { 44 f := fixtures.Basic().One() 45 s.Repository = s.NewRepository(f) 46} 47 48// NewRepository returns a new repository using the .git folder, if the fixture 49// is tagged as worktree the filesystem from fixture is used, otherwise a new 50// memfs filesystem is used as worktree. 51func (s *BaseSuite) NewRepository(f *fixtures.Fixture) *Repository { 52 var worktree, dotgit billy.Filesystem 53 if f.Is("worktree") { 54 r, err := PlainOpen(f.Worktree().Root()) 55 if err != nil { 56 panic(err) 57 } 58 59 return r 60 } 61 62 dotgit = f.DotGit() 63 worktree = memfs.New() 64 65 st := filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()) 66 67 r, err := Open(st, worktree) 68 if err != nil { 69 panic(err) 70 } 71 72 return r 73} 74 75// NewRepositoryWithEmptyWorktree returns a new repository using the .git folder 76// from the fixture but without a empty memfs worktree, the index and the 77// modules are deleted from the .git folder. 78func NewRepositoryWithEmptyWorktree(f *fixtures.Fixture) *Repository { 79 dotgit := f.DotGit() 80 err := dotgit.Remove("index") 81 if err != nil { 82 panic(err) 83 } 84 85 err = util.RemoveAll(dotgit, "modules") 86 if err != nil { 87 panic(err) 88 } 89 90 worktree := memfs.New() 91 92 st := filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()) 93 94 r, err := Open(st, worktree) 95 if err != nil { 96 panic(err) 97 } 98 99 return r 100} 101 102func (s *BaseSuite) NewRepositoryFromPackfile(f *fixtures.Fixture) *Repository { 103 h := f.PackfileHash 104 if r, ok := s.cache[h]; ok { 105 return r 106 } 107 108 storer := memory.NewStorage() 109 p := f.Packfile() 110 defer func() { _ = p.Close() }() 111 112 if err := packfile.UpdateObjectStorage(storer, p); err != nil { 113 panic(err) 114 } 115 116 err := storer.SetReference(plumbing.NewHashReference(plumbing.HEAD, plumbing.NewHash(f.Head))) 117 if err != nil { 118 panic(err) 119 } 120 121 r, err := Open(storer, memfs.New()) 122 if err != nil { 123 panic(err) 124 } 125 126 s.cache[h] = r 127 return r 128} 129 130func (s *BaseSuite) GetBasicLocalRepositoryURL() string { 131 fixture := fixtures.Basic().One() 132 return s.GetLocalRepositoryURL(fixture) 133} 134 135func (s *BaseSuite) GetLocalRepositoryURL(f *fixtures.Fixture) string { 136 return f.DotGit().Root() 137} 138 139func (s *BaseSuite) TemporalHomeDir() (path string, clean func()) { 140 home, err := os.UserHomeDir() 141 if err != nil { 142 panic(err) 143 } 144 145 fs := osfs.New(home) 146 relPath, err := util.TempDir(fs, "", "") 147 if err != nil { 148 panic(err) 149 } 150 151 path = fs.Join(fs.Root(), relPath) 152 clean = func() { 153 _ = util.RemoveAll(fs, relPath) 154 } 155 156 return 157} 158 159func (s *BaseSuite) TemporalFilesystem() (fs billy.Filesystem) { 160 tmpDir, err := os.MkdirTemp("", "") 161 if err != nil { 162 panic(err) 163 } 164 fs = osfs.New(tmpDir) 165 path, err := util.TempDir(fs, "", "") 166 if err != nil { 167 panic(err) 168 } 169 170 fs, err = fs.Chroot(path) 171 if err != nil { 172 panic(err) 173 } 174 175 return 176} 177 178type SuiteCommon struct { 179 suite.Suite 180} 181 182func TestSuiteCommon(t *testing.T) { 183 suite.Run(t, new(SuiteCommon)) 184} 185 186var countLinesTests = [...]struct { 187 i string // the string we want to count lines from 188 e int // the expected number of lines in i 189}{ 190 {"", 0}, 191 {"a", 1}, 192 {"a\n", 1}, 193 {"a\nb", 2}, 194 {"a\nb\n", 2}, 195 {"a\nb\nc", 3}, 196 {"a\nb\nc\n", 3}, 197 {"a\n\n\nb\n", 4}, 198 {"first line\n\tsecond line\nthird line\n", 3}, 199} 200 201func (s *SuiteCommon) TestCountLines() { 202 for i, t := range countLinesTests { 203 o := countLines(t.i) 204 s.Equal(t.e, o, fmt.Sprintf("subtest %d, input=%q", i, t.i)) 205 } 206} 207 208func AssertReferences(t *testing.T, r *Repository, expected map[string]string) { 209 for name, target := range expected { 210 expected := plumbing.NewReferenceFromStrings(name, target) 211 212 obtained, err := r.Reference(expected.Name(), true) 213 assert.NoError(t, err) 214 215 assert.Equal(t, expected, obtained) 216 } 217} 218 219func AssertReferencesMissing(t *testing.T, r *Repository, expected []string) { 220 for _, name := range expected { 221 _, err := r.Reference(plumbing.ReferenceName(name), false) 222 assert.Error(t, err) 223 assert.ErrorIs(t, err, plumbing.ErrReferenceNotFound) 224 } 225} 226 227func CommitNewFile(t *testing.T, repo *Repository, fileName string) plumbing.Hash { 228 wt, err := repo.Worktree() 229 assert.NoError(t, err) 230 231 fd, err := wt.Filesystem.Create(fileName) 232 assert.NoError(t, err) 233 234 _, err = fd.Write([]byte("# test file")) 235 assert.NoError(t, err) 236 237 err = fd.Close() 238 assert.NoError(t, err) 239 240 _, err = wt.Add(fileName) 241 assert.NoError(t, err) 242 243 sha, err := wt.Commit("test commit", &CommitOptions{ 244 Author: &object.Signature{ 245 Name: "test", 246 Email: "test@example.com", 247 When: time.Now(), 248 }, 249 Committer: &object.Signature{ 250 Name: "test", 251 Email: "test@example.com", 252 When: time.Now(), 253 }, 254 }) 255 assert.NoError(t, err) 256 257 return sha 258}