github.com/developest/gtm-enhanced@v1.0.4-0.20220111132249-cc80a3372c3f/util/test.go (about) 1 // Copyright 2016 Michael Schenk. All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package util 6 7 import ( 8 "fmt" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "runtime" 13 "strings" 14 "testing" 15 "time" 16 17 "github.com/libgit2/git2go" 18 ) 19 20 // TestRepo represents a test git repo used in testing 21 type TestRepo struct { 22 repo *git.Repository 23 test *testing.T 24 } 25 26 // Repo return a pointer to the git repository 27 func (t TestRepo) Repo() *git.Repository { 28 return t.repo 29 } 30 31 // NewTestRepo creates a new instance of TestRepo 32 func NewTestRepo(t *testing.T, bare bool) TestRepo { 33 path, err := ioutil.TempDir("", "gtm") 34 CheckFatal(t, err) 35 repo, err := git.InitRepository(path, bare) 36 CheckFatal(t, err) 37 return TestRepo{repo: repo, test: t} 38 } 39 40 // Seed creates test data for the git repo 41 func (t TestRepo) Seed() { 42 t.SaveFile("README", "", "foo\n") 43 treeOid := t.Stage("README") 44 t.Commit(treeOid) 45 } 46 47 // Remove deletes temp directories, files and git repo 48 func (t TestRepo) Remove() { 49 var repoPath string 50 51 if t.repo.IsBare() { 52 repoPath = t.repo.Path() 53 } else { 54 repoPath = t.repo.Workdir() 55 } 56 57 // assert it's in a temp dir just in case 58 if !strings.Contains(filepath.Clean(repoPath), filepath.Clean(os.TempDir())) { 59 CheckFatal(t.test, fmt.Errorf("Unable to remove, repoPath %s is not within %s", repoPath, os.TempDir())) 60 return 61 } 62 63 err := os.RemoveAll(repoPath) 64 if err != nil { 65 // this could be just the issue with Windows os.RemoveAll() and privileges, ignore 66 _, _ = fmt.Fprintln(os.Stderr, err) 67 } 68 t.repo.Free() 69 } 70 71 // Workdir return the working directory for the git repository 72 func (t TestRepo) Workdir() string { 73 return filepath.Clean(t.repo.Workdir()) 74 } 75 76 // Path return the git path for the git repository 77 func (t TestRepo) Path() string { 78 return filepath.Clean(t.repo.Path()) 79 } 80 81 // Stage adds files to staging for git repo 82 func (t TestRepo) Stage(files ...string) *git.Oid { 83 idx, err := t.repo.Index() 84 CheckFatal(t.test, err) 85 for _, f := range files { 86 err = idx.AddByPath(filepath.ToSlash(f)) 87 CheckFatal(t.test, err) 88 } 89 treeID, err := idx.WriteTreeTo(t.repo) 90 CheckFatal(t.test, err) 91 err = idx.Write() 92 CheckFatal(t.test, err) 93 return treeID 94 } 95 96 // Commit commits staged files 97 func (t TestRepo) Commit(treeID *git.Oid) *git.Oid { 98 loc, err := time.LoadLocation("America/Chicago") 99 CheckFatal(t.test, err) 100 sig := &git.Signature{ 101 Name: "Rand Om Hacker", 102 Email: "random@hacker.com", 103 When: time.Date(2013, 03, 06, 14, 30, 0, 0, loc), 104 } 105 106 headUnborn, err := t.repo.IsHeadUnborn() 107 CheckFatal(t.test, err) 108 var currentTip *git.Commit 109 110 if !headUnborn { 111 currentBranch, err := t.repo.Head() 112 CheckFatal(t.test, err) 113 currentTip, err = t.repo.LookupCommit(currentBranch.Target()) 114 CheckFatal(t.test, err) 115 } 116 117 message := "This is a commit\n" 118 tree, err := t.repo.LookupTree(treeID) 119 CheckFatal(t.test, err) 120 121 var commitID *git.Oid 122 if headUnborn { 123 commitID, err = t.repo.CreateCommit("HEAD", sig, sig, message, tree) 124 } else { 125 commitID, err = t.repo.CreateCommit("HEAD", sig, sig, message, tree, 126 currentTip) 127 } 128 CheckFatal(t.test, err) 129 130 return commitID 131 } 132 133 // SaveFile creates a file within the git repo project 134 func (t TestRepo) SaveFile(filename, subdir, content string) { 135 d := filepath.Join(t.Workdir(), subdir) 136 err := os.MkdirAll(d, 0700) 137 CheckFatal(t.test, err) 138 err = ioutil.WriteFile(filepath.Join(d, filename), []byte(content), 0644) 139 CheckFatal(t.test, err) 140 } 141 142 // FileExists Checks if a file exists in the repo folder 143 func (t TestRepo) FileExists(filename, subdir string) bool { 144 _, err := os.Stat(filepath.Join(subdir, filename)) 145 return !os.IsNotExist(err) 146 } 147 148 // Clone creates a clone of this repo 149 func (t TestRepo) Clone() TestRepo { 150 path, err := ioutil.TempDir("", "gtm") 151 CheckFatal(t.test, err) 152 153 r, err := git.Clone(t.repo.Path(), path, &git.CloneOptions{}) 154 CheckFatal(t.test, err) 155 156 return TestRepo{repo: r, test: t.test} 157 } 158 159 // AddSubmodule adds a submodule to the test repository 160 func (t TestRepo) AddSubmodule(url, path string) { 161 _, err := t.repo.Submodules.Add(url, path, true) 162 CheckFatal(t.test, err) 163 } 164 165 func (t TestRepo) remote(name string) *git.Remote { 166 remote, err := t.repo.Remotes.Lookup(name) 167 CheckFatal(t.test, err) 168 return remote 169 } 170 171 // Push to remote refs to remote 172 func (t TestRepo) Push(name string, refs ...string) { 173 if len(refs) == 0 { 174 refs = []string{"refs/heads/master"} 175 } 176 err := t.remote(name).Push(refs, nil) 177 CheckFatal(t.test, err) 178 } 179 180 // Fetch refs from remote 181 func (t TestRepo) Fetch(name string, refs ...string) { 182 if len(refs) == 0 { 183 refs = []string{"refs/heads/master"} 184 } 185 err := t.remote(name).Fetch(refs, nil, "") 186 CheckFatal(t.test, err) 187 } 188 189 // CheckFatal raises a fatal error if error is not nil 190 func CheckFatal(t *testing.T, err error) { 191 if err == nil { 192 return 193 } 194 195 // The failure happens at wherever we were called, not here 196 _, file, line, ok := runtime.Caller(1) 197 if !ok { 198 t.Fatalf("Unable to get caller") 199 } 200 t.Fatalf("Fail at %v:%v; %v", file, line, err) 201 }