code.oscarkilo.com/klex-git/util/commit_test.go

..
commit.go
commit_test.go
committest/
files.go
files_test.go
paths.go
paths_test.go
root.go
root_test.go
run.go
run_test.go
package util

import (
  "os"
  "path"
  "reflect"
  "runtime"
  "testing"
)

func check(t *testing.T, err error) {
  if err != nil {
    t.Fatal(err)
  }
}

func makeGitRepo(t *testing.T) string {
  // Create an empty git repo in a temporary directory.
  dir := t.TempDir()
  os.Chdir(dir)
  RunOrDie("git", "init")
  RunOrDie("git", "config", "user.email", "[email protected]")
  RunOrDie("git", "config", "user.name", "Good User")

  // Add a go.mod dependency on this repo (klex-git).
  _, this_file, _, _ := runtime.Caller(0)
  os.Chdir(path.Dir(this_file))
  this_repo, _ := FindRoot()
  os.Chdir(dir)
  go_mod := path.Join(dir, "go.mod")
  check(t, AddLineTo(go_mod, "module klextest"))
  AddLineTo(go_mod, "go 1.21")
  AddLineTo(go_mod, "replace oscarkilo.com/klex-git => " + this_repo)
  RunOrDie("go", "get", "oscarkilo.com/klex-git")
  RunOrDie("git", "add", "go.mod")
  RunOrDie("git", "commit", "-m", "adds go.mod")

  // Add a pre-commit git hook that runs the committest binary.
  // It writes to .git/hooks/pre-commit.out.
  hook := path.Join(dir, ".git", "hooks", "pre-commit")
  AddLineTo(hook, "#!/bin/sh")
  AddLineTo(hook, "OUT=" + path.Join(path.Dir(hook), "pre-commit.out"))
  AddLineTo(hook, "go run oscarkilo.com/klex-git/util/committest >$OUT 2>&1")
  os.Chmod(hook, 0755)

  return dir
}

func parseCommitInfoFrom(dir string, t *testing.T) *CommitInfo {
  out_file := path.Join(dir, ".git", "hooks", "pre-commit.out")
  var info CommitInfo
  err := ReadJsonFile(out_file, &info)
  if err != nil {
    t.Errorf("error parsing JSON from %s: %v", out_file, err)
    return nil
  }
  return &info
}

func TestGetCommitInfo(t *testing.T) {
  repo := makeGitRepo(t)
  t.Logf("created Git repo at %s", repo)

  commit := func(touched_files ...string) *CommitInfo {
    // make a commit that touches the given files
    for _, file := range touched_files {
      err := AppendStringTo(path.Join(repo, file), "bubble and squeak\n")
      if err != nil {
        t.Fatalf("couldn't write to %s: %v", file, err)
      }
    }
    RunOrDie("git", "add", ".")
    RunOrDie("git", "commit", "-m", "test")
    return parseCommitInfoFrom(repo, t)
  }

  // makea a 3-file commit
  info := commit("foo.txt", "bar/baz.txt", "bar/qux.txt")
  golden := &CommitInfo{
    ChangedPaths: []string{"bar/baz.txt", "bar/qux.txt", "foo.txt"},
  }
  if !reflect.DeepEqual(info, golden) {
    t.Errorf("\nexpected %v; got %v", golden.DebugString(), info.DebugString())
  }
}