137c05e802
This change introduces the file deprecated.go, which contains any constants, functions, and types that are slated to be deprecated in the next major release. These symbols are deprecated because they refer to old spellings in pre-1.0 libgit2. This also makes the build be done with the `-DDEPRECATE_HARD` flag to avoid regressions. This, together with [gorelease](https://godoc.org/golang.org/x/exp/cmd/gorelease)[1] should make releases safer going forward. 1: More information about how that works at https://go.googlesource.com/exp/+/refs/heads/master/apidiff/README.md
199 lines
4.6 KiB
Go
199 lines
4.6 KiB
Go
package git
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"reflect"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestStash(t *testing.T) {
|
|
repo := createTestRepo(t)
|
|
defer cleanupTestRepo(t, repo)
|
|
|
|
prepareStashRepo(t, repo)
|
|
|
|
sig := &Signature{
|
|
Name: "Rand Om Hacker",
|
|
Email: "random@hacker.com",
|
|
When: time.Now(),
|
|
}
|
|
|
|
stash1, err := repo.Stashes.Save(sig, "First stash", StashDefault)
|
|
checkFatal(t, err)
|
|
|
|
_, err = repo.LookupCommit(stash1)
|
|
checkFatal(t, err)
|
|
|
|
b, err := ioutil.ReadFile(pathInRepo(repo, "README"))
|
|
checkFatal(t, err)
|
|
if string(b) == "Update README goes to stash\n" {
|
|
t.Errorf("README still contains the uncommitted changes")
|
|
}
|
|
|
|
if !fileExistsInRepo(repo, "untracked.txt") {
|
|
t.Errorf("untracked.txt doesn't exist in the repo; should be untracked")
|
|
}
|
|
|
|
// Apply: default
|
|
|
|
opts, err := DefaultStashApplyOptions()
|
|
checkFatal(t, err)
|
|
|
|
err = repo.Stashes.Apply(0, opts)
|
|
checkFatal(t, err)
|
|
|
|
b, err = ioutil.ReadFile(pathInRepo(repo, "README"))
|
|
checkFatal(t, err)
|
|
if string(b) != "Update README goes to stash\n" {
|
|
t.Errorf("README changes aren't here")
|
|
}
|
|
|
|
// Apply: no stash for the given index
|
|
|
|
err = repo.Stashes.Apply(1, opts)
|
|
if !IsErrorCode(err, ErrorCodeNotFound) {
|
|
t.Errorf("expecting GIT_ENOTFOUND error code %d, got %v", ErrorCodeNotFound, err)
|
|
}
|
|
|
|
// Apply: callback stopped
|
|
|
|
opts.ProgressCallback = func(progress StashApplyProgress) error {
|
|
if progress == StashApplyProgressCheckoutModified {
|
|
return fmt.Errorf("Stop")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
err = repo.Stashes.Apply(0, opts)
|
|
if err.Error() != "Stop" {
|
|
t.Errorf("expecting error 'Stop', got %v", err)
|
|
}
|
|
|
|
// Create second stash with ignored files
|
|
|
|
os.MkdirAll(pathInRepo(repo, "tmp"), os.ModeDir|os.ModePerm)
|
|
err = ioutil.WriteFile(pathInRepo(repo, "tmp/ignored.txt"), []byte("Ignore me\n"), 0644)
|
|
checkFatal(t, err)
|
|
|
|
stash2, err := repo.Stashes.Save(sig, "Second stash", StashIncludeIgnored)
|
|
checkFatal(t, err)
|
|
|
|
if fileExistsInRepo(repo, "tmp/ignored.txt") {
|
|
t.Errorf("tmp/ignored.txt should not exist anymore in the work dir")
|
|
}
|
|
|
|
// Stash foreach
|
|
|
|
expected := []stash{
|
|
{0, "On master: Second stash", stash2.String()},
|
|
{1, "On master: First stash", stash1.String()},
|
|
}
|
|
checkStashes(t, repo, expected)
|
|
|
|
// Stash pop
|
|
|
|
opts, _ = DefaultStashApplyOptions()
|
|
err = repo.Stashes.Pop(1, opts)
|
|
checkFatal(t, err)
|
|
|
|
b, err = ioutil.ReadFile(pathInRepo(repo, "README"))
|
|
checkFatal(t, err)
|
|
if string(b) != "Update README goes to stash\n" {
|
|
t.Errorf("README changes aren't here")
|
|
}
|
|
|
|
expected = []stash{
|
|
{0, "On master: Second stash", stash2.String()},
|
|
}
|
|
checkStashes(t, repo, expected)
|
|
|
|
// Stash drop
|
|
|
|
err = repo.Stashes.Drop(0)
|
|
checkFatal(t, err)
|
|
|
|
expected = []stash{}
|
|
checkStashes(t, repo, expected)
|
|
}
|
|
|
|
type stash struct {
|
|
index int
|
|
msg string
|
|
id string
|
|
}
|
|
|
|
func checkStashes(t *testing.T, repo *Repository, expected []stash) {
|
|
var actual []stash
|
|
|
|
repo.Stashes.Foreach(func(index int, msg string, id *Oid) error {
|
|
stash := stash{index, msg, id.String()}
|
|
if len(expected) > len(actual) {
|
|
if s := expected[len(actual)]; s.id == "" {
|
|
stash.id = "" // don't check id
|
|
}
|
|
}
|
|
actual = append(actual, stash)
|
|
return nil
|
|
})
|
|
|
|
if len(expected) > 0 && !reflect.DeepEqual(expected, actual) {
|
|
// The failure happens at wherever we were called, not here
|
|
_, file, line, ok := runtime.Caller(1)
|
|
if !ok {
|
|
t.Fatalf("Unable to get caller")
|
|
}
|
|
t.Errorf("%v:%v: expecting %#v\ngot %#v", path.Base(file), line, expected, actual)
|
|
}
|
|
}
|
|
|
|
func prepareStashRepo(t *testing.T, repo *Repository) {
|
|
seedTestRepo(t, repo)
|
|
|
|
err := ioutil.WriteFile(pathInRepo(repo, ".gitignore"), []byte("tmp\n"), 0644)
|
|
checkFatal(t, err)
|
|
|
|
sig := &Signature{
|
|
Name: "Rand Om Hacker",
|
|
Email: "random@hacker.com",
|
|
When: time.Now(),
|
|
}
|
|
|
|
idx, err := repo.Index()
|
|
checkFatal(t, err)
|
|
err = idx.AddByPath(".gitignore")
|
|
checkFatal(t, err)
|
|
treeID, err := idx.WriteTree()
|
|
checkFatal(t, err)
|
|
err = idx.Write()
|
|
checkFatal(t, err)
|
|
|
|
currentBranch, err := repo.Head()
|
|
checkFatal(t, err)
|
|
currentTip, err := repo.LookupCommit(currentBranch.Target())
|
|
checkFatal(t, err)
|
|
|
|
message := "Add .gitignore\n"
|
|
tree, err := repo.LookupTree(treeID)
|
|
checkFatal(t, err)
|
|
_, err = repo.CreateCommit("HEAD", sig, sig, message, tree, currentTip)
|
|
checkFatal(t, err)
|
|
|
|
err = ioutil.WriteFile(pathInRepo(repo, "README"), []byte("Update README goes to stash\n"), 0644)
|
|
checkFatal(t, err)
|
|
|
|
err = ioutil.WriteFile(pathInRepo(repo, "untracked.txt"), []byte("Hello, World\n"), 0644)
|
|
checkFatal(t, err)
|
|
}
|
|
|
|
func fileExistsInRepo(repo *Repository, name string) bool {
|
|
if _, err := os.Stat(pathInRepo(repo, name)); err != nil {
|
|
return false
|
|
}
|
|
return true
|
|
}
|