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  }