github.com/nfisher/gitit@v0.0.7-0.20240131193748-bc8dd26542cc/cmd/helper_test.go (about)

     1  package cmd_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"github.com/go-git/go-git/v5"
     7  	"github.com/go-git/go-git/v5/config"
     8  	"github.com/go-git/go-git/v5/plumbing"
     9  	"github.com/go-git/go-git/v5/plumbing/object"
    10  	"net"
    11  	"net/http"
    12  	"net/http/cgi"
    13  	"os"
    14  	"os/exec"
    15  	"path/filepath"
    16  	"strings"
    17  	"testing"
    18  )
    19  
    20  func WorkTree(t *testing.T, repo *git.Repository) *git.Worktree {
    21  	t.Helper()
    22  	wt, err := repo.Worktree()
    23  	if err != nil {
    24  		t.Fatalf("call=WorkTree err=`%v`", err)
    25  	}
    26  	return wt
    27  }
    28  
    29  func CreateBareDir(t *testing.T) func() {
    30  	t.Helper()
    31  
    32  	pwd, err := os.Getwd()
    33  	if err != nil {
    34  		t.Fatalf("call=Getwd err=`%v`\n", err)
    35  	}
    36  
    37  	dir := t.TempDir()
    38  	err = os.Chdir(dir)
    39  	if err != nil {
    40  		t.Fatalf("call=Chdir err=`%v`\n", err)
    41  	}
    42  
    43  	return func() {
    44  		os.Chdir(pwd)
    45  		os.RemoveAll(dir)
    46  	}
    47  }
    48  
    49  func CreateRepo(t *testing.T) (*git.Repository, func()) {
    50  	t.Helper()
    51  
    52  	pwd, err := os.Getwd()
    53  	if err != nil {
    54  		t.Fatalf("call=Getwd err=`%v`\n", err)
    55  	}
    56  
    57  	dir := t.TempDir()
    58  	err = os.Chdir(dir)
    59  	if err != nil {
    60  		t.Fatalf("call=Chdir err=`%v`\n", err)
    61  	}
    62  
    63  	repo, err := git.PlainInit(dir, false)
    64  	if err != nil {
    65  		t.Fatalf("call=PlainInit err=`%v`\n", err)
    66  	}
    67  
    68  	return repo, func() {
    69  		os.Chdir(pwd)
    70  		os.RemoveAll(dir)
    71  	}
    72  }
    73  
    74  func Commit(t *testing.T, wt *git.Worktree, files map[string]string, msg string) {
    75  	t.Helper()
    76  	for n, c := range files {
    77  		AddFile(t, wt, n, c)
    78  	}
    79  
    80  	_, err := wt.Commit(msg, &git.CommitOptions{
    81  		Author: &object.Signature{Email: "nate@fisher.com", Name: "Nate Fisher"},
    82  	})
    83  	if err != nil {
    84  		t.Fatalf("call=Commit err=`%v`\n", err)
    85  	}
    86  }
    87  
    88  func CreateFile(t *testing.T, filename, contents string) {
    89  	t.Helper()
    90  	w, err := os.Create(filename)
    91  	if err != nil {
    92  		t.Fatalf("call=os.Create err=`%v`\n", err)
    93  	}
    94  	defer w.Close()
    95  
    96  	_, err = w.WriteString(contents)
    97  	if err != nil {
    98  		t.Fatalf("call=w.WriteString err=`%v`\n", err)
    99  	}
   100  }
   101  
   102  func AddFile(t *testing.T, wt *git.Worktree, filename, contents string) {
   103  	t.Helper()
   104  	w, err := os.Create(filename)
   105  	if err != nil {
   106  		t.Fatalf("call=os.Create err=`%v`\n", err)
   107  	}
   108  	defer w.Close()
   109  
   110  	_, err = w.WriteString(contents)
   111  	if err != nil {
   112  		t.Fatalf("call=w.WriteString err=`%v`\n", err)
   113  	}
   114  
   115  	_, err = wt.Add(filename)
   116  	if err != nil {
   117  		t.Fatalf("call=Add err=`%v`\n", err)
   118  	}
   119  }
   120  
   121  func InitialCommit(t *testing.T, repo *git.Repository) {
   122  	t.Helper()
   123  	wt, err := repo.Worktree()
   124  	if err != nil {
   125  		t.Fatalf("call=CreateBranch err=`%v`\n", err)
   126  	}
   127  
   128  	Commit(t, wt, map[string]string{
   129  		".gitignore": "*.sw?",
   130  	}, "Add .gitignore")
   131  }
   132  
   133  func CreateBranch(t *testing.T, repo *git.Repository, stack, branch string) {
   134  	t.Helper()
   135  	name := fmt.Sprintf("%s/%s", stack, branch)
   136  	wt, err := repo.Worktree()
   137  	if err != nil {
   138  		t.Fatalf("call=Worktree err=`%v`\n", err)
   139  	}
   140  
   141  	err = wt.Checkout(&git.CheckoutOptions{
   142  		Branch: plumbing.NewBranchReferenceName(name),
   143  		Create: true,
   144  	})
   145  	if err != nil {
   146  		t.Fatalf("call=Checkout err=`%v`\n", err)
   147  	}
   148  }
   149  
   150  func InitStack(t *testing.T, repo *git.Repository, stack, branch string) {
   151  	t.Helper()
   152  	CreateBranch(t, repo, stack, branch)
   153  }
   154  
   155  func SkipWIP(t *testing.T, runWip bool) {
   156  	t.Helper()
   157  	if !runWip {
   158  		t.Skip("WIP")
   159  	}
   160  }
   161  
   162  type server struct {
   163  	Port int
   164  	Root string
   165  	Repo *git.Repository
   166  }
   167  
   168  func (s *server) Address() string {
   169  	return fmt.Sprintf("http://localhost:%d", s.Port)
   170  }
   171  
   172  func LaunchServer(t *testing.T) (*server, func()) {
   173  	// inspired by go-git tests.
   174  	l, err := net.Listen("tcp", "localhost:0")
   175  	if err != nil {
   176  		t.Fatalf("call=Listen err=`%v`\n", err)
   177  	}
   178  	d := t.TempDir()
   179  
   180  	cmd := exec.Command("git", "--exec-path")
   181  	b, err := cmd.CombinedOutput()
   182  	if err != nil {
   183  		t.Fatalf("call=CombinedOutput err=`%v`\n", err)
   184  	}
   185  
   186  	backend := filepath.Join(strings.TrimSpace(string(b)), "git-http-backend")
   187  
   188  	srv := http.Server{
   189  		Handler: &cgi.Handler{
   190  			Path: backend,
   191  			Env:  []string{"GIT_HTTP_EXPORT_ALL=true", fmt.Sprintf("GIT_PROJECT_ROOT=%s", d)},
   192  		},
   193  	}
   194  
   195  	repo, err := git.PlainInit(d, true)
   196  	if err != nil {
   197  		t.Fatalf("call=PlainInit err=`%v`\n", err)
   198  	}
   199  
   200  	err = os.WriteFile(filepath.Join(d, "config"), []byte(configContents), os.ModePerm)
   201  	if err != nil {
   202  		t.Fatalf("call=WriteFile err=`%v`\n", err)
   203  	}
   204  
   205  	s := &server{
   206  		Root: d,
   207  		Port: l.Addr().(*net.TCPAddr).Port,
   208  		Repo: repo,
   209  	}
   210  
   211  	go func() {
   212  		srv.Serve(l)
   213  	}()
   214  
   215  	return s, func() {
   216  		srv.Shutdown(context.Background())
   217  	}
   218  }
   219  
   220  var configContents = `[core]
   221    bare = true
   222  [http]
   223    receivepack = true
   224  `
   225  
   226  func CreateRemote(t *testing.T, repo *git.Repository, s *server) {
   227  	_, err := repo.CreateRemote(&config.RemoteConfig{
   228  		Name: "origin",
   229  		URLs: []string{fmt.Sprintf("http://localhost:%d", s.Port)},
   230  	})
   231  	if err != nil {
   232  		t.Fatalf("call=CreateRemote err=`%v`\n", err)
   233  	}
   234  }
   235  
   236  func CreateThreeLayerStack(t *testing.T, repo *git.Repository) {
   237  	wt := WorkTree(t, repo)
   238  	InitialCommit(t, repo)
   239  	InitStack(t, repo, "kb3456", "001_migration")
   240  	Commit(t, wt, map[string]string{"001_create.sql": "SELECT 1;"}, "Add 001_create.sql")
   241  	InitStack(t, repo, "kb1234", "001_docs")
   242  	Commit(t, wt, map[string]string{"README.md": "Hello world"}, "Add README.md")
   243  	CreateBranch(t, repo, "kb1234", "002_api")
   244  	Commit(t, wt, map[string]string{"api.js": "function api() {}"}, "Add api.js")
   245  	CreateBranch(t, repo, "kb1234", "003_ui")
   246  	Commit(t, wt, map[string]string{"ui.js": "function ui() {}"}, "Add ui.js")
   247  }
   248  
   249  func PushBranch(t *testing.T, repo *git.Repository, branchName string) {
   250  	t.Helper()
   251  	spec := config.RefSpec(fmt.Sprintf("refs/heads/%[1]s:refs/heads/%[1]s", branchName))
   252  	err := repo.Push(&git.PushOptions{
   253  		RemoteName: "origin",
   254  		RefSpecs:   []config.RefSpec{spec},
   255  	})
   256  	if err != nil {
   257  		t.Fatalf("call=Push err=`%v`\n", err)
   258  	}
   259  }
   260  
   261  func CheckoutBranch(t *testing.T, wt *git.Worktree, name string) {
   262  	t.Helper()
   263  	err := wt.Checkout(&git.CheckoutOptions{
   264  		Branch: plumbing.NewBranchReferenceName(name),
   265  	})
   266  	if err != nil {
   267  		t.Fatalf("call=Checkout err=`%v`\n", err)
   268  	}
   269  }
   270  
   271  func Chdir(t *testing.T, wt *git.Worktree) {
   272  	t.Helper()
   273  
   274  	err := os.Chdir(wt.Filesystem.Root())
   275  	if err != nil {
   276  		t.Fatalf("call=Chdir err=`%v`\n", err)
   277  	}
   278  }
   279  
   280  func CloneRepo(t *testing.T, s *server, name string) (*git.Repository, func()) {
   281  	t.Helper()
   282  
   283  	pwd, err := os.Getwd()
   284  	if err != nil {
   285  		t.Fatalf("call=Getwd err=`%v`\n", err)
   286  	}
   287  
   288  	dir := t.TempDir()
   289  	err = os.Chdir(dir)
   290  	if err != nil {
   291  		t.Fatalf("call=Chdir err=`%v`\n", err)
   292  	}
   293  
   294  	repo, err := git.PlainClone(dir, false, &git.CloneOptions{
   295  		RemoteName:    "origin",
   296  		URL:           s.Address(),
   297  		ReferenceName: plumbing.ReferenceName("refs/heads/" + name),
   298  	})
   299  	if err != nil {
   300  		t.Fatalf("call=PlainClone err=`%v`\n", err)
   301  	}
   302  
   303  	return repo, func() {
   304  		os.Chdir(pwd)
   305  		os.RemoveAll(dir)
   306  	}
   307  }
   308  
   309  func FetchRefs(t *testing.T, repo *git.Repository, refs string) {
   310  	t.Helper()
   311  	spec := config.RefSpec(fmt.Sprintf("refs/heads/%[1]s:refs/heads/%[1]s", refs))
   312  	err := repo.Fetch(&git.FetchOptions{
   313  		RemoteName: "origin",
   314  		RefSpecs:   []config.RefSpec{spec},
   315  	})
   316  	if err != nil {
   317  		t.Fatalf("call=Fetch err=`%v`\n", err)
   318  	}
   319  }